This article was converted by SimpRead, original source git-scm.com
Let’s look at a simple example of branch creation and merging. In actual work, you might use a similar workflow. You will go through the following steps:
Let’s look at a simple example of branch creation and merging. In actual work, you might use a similar workflow. You will go through the following steps:
-
Develop a website.
-
Create a branch to implement a new user requirement.
-
Work on this branch.
At this moment, you suddenly get a call about a serious issue that requires an urgent fix. You will handle it in the following way:
-
Switch to your production branch.
-
Create a new branch for this urgent task and fix it there.
-
After passing the tests, switch back to the production branch, merge this hotfix branch, and then push the changes to the production branch.
-
Switch back to your original working branch and continue working.
Creating a New Branch
First, assume you are working on your project, and you already have some commits on the master branch.
![]()
Figure 18. A simple commit history
Now, you have decided to address issue #53 in your company’s issue tracking system. To create a new branch and simultaneously switch to it, you can run the git checkout command with the -b parameter:
$ git checkout -b iss53
Switched to a new branch "iss53"
This is shorthand for the following two commands:
$ git branch iss53
$ git checkout iss53
![]()
Figure 19. Creating a new branch pointer
You continue to work on issue #53 and make some commits. In this process, the iss53 branch advances, because you have checked out this branch (meaning your HEAD pointer now points to the iss53 branch).
$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
![]()
Figure 20. The iss53 branch moving forward with work progress
Now you receive that call about an urgent issue waiting for your fix. Thanks to Git, you don’t have to mix this urgent issue with the modifications on iss53, nor do you need to spend a lot of effort reverting changes related to issue #53 and then adding changes for the urgent fix before committing them to the production branch. All you need to do is switch back to the master branch.
However, before doing so, be aware of any uncommitted changes in your working directory and staging area. They may conflict with the branch you are about to check out and prevent Git from switching branches. The best practice is to keep a clean state before switching branches. There are ways to work around this problem (i.e., stashing and commit amending), which we will see introduced in Stashing and Cleaning. Now, assume you have committed all your changes, and you can switch back to the master branch:
$ git checkout master
Switched to branch 'master'
At this point, your working directory looks exactly like it did before starting issue #53, so you can focus on fixing the urgent issue. Remember: when you switch branches, Git resets your working directory to look exactly like the latest commit on that branch. Git will automatically add, delete, and modify files to ensure your working directory matches the last commit on the branch.
Next, you want to fix this urgent issue. Let’s create a hotfix branch and work on it until the problem is resolved:
$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
1 file changed, 2 insertions(+)
![]()
Figure 21. Emergency issue branch hotfix based on master
You can run your tests to ensure your changes are correct, then merge the hotfix branch back into your master branch for deployment online. You can use the git merge command to achieve this:
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
When merging, you might notice the term “fast-forward.” Since the commit C4 pointed to by the branch hotfix you want to merge is a direct successor of your current commit C2, Git will simply move the pointer forward. In other words, when you try to merge two branches, if one branch’s history is ahead of the other, Git will just advance the pointer (move it forward) because there are no divergent changes to resolve — this is called a “fast-forward.”
Now, the latest changes are included in the master branch commit snapshot, and you can proceed to release the fix.
![]()
Figure 22. master fast-forwarded to hotfix
After releasing this urgent fix, you are ready to return to your interrupted work. However, you should first delete the hotfix branch since it is no longer needed — the master branch already points to the same commit. You can delete the branch using the git branch command with the -d option:
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
Now you can switch back to your working branch, the one for issue #53 (the iss53 branch), to continue your work.
$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
![]()
Figure 23. Continuing work on the iss53 branch
The work done on the hotfix branch has not been included in the iss53 branch. If you want to pull in the changes made in the hotfix branch, you can merge the master branch into iss53 using git merge master, or you can wait until your iss53 branch completes its task, then merge it back into master.
Merging Branches
Assuming you have fixed issue #53 and want to merge your work into the master branch. To do this, you need to merge the iss53 branch into master, which is similar to what you did with the hotfix branch. Just check out the branch you want to merge into and run git merge:
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
This looks a bit different from when you merged the hotfix branch. In this case, your development history diverged earlier. Because the commits on the master branch are not a direct ancestor of those on iss53, Git has to work harder. In this scenario, Git uses the snapshots at the tips of both branches (C4 and C5) and their common ancestor (C2) to perform a simple three-way merge.
![]()
Figure 24. Three snapshots involved in a typical merge
Unlike simply advancing the branch pointer, Git creates a new snapshot as the result of the three-way merge and automatically creates a new commit pointing to it. This is called a merge commit, and its distinguishing feature is that it has more than one parent commit.
![]()
Figure 25. A merge commit
Since your changes have been merged, the iss53 branch is no longer needed. Now you can close this task in the issue tracking system and delete the branch.
Merging Branches with Conflicts
Sometimes, merges don’t go so smoothly. If you have made different modifications to the same part of the same file on two different branches, Git won’t be able to merge them cleanly. If your changes for issue #53 and the changes made on the hotfix branch both involve the same part of a file, a merge conflict will occur when merging them:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
At this point, Git performed the merge but did not automatically create a new merge commit. Git stops and waits for you to resolve conflicts. You can use git status at any time after the conflict to see which files are in an unmerged state due to conflicts:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
Any files containing conflicts that need to be resolved are marked as unmerged. Git inserts standard conflict markers in conflicted files so you can open them and manually resolve the conflict. The conflicting file will include special sections that look like this:
<<<<<<< HEAD:index.html
<div>contact : email.support@github.com</div>
=======
<div>
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
This indicates that the version pointed to by HEAD (your current master branch, because you ran the merge command while checked out to this branch) is in the upper part of the section (above =======), and the version pointed to by the iss53 branch is in the lower part. To resolve the conflict, you must choose one of the parts divided by =======, or merge the content yourself. For example, you could resolve the conflict by changing it to:
<div>
please contact us at email.support@github.com
</div>
This conflict resolution keeps only one branch’s changes, and the lines with <<<<<<<, =======, and >>>>>>> are completely removed. After resolving all conflicts in every file, use the git add command on each conflicted file to mark it as resolved. Once staged, Git will consider the conflicts resolved.
If you want to use a graphical tool to resolve conflicts, you can run git mergetool, which will launch an appropriate visual merge tool and guide you through the resolution step-by-step:
$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html
Normal merge conflict for 'index.html':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (opendiff):
If you want to use a merge tool other than the default (here Git uses opendiff as the default because the author runs it on Mac), you can see all supported merge tools after the phrase “one of the following tools” and enter the name of your preferred tool.
Note | If you need more advanced tools to resolve complex merge conflicts, we will introduce more about branch merging in Advanced Merging. |
After you exit the merge tool, Git will ask if the merge was successful. If you answer yes, Git will stage the files, marking the conflicts as resolved. You can run git status again to confirm that all conflicts have been resolved:
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: index.html
If you are satisfied with the result and sure all previously conflicted files are staged, you can run git commit to finish the merge commit. By default, the commit message looks like this:
Merge branch 'iss53'
Conflicts:
index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: index.html
#
If you think the above message is insufficient to fully reflect the merge process, you can modify it and add some details to help future reviewers understand how you resolved the conflicts and the reasoning behind it.