Mercurial Named Branches: Architecture, Trade‑offs, and Operational Guidance
Named branches in Mercurial embed branch identity into each changeset, offering a global, immutable namespace. This article dissects the design, explains its benefits and pitfalls, and shows how to use, close, and audit branches safely in production repositories.
25 Sept 2026, 05:31 UTC

Problem Statement
When teams adopt Mercurial, they often wonder how branch names are stored and why some Git users find Mercurial’s approach confusing. The core issue is that Mercurial’s named branches are not lightweight pointers like Git’s refs; they are part of the commit metadata itself. This design decision has concrete implications for history integrity, collaboration, and tooling.
Requirements for a Branching System
- Persist branch identity across clones and pushes.
- Maintain a global, conflict‑free namespace.
- Provide auditability: every changeset should reveal its originating branch.
- Allow developers to close a branch without deleting history.
- Keep the repository lightweight: avoid a separate reference store.
Smallest Suitable Design: Branch Name as Changeset Property
The minimal architecture that satisfies the requirements is to embed the branch name directly into each changeset. When a commit is created, Mercurial records the current branch name as a property of that changeset. The repository’s .hg/branch file stores the current active branch for the local working copy, but the authoritative branch information lives in the changesets themselves.
Key Consequences
- Branch identity is immutable once the changeset is created; it cannot be altered without rewriting history.
- Because the branch name is part of the changeset, it travels with the changeset during pushes and pulls, automatically keeping all collaborators in sync.
- There is no separate branch reference table; the repository’s metadata is self‑contained.
Trust & Data Boundaries
Since branch names are stored in the changeset, the boundary between local and remote state is clear: a changeset’s branch name is trustworthy as long as the changeset is signed or the repository’s hg verify passes. The .hg/branch file is only a convenience for the working copy and can be safely ignored by remote peers.
Operational Checks
- Verify Current Branch
# Run on the repository root hg branch # Expected output: the name of the active branch - List All Branches
hg branches # Shows open and closed branches with the latest changeset ID - Inspect Branch in a Commit
hg log -r 12345678 --template "{branch}\n" # Replace 12345678 with a real changeset ID - Check for Closed Branches
hg branches -c # The -c flag lists only closed branches
Failure Modes & Mitigations
- Branch Name Clashes – Two developers creating a branch with the same name on different machines will not clash because the name is part of each changeset. However, if they later push, Mercurial will merge the histories, potentially creating a confusing graph. Mitigation: use a consistent naming convention (e.g.,
feature/xyz). - Unintended Reuse of Closed Branch Names – Even after a branch is closed, its name remains in the history. If a new branch is created with the same name, Mercurial will treat it as a new open branch, but the old closed branch remains visible. Mitigation: always close a branch before deleting the feature branch or use
hg strip(with caution). - Long‑Lived Named Branches Clutter Graphs – Visual tools that render the DAG can become cluttered if many named branches persist. Mitigation: close branches that are no longer needed or use bookmarks for short‑lived work.
- Cannot Delete Branch History – Removing a branch’s history requires a rewrite (e.g.,
hg evolveorhg strip). Mitigation: plan major history rewrites carefully and coordinate with all collaborators.
When the Design Might Need to Change
- If a team requires lightweight, temporary references similar to Git branches, Mercurial’s bookmarks should be used. Bookmarks are stored in a separate file and behave like Git refs.
- When integrating with CI pipelines that rely on branch names for deployment, the immutable branch name property can simplify tracking but may need custom scripts to map closed branches to deployment branches.
- Large monorepos with many short‑lived features may benefit from a hybrid approach: use named branches for long‑term releases and bookmarks for experimental features.
Practical Example: Closing and Reopening a Branch
Suppose you finished a feature on branch feature/login and want to close it. The following steps illustrate the process.
- Switch to a stable branch
hg update default - Close the feature branch
hg update feature/login hg commit -m "Close feature/login"The commit will have
branch: feature/loginbut will be marked as closed in the repository metadata. - Verify closure
hg branches # feature/login should appear with a trailing "(closed)" - Reopen the branch for a quick fix
hg update feature/login # Mercurial will automatically reopen it for you
Conclusion
Mercurial’s named‑branch design embeds branch identity into the commit history, guaranteeing a globally consistent namespace and strong auditability. While this eliminates the need for a separate reference store, it imposes immutability and can clutter the graph if many long‑lived branches exist. By understanding the architecture and using operations like hg branches and hg branch judiciously, teams can manage branches reliably while keeping the repository’s metadata clean and traceable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.