A Comprehensive Guide to Git Merge

0
15

Table of Contents

Introduction

Let’s say you’re experimenting with a side feature to see where it goes, and once it works, you decide to merge it into your main branch. The only issue is several commits and changes have been made to the main branch since you started experimenting. How do you combine these two branches into a single commit?

This is where Git merge comes in. You can use Git merge to combine two (or more) development histories into a single branch. Git merge has a ton of use cases and is an essential git command for any developer.

With git merge, you can integrate all of the commits made to your feature branch into the master branch in a single commit.

Continue reading to learn more about how git merge works, how to handle git merge conflicts, and other frequently asked questions.

How Does the Git Merge Command Work?

When you use Git merge, remember that a branch is simply a pointer pointing to a single commit. At a granular level, you are merging commits, not branches, but it’s easier to think of this command as merging two branches because commits always have branch names. Git creates an entirely new commit when merging that combines the contributions of both branches.

So what’s going on behind the scenes? What internal logic is Git using?

Git first locates the common ancestor or merge base, which is the first commit reachable from both branches. Then Git calculates two diffs, from the merge base to each branch. To create a merge commit, Git applies these two diffs to the merge base.

There are two primary methods that Git merge can use, the fast forward method and the three-way merge, both of which have their pros and cons.

Fast-forward Merge

Git uses the fast-forward merge method if no new changes have been made on your main branch since your feature branch was first created. This means there is no possibility of merge conflicts, and Git can just move your main branch’s tip to the end of your feature branch. Fast forward merges do not create a new merge commit.

Three-Way Merge

Git merge may also merge the source branch to the target branch using the 3-way merge algorithm. This merge method is based on three different commits:

Which commit is the common ancestor of both branches? Which commit is at the tip of the master branch? Which commit is at the tip of the secondary (experimental, feature, etc) branch?

Git identifies these three commits using snapshots. Git compares the common ancestor to each of the tip commits. If any files are edited in one branch but not the other, this change is automatically resolved as the intended file change. For example, on line 45, the common ancestor has a simple print function:

Print(“The application is working”)

This line was edited by John Smith but was not edited by Jane Doe. John Smith’s line 45 reads:

Print(“The application is working as intended.”)

Git assumes that the most updated version of line 45, changed by John Smith, is correct. The new master merge will have this change.

What are Git Merge Conflicts

A merge conflict will occur when Git isn’t able to sort out the changes between two commits automatically, likely due to two developers modifying the same line of code.

If the two branches you’re trying to merge both changed the same part of the same file, Git won’t be able to figure out which version to use. When such a situation occurs, it stops right before the merge commit so that you can resolve the conflicts manually. Let’s continue the three-way merge example from above to understand merge conflicts.

Imagine both Jane Doe and John Smith had changed line 45. A reminder that John Smith edited the line to read:

Print(“The application is working as intended.”)

But Jane Doe changed line 45 to read:

Print(“The application is NOT working as intended.”)

When Git reaches this line, it won’t be able to reconcile these changes. Because the file has been edited by two contributors or multiple times since the original file, Git can’t make the call about which version to use. This creates a merge conflict. Merge conflicts must be manually reconciled by the developer to resolve the conflict.

How to Use Git Merge: Step-By-Step Instructions

Follow these step-by-step instructions to walk through the git merge workflow and learn how to resolve merge conflicts as you go.

Start by using git status to double-check that the merge-receiving branch is the intended branch. If HEAD is not pointing to the correct branch, use git checkout to switch to the intended receiving branch.

$ git status
On branch master

Ensure that both the merging and receiving branches are updated with the latest commits from the remote repository by using the git fetch command:

$ git fetch origin
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done. 
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
unpacking objects: 100% (3/3), done.
from https//github.com/test/git-example
* [new branch ] some-new-feature -> origin/some-new-feature	

Now you’re ready to start merging with the git merge command. Notice in this example that Git is merging using the fast-forward method:

$ git merge
Updating a1b2c3d4 . . 3c73b1e
Fast-forward
Alphabet.txt | +++ -
Prime-numbers.txt | +++++ -
2 files changed, 8 insertions (+), 2 deletions (-)

How to Fix Git Merge Conflicts

If Git encounters a merge conflict while merging, you’ll see an output that is very similar to this one:

$ git merge
Auto-merging words.md
CONFLICT (content): Merge conflict in words.md
Recorded preimage for ‘words.md’
Automatic merge failed; fix conflicts and then commit the result 

Following a failed merge due to merging conflicts, you can review all of the unmerged paths by using git status:

$ git status
On branch main
You have unmerged paths
(fix conflicts and run ‘git commit’)

Unmerged paths:
(use “git add <file>...” to mark resolution)

Both modified: words.md

This tells you exactly which files need to be reviewed and manually reconciled.

Now it’s time to individually open, inspect, and resolve each merge conflict. Thankfully in this example, it’s just one conflict. This process may be time-consuming for larger projects if there are many merge conflicts.

Each merge conflict file will have new visual markers added by Git to direct you. Each marker will specify which lines need your attention. These visual markers are:

  • ======= is the center point of the conflict; everything before this point exists in the current main branch. While everything after this point exists in the merging branch.

  • <<<<<<< marks the starting point of the merger conflict

  • >>>>>>> marks the ending point of the merger conflict

Now let’s look at the words.md file to see what the merge conflict looks like:

$ words.md
<<<<<<< HEAD
## Beginners Guide to Git
Today, you will learn all the information you need if you’re brand new to using Git.
=======
## Beginners Guide to Git: Introducing Version Control & Repositories 	
Within this guide, you’ll learn the basics of version control, what repositories are, and how to get started with your very own repository. 
>>>>>>>

At this point, you can choose to keep either side of the conflict or combine them together to make something completely new. Once you’ve edited the file, save it and continue to the next step.

Next, you’ll continue with the same workflow you’ve always used when making changes in Git. You need to stage the changes using git add:

$ git add words.md

Finally, you can create a new commit using git commit:

$ git commit -m ‘enter your commit message here’

This creates the merge commit, and you are done! You have successfully merged two branches and resolved a merge conflict in the process.

Git Merge Subcommands

Git merge includes a handful of useful subcommands to help direct your workflow.

  • Git merge –abort – after a merge results in merge conflicts, you can use –abort to stop the merge process and attempt to recreate the pre-merge state
  • Git merge –commit – overrides the –no-commit command to force Git to merge and automatically commit
  • Git merge –no-commit – this command merges the branches but stops before creating a merge commit. Useful for checking the results before committing.

What is the difference between Git Merge and Git Pull?

Git merge is a base command, whereas git pull is the combination of multiple commands into a single step. Git pull combines `git fetch` and `git merge` into a single command.

At first glance, it may be difficult to ascertain how git merge and git pull aren’t the same commands. Both git merge and git pull are used to merge commits from one branch to another.

Git has many of these overlapping commands, which are used to provide flexibility and multiple avenues to reach the same result. Git merge stands on its own; Git pull first uses Git fetch to download commits and files from the remote to your local branch and follows up with a merge.

Git pull fetches and downloads updates from a remote repository, so the local repository matches the remote repository. Git pull then merges and creates a new commit. Git pull is ideal if you know the exact content being fetched and merged. Otherwise, it’s a safer and better work practice to first run git fetch to review the commits and changes before using git merge.

What is the difference between merge and rebase?

Git merge and Git rebase are both Git commands that allow you to combine two branches, but their methods are different. With Git merge, a source branch is integrated with a target branch. The source branch is not altered, leaving it as a reference if needed for later use.

With Git rebase, two branches are combined into one single branch, with no history of the preexisting source branch. Rebase is useful to streamline a complex version history, while Git merge is useful to preserve the complete history and maintain branch context.

Frequently Asked Questions

  1. Is git merge local or remote?

Git merges occur locally, but you can merge two branches that are completely local, or you can use git fetch to download updates from a remote master branch and then merge these changes to your local branch.

  1. Is push the same as merge?

no git push is not the same as the git merge command. Merging occurs locally while pushing acts on a remote repository. Often git push is used after merging to update the remote repository.

  1. Do I have to commit after merging?

No, you do not have to commit after a merge because git merge automatically creates a merge commit for you. If you don’t want Git to auto-commit, you can use the –no-commit subcommand.

Summary

You’ve learned about the two merging methods, fast forward merge and three-way merge, and how to resolve merge conflicts. Over the course of your career as a developer, you will inevitably run into scenarios where Git merge will come in handy. Now you have all the tools to use git merge with confidence, you can start implementing it in your git workflow.

Git merge is a helpful command to add to your toolbox. Using merge, you’ll be able to work on code bases that require you to combine changes made across different branches. More importantly, it will help you become a more collaborative developer.

Next Steps

If you’re interested in learning more about how Git works under the hood, check out our Baby Git Guidebook for Developers, which dives into Git’s code in an accessible way. We wrote it for curious developers to learn how Git works at the code level. To do this we documented the first version of Git’s code and discussed it in detail.

We hope you enjoyed this post! Feel free to shoot me an email at jacob@initialcommit.io with any questions or comments.

References

  1. Git SCM Docs, git fetch – https://git-scm.com/docs/git-merge

Source

LEAVE A REPLY

Please enter your comment!
Please enter your name here