Chapter 14 — Updating Branches
Overview: Staying in Sync with main
When you are working on a feature branch that takes several days or weeks,
main will receive other people's merged PRs in the meantime.
Your branch gradually diverges from main.
gitGraph
commit id: "A"
commit id: "B"
branch feature/thermal-correction
checkout feature/thermal-correction
commit id: "C: your work"
checkout main
commit id: "D: Alice's PR"
commit id: "E: Bob's PR"
checkout feature/thermal-correction
commit id: "F: more your work"
At this point, your branch is based on commit B, while main is at E.
Before opening a PR, you should update your branch to be based on the latest main.
Rebase: The Group's Preferred Strategy
The group uses rebase to update feature branches.
Rebase replays your commits on top of the latest main, creating a linear history:
Before rebase: After rebase:
main: A - B - D - E main: A - B - D - E
\
feature: A - B - C - F feature: C' - F'
gitGraph
commit id: "A"
commit id: "B"
commit id: "D: Alice's PR"
commit id: "E: Bob's PR"
branch feature/thermal-correction
checkout feature/thermal-correction
commit id: "C': your work (rebased)"
commit id: "F': more your work (rebased)"
Your commits C and F are replayed as new commits C' and F' on top of E. The content is the same; the parent commits are different.
Step-by-Step: Rebase Onto main
# 1. Fetch the latest changes from GitHub
git fetch origin
# 2. Check how far main has advanced
git log --oneline origin/main
# 3. Rebase your branch onto the latest main
git rebase origin/main
If there are no conflicts, this completes silently and your branch is now
based on the latest main.
If conflicts occur, resolve them following Chapter 13, then continue:
After rebase, your branch history has been rewritten (new commit hashes). Force-push to update GitHub:
Rebase vs Merge: Why Rebase?
The alternative to git rebase is git merge:
Merge creates a merge commit that ties the two histories together. The result looks like:
Where M is a new merge commit connecting E and F.
| Rebase | Merge | |
|---|---|---|
| History shape | Linear | Graph with branches |
main log readability |
Clean | Cluttered with merge commits |
| PR diff | Shows only your changes | May include noise from the merge |
| Group policy | Required | Not used for branch updates |
Rebase produces a cleaner history that is easier to read and review.
Rebase rewrites history
Because rebase creates new commits (with new hashes), you must force-push after rebasing.
Use git push --force-with-lease.
Never rebase a branch that other people have already based work on.
For private feature branches (the normal case), this is always safe.
--force-with-lease vs --force
| Flag | Behaviour | When to use |
|---|---|---|
--force-with-lease |
Checks that no one else pushed since you last fetched | Always |
--force |
Overwrites unconditionally | Never |
--force-with-lease refuses if someone else has pushed to the remote branch since
you last fetched. This protects you from accidentally overwriting a colleague's
commits.
When to Update Your Branch
Update (rebase) your branch in these situations:
-
Before opening a PR. Your branch should be based on the latest
mainso the reviewer does not need to mentally subtractmain's changes from your diff. -
When
mainhas changed significantly. If a colleague merged changes to files you are also editing, update sooner rather than later to avoid large conflict sessions. -
When a reviewer asks you to rebase. Sometimes a PR review includes the instruction to rebase because
mainhas changed since the PR was opened. -
When GitHub shows "This branch is out of date with the base branch." The PR page shows this warning when
mainhas advanced past your branch's base commit.
Checking How Far Behind You Are
This shows commits that are on origin/main but not on your current branch.
If this list is empty, you are up to date.
Aborting a Rebase
If a rebase goes wrong and you want to cancel:
This returns your branch to exactly the state it was in before you started the rebase. No changes are lost.
Common Mistakes
-
Using
git merge origin/maininstead ofgit rebase origin/main. This creates a merge commit on your feature branch, which clutters the PR diff. -
Not fetching before rebasing.
Always# Wrong (rebases onto your local copy of main, which may be stale): git rebase main # Correct (rebases onto the actual current state of main on GitHub): git rebase origin/maingit fetch originbefore rebasing. -
Force-pushing to
main. The force push after rebase should only target your feature branch. -
Using
--forceinstead of--force-with-lease. Always use--force-with-lease. -
Rebasing a branch that others have checked out. If a colleague has branched from your branch or is reviewing it with local checkout, rewriting history will break their copy. Coordinate first.
Best Practice Summary
- Use
git rebase origin/main(notgit merge) to update feature branches. - Always
git fetch originbefore rebasing to get the latest remote state. - After rebase, use
git push --force-with-leaseto update GitHub. - Update before opening a PR and whenever
mainhas changed significantly. - Use
git rebase --abortto safely cancel a rebase that goes wrong.
Checklist
- I understand the difference between rebase and merge for branch updates.
- I know to run
git fetch originbeforegit rebase origin/main. - I know to use
git push --force-with-leaseafter rebasing. - I know when to update my branch (before PR, when main advances).
- I know how to abort a rebase with
git rebase --abort.
Exercises
-
Simulate a diverged branch. Create
feature/branch-a. Switch tomain, make a commit there (or pull a new commit from the remote). Switch back tofeature/branch-aand rungit log --oneline HEAD..origin/mainto see the divergence. Then rebase. -
Rebase with a conflict. Extend the conflict scenario from Chapter 13. After resolving the conflict during rebase, verify with
git log --oneline --graphthat the history is linear. -
Before and after comparison. Run
git log --oneline --graphbefore and after a rebase. Note how the graph changes from a two-branch shape to a linear shape.