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
- Branches Basics
- A feature branch with at least one commit not on
main
Prepare a Feature Branch
Starting from main:
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):
git switch main
git merge feature/footerIf main had no new commits since branch point, Git fast-forwards:
Updating a1b2c3d..e4f5g6h
Fast-forward
footer.html | 1 +
1 file changed, 1 insertion(+)Code explanation:
mainpointer moves forward to feature tip- No merge commit created—linear history
Verify:
git log --oneline --graph
ls footer.htmlThree-Way Merge
When main moved while feature was active:
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:
git switch main
git merge feature/footerGit opens editor for merge commit message (or use -m):
Merge branch 'feature/footer'Log shows divergent history joined:
git log --oneline --graph --decorate* f6g7h8i (HEAD -> main) Merge branch 'feature/footer'
|\
| * e5f6g7h (feature/footer) Add footer styles
* | d4e5f6g Update README on main
|/
* a1b2c3d Initial commitMerge with --no-ff
Force a merge commit even when fast-forward is possible:
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:
git branch -d feature/footerIf Git warns not fully merged, you merged differently or branch diverged—use -D only to discard intentionally.
Merge vs Rebase (Preview)
| merge | rebase | |
|---|---|---|
| History | Preserves branch topology | Linear replay |
| Command | git merge feature | git rebase main on feature |
| Shared branches | Safe on main | Do 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):
git merge --abortReturns 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) beforegit merge feature - Feature branch tested or reviewed
-
git log --graphshows 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.