In Git, a merge is a way to put fork commit histories back together.git merge
The command is used to put you before usegit branch
Branches created by commands and independently developed content on this branch are consolidated into one branch.
Note that all of the following commands merge other branches into the current work branch. The contents of the current working branch are updated due to the merge operation, but the target branch is not affected at all. Again, this means that Git merge is usually used in conjunction with several other Git commands, including using the Git checkout command to select the current working branch, and using the Git branch -d command to remove obsolete branches that have been merged.
How does it work
Git merge merges multiple commit sequences into a single commit history. In the most common use scenario, Git merge is used to merge two branches. We will focus on this merge scenario in the remainder of this document. In this scenario, Git merge takes two commit Pointers, usually the top commit of both branches, and then traces back to the most recent joint commit of both branches. Once the joint commit is found, Git creates a new “Merge Commit” that merges the commit sequences on the two branches.
Let’s say we have a function branch derived from main, and now we want to merge the function branch back into main.
Executing the merge command merges the specified branch to the current working branch, which we assume is main. Git decides on its own algorithm for merging commits based on the two branches (discussed in detail below).
A merge commit is different from a regular commit because there are two parent commits. Git attempts to automatically merge two separate commit histories into one when creating a merge commit. However, when Git finds that a piece of data has changed in both commit histories, it cannot automatically merge it. This situation is called a version conflict, and Git needs human intervention to make adjustments to continue merging.
Ready to merge
Before the actual merge operation, you need to take some preparatory steps to ensure that the merge process can proceed smoothly.
Confirm the branch that receives the merge
Run the git status command to check the status of the current branch and ensure that the HEAD finger is pointing to the correct branch to receive the merge. If not, execute the git checkout command to switch to the correct branch. In our example, git Checkout Main is executed.
Get the latest remote commit
Ensure that both branches involved in the merge operation are updated to the latest state of the remote repository. Perform git fetch to pull the latest commit from the remote repository. Once the fetch operation is complete, you need to run the git pull command to ensure that the main branch is synchronized with the remote branch.
merge
When the aforementioned preparations are complete, the merger can begin. Run git merge
, which is the name of the target branch that you want to merge into the current branch.
Fast forward to merge
Fast forward merges when the commit history between the current working branch and the merge target branch is a linear path. In this case, instead of actually merging the two branches, Git simply moves the top pointer of the current branch to the top of the target branch. In this case, fast-forward the merge successfully and merge the commit history into one place. After all, the commits in the target branch are now included in the commit history of the current branch. The process for fast-forwarding a function branch to the main branch is shown below:
Fast forward merging, however, is not allowed in cases where two branches branch. When the commit history of the target branch is not linear relative to the current branch, Git can only use a three-way merge algorithm to determine how to merge the two branches. The three-way merge algorithm requires a dedicated COMMIT to consolidate the commit history on both sides. The term derives from the fact that Git requires three commits: the top commits of two branches and their common ancestor commits.
While there are actually options for using these various basing strategies, most developers prefer fast-forward basing (with the Rebasing command), especially for minor feature development or bug fixing; On the contrary, three-way merging is preferred for merging long-developed functional branches. In the second scenario, the merge COMMIT resulting from the merge remains in the commit history as a sign that the two branches merge.
Let’s use the first example below to show how to fast-forward a merge. The following command creates a new branch, commits twice on the new branch, and then merges the new branch back into the main branch using a fast-forward merge.
# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature
Copy the code
The workflow in this example is typically used for short term functionality development, which is considered more of an independent primary development process, as opposed to a long term functional development branch that needs to be coordinated and managed.
Git will not warn you about Git branch -d because the new-feature content is already incorporated into the main branch.
In some cases, even though the commit history of the target branch is linear with respect to the current branch, you still want to have a merge commit to indicate that the merge occurred at that commit. Use the –no-ff option when executing git merge.
git merge --no-ff <branch>
Copy the code
The above command merges the specified branch to the current branch, but always generates a merge COMMIT (even if the merge can be fast-forward). This command is useful when you need to mark merge events in your repository’s commit history.
Three-way merge
The following example is similar to the above one, but since the main branch itself also changes during the development of the feature branch, three-way merging is required during the merging. This scenario is quite common in large feature developments or when there are multiple developers working at the same time.
Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature
Copy the code
Note that Git cannot perform a fast-forward merge in this case because there is no way to move the top pointer of main directly to the new-feature branch.
In most real work scenarios, the new-feature should be a big feature, and the development process lasts quite a long time, which makes it inevitable that there will be new commits on the main branch at the same time. If your feature branch size is as small as the example above, it is perfectly possible to use rebase to base the new-feature branch onto the main branch, and then perform a fast-forward merge again. This also avoids excessive redundancy in the project commit history.
Resolve the conflict
If both branches to be merged change the same part of the file, Git can’t decide which version to use. When this happens, the merge process stops before the merge COMMIT is committed to give the user the opportunity to fix these conflicts manually.
The nice thing about Git’s merge process is that it uses the well-known edit/staging/commit workflow to resolve conflicts. When a merge conflict occurs, the git status command lists which files contain the conflict and need to be resolved manually. For example, if both branches modify the same part of the hello.py file, you’ll see something like this:
On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py
Copy the code
How does the conflict show up
When Git encounters a conflict during a merge, it edits the relevant content in the affected file and adds visual markers to show the difference between the two parties in that part of the conflict. These visual labels are: <<<<<<<,=======,>>>>>>>. To find out exactly where the conflict is occurring, it’s very easy to do this by searching the document for these visual markers.
here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;
Copy the code
In general, the content before the ====== tag comes from the branch that receives the merge, and the content after that comes from the branch to merge.
Once the conflicting parts are found, they can be fixed as needed. When you have fixed the conflicts and are ready to proceed with the merge, simply run the git add command to add the resolved files to the staging area and tell Git that the conflicts have been resolved. After that, execute git commit as you would normally commit code to complete the merge commit. This process is exactly the same as submitting code normally, which means that conflict resolution is a breeze for the average developer.
It should also be noted that merge conflicts can only occur in the three-way merge process and will not occur in the fast-forward merge.
conclusion
This article provides an overview of the Git merge command. Merge is a very important operation when working with Git. This article discusses the mechanisms behind merge operations and the differences between fast-forward and three-way merge. Key points to keep in mind:
- The Git merge process combines different commit sequences into a single commit history
- There are two main approaches to Git merge: fast forward merge and three-way merge
- Unless there is a conflict between two commit sequences, Git can usually merge commits automatically