Git Branches | git merge

The git merge command

Merging is the way Git integrates branched work back together. git merge combines independent lines of development created with git branch into one branch.

Note that all commands described below merge into the current branch. The current branch is updated with the result of the merge, while the target branch specified as the argument remains unchanged. For that reason, git merge is usually used together with git checkout to select the receiving branch and git branch -d to delete the branch that is no longer needed.

Usage

git merge <branch>

Merges the specified branch into the current branch. Git automatically chooses the merge algorithm.

git merge --no-ff <branch>

Merges the specified branch into the current branch and always creates a merge commit, even when a fast-forward merge would be possible. This is useful when you want to record every merge in the repository.

Additional notes

After feature development is completed on an independent branch, the work needs to be integrated into the main codebase. Git provides multiple algorithms depending on the shape of the repository history: fast-forward merge and three-way merge.

A fast-forward merge applies when there is a single straight path from the tip of the current branch to the target branch. In this case, no real merge is needed. Git simply moves the tip of the current branch to the tip of the target branch. As a result, commits that were reachable from the target branch become reachable from both branches.

Git Tutorial: Fast-forward merge

When branches have diverged, a fast-forward merge cannot be used. Because there is not a single path to the target branch, Git must use a three-way merge. A three-way merge creates a dedicated merge commit to combine two histories. The name comes from the three commits used to create the merge commit: the tips of the two branches and their common ancestor.

Git Tutorial: Three-way merge

Both merge algorithms are available. Many developers use fast-forward merges, often after rebasing, for small features and bug fixes, and use three-way merges for long-running features. In the latter case, the generated merge commit acts as a symbolic join between the two branches.

Resolving conflicts

If the two branches being merged changed the same part of the same file, Git cannot decide which version to use. In that situation, Git stops before creating the merge commit and asks you to resolve the conflict manually.

One strength of Git’s merge process is that conflict resolution uses the normal edit, stage, and commit workflow. When a merge conflict occurs, git status shows the files that need resolution. For example, if both branches changed the same part of hello.py, you may see:

# On branch master
# Unmerged paths:
# (use "git add/rm ..." as appropriate to mark resolution)
#
# both modified: hello.py
#

Inspect the conflicting content and make the required edits. When the fixes are complete, add the conflicted files to the staging area with git add. Then create the merge commit with the normal git commit command. Because this process is exactly the same as an ordinary snapshot commit, merge work remains easy to understand for regular developers.

Remember that merge conflicts occur only in three-way merges. A fast-forward merge cannot create a conflict.

Examples

Fast-forward merge

The following example shows a fast-forward merge. It creates a new branch, adds two commits to it, and then integrates it into master with a fast-forward merge.

# Start a new feature
git checkout -b new-feature master

# 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 master
git merge new-feature
git branch -d new-feature

This is a common flow when using short-lived feature branches for small independent work rather than long-running feature branches in a large organization.

Because the new-feature branch is already reachable from master, git branch -d does not show a warning.

Three-way merge

The next example is similar, but master also moves forward while the feature is being developed, so a three-way merge is required. This scenario often happens with large features or when multiple developers work on the project at the same time.

# Start a new feature
git checkout -b new-feature master

# 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 master branch
git checkout master

# Edit some files
git add <file>
git commit -m "Make some super-stable changes to master"

# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

In this case, Git cannot move master to new-feature without losing history shape, so a fast-forward merge is not possible.

In real workflows, new-feature may represent a large feature that requires long-term development, while new commits continue to be added to master. If the feature branch is actually small, as in the example above, rebasing it onto master and then performing a fast-forward merge may be preferable. This reduces unnecessary merge commits and keeps project history simpler.