Monday, January 16, 2012

What Is So Wrong With Mercurial's Named Branches?

I just installed the very latest version of mercurial, 2.0.2. It added a new little feature that warns you when you create a branch. Huh? This is what it looks like:

$ hg branch foo
marked working directory as branch foo
(branches are permanent and global, did you want a bookmark?)

Really? Have we let the git advocates push us this far? Do we really need to start discouraging named branches?

I googled around to see if I could find where the self-hate for mercurial's named branches is coming from and I found things like this, "it is almost never a good idea to use this facility for short-term branching, since branches created this way are inherently 'eternal'." (those quotes around eternal are good, actually, but you didn't explain why they should be there), and this, "you can never really delete branches (since that would mean altering older commits)." (editing history, oh noes!), and others like this. And these were all written by apparent mercurial supporters! I understand when a git developer writes misinformation about mercurial and uses it to try and make git look better (that's only human), but we mercurial users should know not to listen to it!

Here's what I think is going wrong. Git users love flexibility. The love it so much that they even include modifying their local repository history right into their standard workflow. git rebase is a core command. From what I can gather, even though mercurial now (as of years ago, actually) has powerful rebase and patch queue extensions, mercurial users still get the heebie-jeebies when they think about modifying repository history. This is where the git envy comes from. You see, git useres can alter their branch names, or even delete branch names without using scary rebase. Fact is, though, git could adopt mercurial-style named branches and git users would rebase them away or rename them with rebase willy-nilly just like they do with everything else that they deem needs editing in their history. The fact that git users can rename or delete their branches without using rebase is almost completely incidental. If you allow the use of rebase or patch queues, mercurial named branches are not any more permanent than any other changeset in the repository history. Mercurial bookmarks allow mercurial users flexibility around branch names without needing to resort to scary history editing extensions, and that makes us happy, but I don't think that we should talk down mercurial named branches. There are times when you want the branch name associated with a commit to be just as "permanent" as the commit is. Let us do that without dumb warnings that make named branches sound like a bad idea.

The only other argument people may have against mercurial's named branches is the possibility of name collisions. As if that's something that's really hard to deal with. Anyone who has written a fair amount of C code (I'm looking at you, git developers) knows how to prefix a name to get poor-man's namespaces. Alternatively, many projects require an issue tracker number in a feature-branch or bugfix-branch name. Name collision problem solved.

In conclusion, mercurial named branches are fine. Use them more. Use rebase and/or patch queues[1] to rename or delete the branches when necessary. If that really bothers you, you have bookmarks now, but don't go all git-apologetic on named branches. Mercurial is every bit as awesome as git.

1. Before you push to a publicly accesible repository, of course. Ask a git user why that's important.

4 comments:

Alex V Koval said...

yah, that confuses me. mercurial named branches fit our workflow the best way, because we want to stay our branch history forever.

Anonymous said...

The mutable-branches extension (http://mercurial.selenic.com/wiki/MutableBranches) can give the illusion of having renamed a branch.

shelby said...

Face it, you are an idiot, just like Linus Torvald said.

> The fact that git users can rename or delete their branches without using rebase is almost completely incidental.

Named branches can't be assuredly deleted because they have infected the changesets of every unknown decentralized copy in existence on earth. Don't make your changesets public then. Then you don't need DVCS, just use CVS.

> knows how to prefix a name to get poor-man's namespaces

Each Git repository’s set of local branch names can have its own namespace because lightweight branch names are not immutably recorded in changesets. Thus each repository can refer to another repository’s set of local branch names by prepending what ever name the referring repository chooses for the other repository. Whereas, Mercurial’s bookmarks (as currently implemented) invert the naming unique responsibility from the referrer to the referent; and thus require each repository to select a name which will be unique from all other possible names that any other repositories might use. A repository self-prepending its own name to its branch names is only a solution if every repository’s name is globally unique.

Bryan said...

Linus commented about me personally? That would be an exciting first for me. Do you have a link to that?

You are correct that if you push a mercurial branch it can't be renamed (and I mentioned that in my footnote), just like you can't do any other editing of commits (amending, rebasing, folding, etc.) once you push them.

Generally the way things work is you pull in changes from the repo you are about to push to and make sure your push isn't going to break anything before you push to it. When you pull you might discover that you picked a bad name for your branch (one that was already taken, for example) and then you could rename it using rebase. You could also create a named branch to keep track of your local work, pull, then rebase your changes onto another branch forever deleting the named branch you used when doing your local development. My point still stands: even with named branches, you have options.

I'll admit I haven't used mercurial bookmarks much, but from the documentation:

https://www.mercurial-scm.org/wiki/Bookmarks

it sounds like you are correct, there is no automatic namespacing done like with git. Honestly, I found git's auto renaming of branches confusing at first, but I can see how for a large project with many many people involved (like the linux kernel) auto namespacing would avoid another sort of confusion.