Merging Branches

Introduction

When a feature branch is ready, you merge it into main (or another target branch) to combine histories. Git performs a fast-forward when possible, or a three-way merge when branches diverged. This chapter merges locally, reads the results, and cleans up finished branches.

Prerequisites

Prepare a Feature Branch

Starting from main:

bash
git switch main
git switch -c feature/footer
echo "<footer>hello</footer>" > footer.html
git add footer.html
git commit -m "Add footer partial"

Basic Merge

Switch to the branch that should receive changes (usually main):

bash
git switch main
git merge feature/footer

If main had no new commits since branch point, Git fast-forwards:

text
Updating a1b2c3d..e4f5g6h
Fast-forward
 footer.html | 1 +
 1 file changed, 1 insertion(+)

Code explanation:

  • main pointer moves forward to feature tip
  • No merge commit created—linear history

Verify:

bash
git log --oneline --graph
ls footer.html

Three-Way Merge

When main moved while feature was active:

bash
git switch main
echo "# updated" >> README.md
git add README.md
git commit -m "Update README on main"
 
git switch feature/footer
echo "/* styles */" > footer.css
git add footer.css
git commit -m "Add footer styles"

Merge into main:

bash
git switch main
git merge feature/footer

Git opens editor for merge commit message (or use -m):

text
Merge branch 'feature/footer'

Log shows divergent history joined:

bash
git log --oneline --graph --decorate
text
*   f6g7h8i (HEAD -> main) Merge branch 'feature/footer'
|\
| * e5f6g7h (feature/footer) Add footer styles
* | d4e5f6g Update README on main
|/
* a1b2c3d Initial commit

Merge with --no-ff

Force a merge commit even when fast-forward is possible:

bash
git merge --no-ff feature/footer -m "Merge feature/footer into main"

Teams use this to preserve visible merge points in history for releases or audits.

After Successful Merge

Delete local feature branch:

bash
git branch -d feature/footer

If Git warns not fully merged, you merged differently or branch diverged—use -D only to discard intentionally.

Merge vs Rebase (Preview)

mergerebase
HistoryPreserves branch topologyLinear replay
Commandgit merge featuregit rebase main on feature
Shared branchesSafe on mainDo not rebase public history

Rebase chapter comes later; merge is the safe default for beginners merging into main.

Abort a Merge in Progress

If conflicts overwhelm you (conflicts detailed next chapter):

bash
git merge --abort

Returns to pre-merge state.

Pull Request vs Local Merge

On GitHub, merging a PR often creates the same merge commit on remote main. Locally you practice the same git merge before pushing—or merge only on the website. Both end with integrated code.

Checklist

  • On target branch (main) before git merge feature
  • Feature branch tested or reviewed
  • git log --graph shows expected structure
  • Delete merged branch locally when done

FAQ

Wrong branch merged?

If not pushed: git reset --hard ORIG_HEAD immediately after merge (undo chapter). If pushed: revert merge commit.

Merge without switching to main?

git fetch origin then git merge origin/feature while on main—same idea.

Octopus merge?

Merging multiple branches at once—git merge a b c—rare in small teams.

Who resolves conflicts?

Whoever runs merge—next chapter.

merge commit on fast-forward team?

Use --no-ff policy or squash merge on platform.

Squash merge?

All feature commits become one on main—GitHub button; different from local merge.