Mercurial Rebase Extension: Linearize History & Avoid Pitfalls
Rebase in Mercurial rewrites selected changesets to create a linear history. This guide shows how to enable the extension, run a rebase, handle conflicts, and why you should avoid rebasing shared commits.
14 Aug 2025, 20:47 UTC

Problem: A Feature Branch Gets Out of Sync
Imagine you started a feature branch on commit A, but while you were working, the main line advanced to B and C. Your branch now looks like a diverging line:
A – B – C (default)
\
D – E (feature)
When you try to merge feature back, you’ll get a merge commit that hides the linear progress of your work. The question is: can we “pull” D–E onto C so the history stays clean?
Thesis: Rebase Lets You Rewrite History, but Only When You Understand the Consequences
The Mercurial rebase extension rewrites selected changesets so they appear as if they were created on top of a new parent. It gives you a tidy linear history, simplifies bisecting, and makes CI pipelines predictable. However, rewriting history that has already been shared can break collaborators’ repositories. The key is to know when and how to rebase safely.
1. Enable the Extension
Rebase is not enabled by default. Add the following to your .hgrc (global) or hgrc (repository) file:
[extensions]
rebase = .
After that, hg rebase becomes available. Verify by running hg help rebase.
2. Common Rebase Patterns
- Feature branch onto latest tip – before merging, rebase the branch onto the current tip of
default. - Clean up local commits – squash or reorder local changes before pushing.
Both patterns aim to keep history linear and avoid unnecessary merge commits.
3. The Rebase Process
Typical command:
hg rebase -base # optional, defaults to current branch’s base -dest tip
During the operation:
- Mercurial copies each changeset onto the new parent, creating a new node ID.
- If a file conflict occurs, the rebase pauses. Resolve the conflict, then run
hg rebase --continue. - To abort, use
hg rebase --abort, which restores the original state.
Because rebase rewrites node IDs, any bookmarks or tags pointing to the old changesets will need updating.
4. What Exactly Gets Rewritten?
| Item | Before Rebase | After Rebase |
|---|---|---|
| Node ID | abc123 | def456 |
| Parent | commit X | new parent (e.g., tip) |
| Metadata (author, date, message) | unchanged | unchanged |
Because the content stays the same, you can still audit the changes. But any external references (e.g., pull requests, CI jobs) that relied on the old node IDs will break.
5. Trade‑offs & Limitations
- Pros: Linear history, easier bisect, cleaner logs.
- Cons: Rewrites history; shared commits should never be rebased.
- Large divergence can produce many conflicts, making the process tedious.
- Bookmarks or named branches that reference rebased changesets need manual updating.
Use rebase only on local, unpublished changes or coordinate with teammates if you must rebase shared commits.
6. Worked Example
- Create a test repo:
hg init testrepo cd testrepo hg commit -A -m "Initial commit" - Make a few commits on
default:echo "line1" > file.txt hg add file.txt hg commit -m "Add file" echo "line2" >> file.txt hg commit -m "Update file" - Create a feature branch:
hg branch feature hg commit -m "Start feature" - While on
feature, the main line advances:cd .. cd testrepo hg update default hg commit -m "New change on default" - Rebase
featureonto the latest tip:hg update feature hg rebase -dest tipIf a conflict appears (e.g., both branches edited the same line), resolve it, then run:
hg rebase --continue - Verify linear history:
hg log -GYou should see a straight line of commits with no merge nodes.
7. Actionable Checklist
- Enable the
rebaseextension in.hgrc. - Only rebase local, unpublished changes unless coordination is established.
- Always run
hg statusbefore rebasing to catch uncommitted work. - After rebasing, update bookmarks or tags that pointed to old node IDs.
- Push to a remote only after confirming the new history is correct.
- Document the rebase in your team’s workflow guide.
Conclusion
Mercurial’s rebase extension is a powerful tool for keeping history clean, but it’s not a silver bullet. By enabling it correctly, understanding what changes, and respecting the boundaries of shared history, you can harness its benefits while avoiding the classic pitfalls of rewritten commits.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.