Merge Branches – Git Merge
git merge
is the command used when you want to merge branches. The merge operation can be done through the Remote Repository on the GitHub platform; it will be explained further in the next chapter.
When you run the git merge
command, you need to run the command from the branch you want to continue to work on and specify a target branch name that you want to merge with the current branch.
There are four main cases for merge actions depending on the status of branches and command options.
- Fast-Forward Merge
- Non-Fast-Forward Merge
- Non-Fast Forward Merge with the "--no-ff" option
- Squash Merge
1. Fast-Forward Merge
When you are merging a child branch that is ahead of the parent branch (no changes were made to the parent branch after the point when you created the child branch), the git merge
command simply brings changes made in the child branch into the parent branch without creating a new commit. In this case, the status of the branches will shift to the one shown in the following illustration.
This command moves the HEAD of the master branch forward to the point of the HEAD of Branch_A. The merge command doesn't impact Branch_A. The master branch simply becomes the same as the status of Branch_A.
Key Points of Fast-Forward Merge
- No new commit is created
- HEAD of the master branch moves forward to HEAD of Branch_A
- Branch_A still remains the same (it is not deleted by the merge command)
- The master branch and Branch_A reach the same status
2. Non-Fast-Forward Merge
When the parent branch (e.g., master branch) is already ahead of the diverged point of the child branch, the merge action becomes a non-fast-forward merge. In this case, the merge action is recorded as a new commit. When you run the git merge
command, a text editor is launched to add a commit message. A short description is already written in the text editor. You can change the message or just save it. When you close the editor, the merge action is completed. The following illustration describes the before and after of the non-fast forward merge.
In this case, the HEAD of the master branch moves forward integrating all commit histories under Branch_A.
Key Points of Non-Fast Forward Merge
- A new commit is created
- HEAD of the master branch moves forward while integrating the changes made in Branch_A
- Branch_A's commit histories are also recorded under the master branch
- Branch_A still remains the same (it is not deleted by the merge command)
3. Non-Fast Forward Merge with the "--no-ff" option
Even when the status of branches is the same as the fast-forward case, you may want to create a new commit. If that is the case, you can use the --no-ff
option. The command enforces the creation of the commit shown in the illustration below. The merge result becomes almost the same as the previous case; the only difference is that the previous case has commit M4 before the HEAD on the master branch.
4. Squash Merge
Squash is another approach when you merge branches. This approach is useful when you don't want to keep every single detail of change histories in the master branch.
When you run the git merge
command with the --squash
option, all the changes made in the target branch are reflected in the destination branch. However, the command doesn't create a new commit. The changes are only reflected in the Working Tree and INDEX (see the illustration below).
When you want to proceed with the change, you need to make a new commit by running the git commit
command. This command records only one new commit under the master branch. All commits under Branch_A are combined (squashed) in the new commit.
Key Points of Squash Merge
- No new commit is created by the
git merge
command - The status of Branch_A (the changes made after the divergence point from the master branch: commit A1 and A2) is integrated into the Working Tree and INDEX of the master branch
- You need to create a new commit to record the merge operation
- Branch_A's commit histories are not recorded under the master branch (All commits under Branch_A are combined (squashed) in the new commit)
- Branch_A still remains the same (it is not deleted by the merge command)