

Git and Mercurial branching - steveklabnik
http://lucumr.pocoo.org/2010/8/17/git-and-mercurial-branching/

======
rlpb
Git doesn't really have changesets as first order objects; it has snapshots.
Each commit is the hash of a snapshot of the tree at that point, together with
the commit message and the hash of any (at least one) parent commits. This is
pretty much the entire data model. The rest just pops out, which is why it is
so elegant.

~~~
tzs
Minor correction: there does not have to be at least one parent commit. A
commit can have no parent. The root commit, for example, should be parentless.

A repository can have more than root. For instance, I have a repository that
was formed from merging two separate repositories. From a code history point
of view, the two repositories are unrelated, so in the merged repository each
has its own root.

~~~
psadauskas
Github also takes advantage of this; if you make an empty branch called "gh-
pages", and put static html (and css, js) in it, Github will host them for
you.

I've also used it to greenfield some ideas in the same project. Its a bit of a
hack to create one, though:

    
    
        git symbolic-ref HEAD refs/heads/newbranch 
        rm .git/index 
        git clean -fdx 
        <do work> 
        git add your files 
        git commit -m 'Initial commit'
    

(From <http://book.git-scm.com/5_creating_new_empty_branches.html>)

~~~
davvid
The community git book will often do things "the old fashioned way" to keep
compatibility with older versions of git.

Modern versions of git let you do this instead:

    
    
        git checkout --orphan new-branch

------
ErrantX
Gah, I kinda came to this hoping to stick up for hg yet again. But a lot of
these gripes are accurate.

It's not likely to change though. And here's the dice:

If you want something that "just works" and is awesome from the command line
Mercurial is your best friend. If you may be facing borderline case that will
wrap you in tape, Git is a better option.

~~~
sjs
And let's be honest, if you don't think you'll _ever_ face such a borderline
case you're being naïve or shortsighted. Just take the time to learn git. Like
learning to use unix or $EDITOR you will not regret it.

With whatever git-hg bridges are available you can probably still use hg if
you really like it. Could be wrong on that but iirc they exist.

------
rue
An interesting article, if a little incoherent. It seemed to bounce around a
bit much.

There are some reasonable means of local git sharing, by the by: the old
gitjour project was fun and more recently there's gitosis and gitolite. You
could also leverage Dropbox or similar, or actually work with individual
repositories.

~~~
josegonzalez
Bananajour and the Git server also work just as well. Any git repository can
also act as a remote, and if it is made accessible over network, then you have
essentially duplicated a git server.

~~~
cdavid
In all fairness, hg serve is much easier to use than git daemon. It works on
windows, for once, and you don't have to be aware of all kind of border cases
w.r.t. aliases, etc... Still recently, I got issues accessing a git repo in
which I did "git daemon --export-all" - I ended up making it work by executing
git daemon outside the repo, which is a bit weird.

------
fendrak
Am I the only one who thinks picking a DVCS tool based on the GUI is a bad
idea? It seems to me that hg and git were designed to be used from a command
line, and (for git at least) it works brilliantly. The GUI DVCS frontends try
to hide a lot of the complexity of various tasks from you, but in that
insulation you also end up with a clouded view of how things actually work,
leading to the branching/merging mistakes the author talks about.

~~~
steveklabnik
I assumed that when he said "GUI" he meant "interface."

I could be wrong.

~~~
fendrak
"GUI" is never explicitly mentioned, but after re-reading, I'm still not sure
he _didn't_ mean a GUI, but neither am I sure that he certainly meant the CLI.
I've never had a problem with the git CLI, I actually preferred it over the hg
one (git pipes the log into 'less' for example, and lists entries in a sane
reverse order so that the most recent log entry is on top). Maybe I'm just
sensitive?

~~~
steveklabnik
Maybe. "git has a hard cli" is a meme that's been around as long as git has.
I've never found it to be particularly difficult.

~~~
davvid
...and I would never hire anyone who perpetuates that myth. I converted a
large (50+) group of developers to git from an old, horrible system which will
go unnamed. Only the stupid ones complained about the switch. Sorry, it's
true.

Ya, I'm a little bruised over the flames that ensued during the transition but
I think we're better off after having bitten the bullet. The biggest problem
was always close-minded people, it was never the technology.

~~~
prodigal_erik
The git model is good enough that we use it in spite of the bad CLI, not
because of it. Just off the top of my head:

* the HEAD^2~3 syntax is so obscure that I can't believe anyone actually uses it; I always give up and get a commit name from the log instead

* it will cheerfully give you a branch named refs/heads/R/B having no relationship with refs/remotes/R/B with no warnings (I have even seen peers create and push refs/heads/refs/heads/R/B by mistake)

* the index should be a hidden implementation detail, with partial commits done instead via "git stash" so it's at least possible to test them (the index is also what caused "git checkout" and "git reset" to become bizarre grab bags of mutually exclusive actions)

------
stevelosh
I really need to sit down and write a blog post and set of aliases that let
you use git-style branching in Mercurial through the bookmarks extension. It's
completely possible, it's just not the standard.

The only thing I'm aware of that Git can do that Mercurial can't, branching-
wise, is pushing deletes, which messes up everyone else's pulls anyway.

~~~
davvid
What about pushing only a subset of your branches? As far as I know, you can't
commit to N branches and then push only a subset of them with hg.

There's also the whole index/staging area thing that I use everyday in git.
That said, I think they're both alright. I think schacon summed it up pretty
well in his talk at pycon:

<http://us.pycon.org/2010/conference/schedule/event/137/>

~~~
piranha
You mean something like "hg push -B sub -B set"? Why not?

------
follower
> "This however is a shame because if you remove the github component..."

I'm quite happy using the hg-git plugin (by the GitHub folks) which allows you
to use Mercurial to interact with GitHub: <http://hg-git.github.com/>

------
cookiecaper
I prefer git over hg because of its branch model. hg's doesn't compete, and
git has totally changed my workflow with branches. hg seems like it would
cause me to revert to the old way which is not desirable to me.

hg also requires extensions to do many things that git does out of the box
(like the equivalent of git stash, which I also use often). I saw very little
reason to prefer hg for the brief time I experimented with it.

~~~
tednaleid
In what way doesn't hg's branch model compete? Are you going off FUD and "a
brief time that [you] experimented with it" or do you have a real example?

~~~
cookiecaper
I'm going off of a brief time I experimented with it, I admit that I didn't
use hg very long. I may come to like it better or learn more if I use hg for a
serious project, though I know of no reason to do so voluntarily other than
curiosity and education.

The branch model doesn't compete because branches are ingrained, as this
article discusses; the changeset always carries the branch name with it.
Branches are also ingrained as "long-lived branches" and instead of the mere
application of a label to divergent changesets, these branches appear tightly
coupled and are meant to be merged and/or closed in the way hg expects. You
can only get git-like flexibility such as cherry-picking by making another
clone or by installing a variety of extensions.

See <http://mercurial.selenic.com/wiki/GitConcepts#Branch_model> , which
explains that git-like branches don't have a direct equivalent in Mercurial
unless you use the BookmarkExtension to apply names to a changeset; otherwise,
you must use hg heads, which doesn't work in quite the same way, at least
during my brief experience.

On top of this, git is usually faster and usually has much smaller
repositories (see <https://git.wiki.kernel.org/index.php/GitBenchmarks>), so I
don't see much reason to prefer hg. git integrates fine with Windows if one
installs msysgit, which includes a minimalist cygwinish environment and is not
at all unreasonable.

~~~
tednaleid
I think that extensions are sort of badly named in mercurial, but you're
making them out to be much more difficult to work with/install than they
actually are.

Mercurial ships with a bunch of features ("extensions") turned off by default
so that beginner users aren't confused with stuff before they're ready.
Turning the bookmark extension on is as easy as putting "bookmarks=" in your
~/.hgrc file. So the bookmark branching model, which is equivalent to the git
branching model and something I use every day, is a built-in part of
mercurial. You just have to enable it to work that way.

The "transplant" extension (similar to cherry picking in git) also comes with
mercurial and is just a one liner in a config file to enable.

------
wkornewald
So hg branches should behave like completely separate clones/repos that happen
to live within the same folder/URL. That would fix pretty much all issues and
be completely straight-forward since it mimics the separate-clones-as-branches
model originally promoted by hg, with the difference that you don't have
separate folders for the clones.

