Hacker News new | past | comments | ask | show | jobs | submit login
Mercurial over Git (jonchu.posterous.com)
38 points by jchonphoenix on April 16, 2010 | hide | past | favorite | 52 comments



"Need to make a new branch? Try git branch--er... I mean 4 seemingly random Git commands that don't include the word branch. "

'git branch <branchname> [start-point]' creates a new branch....

Maybe he is referring to the fact that git branch wont change change branches? You have to use git checkout to actually switch branches.

"Not only is documentation for some important features sparse, the documentation that does exist is rarely ever of the best quality."

I am curious what specifically he was referring to. The docs on git-scm are pretty extensive. Between the docs, books, cheatsheets, videos there is a ton out there. Even the man pages include example usage where many man pages for command line tools do not.

Something I can't help but ponder is that in switching to the second system they already had a grasp of some dvc concepts making it easier and if trying git second would have been easier.


The problem is that every git command tries to be extremely flexible. That means the documentation for command X has to cover everything X can do, and when you're just trying to find out how to do action A you have to skim through all the other crap X can do.

For example, 'git help checkout' clocks in at 236 lines. 'git checkout' can change the revision/branch you're at, create a new branch, or revert files without changing HEAD.

The help output for the equivalent Mercurial commands:

* hg help update: 38 lines * hg help revert: 41 lines * hg help branch: 24 lines

If I want to revert a file's contents in a git repo I need to wade through 236 lines to figure out the exact command I need. With Mercurial I need to wade through 41, because I know: "Oh, I'm reverting a file, I need an 'hg revert' command of some kind."

Mercurial commands each do one thing (rarely two, almost never more than that) and do it well. If you want to combine commands, write a script. This makes the documentation concise and easy to read as you're working.

Git commands each try to be flexible enough to do many different things. The price you pay is that any time you need to read through the documentation it's an exercise in trying to search for a word in a man page and hoping everything you need is somewhere nearby.


I think he meant `git checkout -b ...` since that's what people want to do most of the time. What's the use case for creating a branch if you're not going to use it straight away? (and no 'branch' in the command really)


I always branch before rebasing. Especially when cleaning up history (merging 5-6 "checkpoint" type commits for a big feature into one, etc.) It makes it easy to get back to where you started and you have the original work for reference purposes.


does he really have a problem remembering 'git checkout -b ...'? Seems like a non issue to me.


It's not an issue, but it can be an annoyance. Put many of them together and you've got a reason why projects like Ubuntu's 100 papercuts exist. If you have to work with something that just isn't quite right even if it works in the end, it can affect your work.


I think the author meant these commands as I'm in the same OS class and this script has been circulating around the class:

$ cat git-create-branch #!/bin/sh

if [ $# -ne 1 ]; then echo 1>&2 Usage: $0 branch_name exit 127 fi

branch_name="$1" git push origin origin:refs/heads/${branch_name} git fetch origin git checkout --track -b ${branch_name} origin/${branch_name} git pull


Wow...just wow. Why would you do this to yourselves?

First of all,

    git push origin origin:refs/heads/${branch_name}
is totally unnecessary when creating a new branch.

I see that there are remote branches you want to track. It's simple, no need for a script. Just make sure you are synced with the current version of the repo you are using (using `git pull`). Then:

    git checkout --track -b bugfix origin/bugfix
Easy as pie. I even have an alias set when I want to do this, so I just call

    git cot bugfix origin/bugfix
To create a new branch locally (that doesn't track a remote), just call

    git checkout -b new-feature
Note: When using `git pull`, `git fetch` doesn't need to be called. Pulling changes will fetch them for you automatically.


That's not simple. Simple would be doing what everyone wants it to do with one command that's really easy to remember/discover.


> Simple would be doing what everyone wants it to do with one command

Everyone comes to the plate with different experiences/expectations. You can't hope to satisfy everyone.


how could it be simpler?


  hg branch new-feature
If you want it to branch from a different changeset than the one you're on, then:

  hg update deadbeef
  hg branch new-feature
No flags, no orgin/newfeature (what does that even mean?), just the commands describing exactly what you're doing.


# this creates the branch and switches to it (i.e. does a checkout)

git checkout -b new-feature

The only diff is -b, which is fine to me because it makes it clear that you are doing two things. You don't need the origin/newfeature stuff for the common case. I'm assuming this is what 'hg branch new-feature' is doing. How do you create a branch and not switch to it?


> How do you create a branch and not switch to it?

  hg branch new-feature
  hg update default
But why would you not want to switch to a branch you just created? Why create the branch if you're not going to work on it?


Actually that won't create a new branch.

'hg branch foo' just marks the working directory as branch foo. The 'hg update default' would then update back to the default branch and mark the working directory as being on 'default'.

To really just create a new branch you do: 'hg branch foo; hg commit -m "Create a new branch."' Two steps, but like you said, it's probably not something you'd be doing very often anyway.


I don't presume to know what is necessary by everyone's situation. If the argument is that mercurial is better because you don't have to use -b, well that's weak sauce.


I actually use git, myself, but it's not just the -b; there's all kind of stuff like that in git's "user interface". It gets annoying at times.


Also, while it makes it 'a bit annoying' for people like me, I wonder if it will rule git out when it comes to Big Companies and people who are not so computer literate. The last time I looked at the git/windows thing, it was pretty ugly and not nearly as easy to use as turtlesvn.


i'm at a big company that everyone has heard of, and we use git.


Without more information, I can't really say if you're contradicting me thesis or not. I can easily imagine a small group of git users in any big company, but not so much a larger group that includes a lot of less technical users.


That's a very odd and circuitous way of doing something that is already built-in, I've got to say.


To a lot of the people who prefer Hg to Git, I ask this question: What's the proper way to do a feature branch in Hg? (serious question) The three answers I've heard are:

* Use hg branch <branchname> like git. The problem is this always requires me to do a push -f, which doesn't feel right...

* Use clone. Really? For a feature branch?

* Use the LocalBranches extension. Really, feature branches (the #1 productivity gain since switching to DVCS) isn't in the core code?

I have yet to find an equivalent to what I consider a core git workflow.


You could use bookmarks if it's just going to be a local branch that only you work on, and you don't want anyone else to see the branch name.

I'd probably use a named branch. Yes, you have to use push -f the first time you push that branch to a remote repo, but I think of that as a "hey, do you really want other people to see this work-in-progress branch?" safeguard.


Hg allows local branches natively, but it tends to prefer pushing from repository to repository rather than from local branch to local branch. So you can do it either way 1 or 2 (whatever suits you). It sounds like #3 might be based on outdated information.


push -f is what I use, "force" makes it sound more sinister than it is.


push -f is the thing. Requiring -f just makes you think twice before accidentally exposing the rest of the world to your changes without merging them.


Your use of the words "intuitive" and "revert" in this context betray that your models are driven by how you expect centralized version control to work.

While Git and Mercurial are nearly isomorphic in implementation, their UIs differ significantly because they're written with different models of DVCS in mind.

Basically, I would argue you haven't fully grokked Git. To the extent that I have understood Git's model, I have found it extremely insightful; if you want this insight, you should spend a little more time trying to understand it before giving up on it.


As a long-time TA for the class leading up to 15-410 (almost as long as he's been a student at CMU) I can firmly attest to the fact that we have done absolutely nothing to make him aware of centralized version control (or distributed version control...) :)

So basically, he's got the freshest possible eyes to make this judgement, and if your counterclaim is that he hasn't truly grokked it yet, then that suggests that it may be counterintuitive.

Additional fairness: the project in question is a 6-week round-the-clock code fest. Writing a kernel from scratch takes forever. (Is this project just a waste of time? Having moved on to poking at the Linux kernel and stuff, I'd say almost certainly, but that's a topic for another conversation.)

Most Sincerely, Alex "Found out the hard way that reset != revert" Gartrell


" if your counterclaim is that he hasn't truly grokked it yet, then that suggests that it may be counterintuitive."

You should say, "it may be counterintuitive to him". Intuition is based on past experiences and our internal metaphors. We have no reason to believe that his "intuition" is the same as most of the population that would use git.


> if your counterclaim is that he hasn't truly grokked it yet, then that suggests that it may be counterintuitive.

Or proper usage wasn't explained to him correctly.


Since we learn from the online docs, doesn't your statement imply that Gits online documentation isn't very good?


> Since we learn from the online docs

That's an assumption.


wmcc stated he was in the same OS class as the blog poster.


git is the first revision control system I've used where "revert" actually does what I "intuitively" expect it to: begin a new commit that reverts a commit in the history.

The rest of the clown-car VCSes use "revert" to go back in time to that commit in the history.


Clearly, you don't know your clown-cars.

Mercurial uses hg backout to start a new commit that backs out a previous commit, hg rollback to undo the previous transaction (without a separate commit), and hg revert does undoes the uncommitted changes in your working directory, very similar to MS Word's (now defunct) and Photoshop's (still active) File > Revert command.

To me, revert means "revert all my changes to the last saved version", which is exactly what Hg does.


I had another sentence in my post that I edited out that was a caveat to Mercurial: at least it's possible to get the 'git revert' behavior with hg without implementing it yourself from a patch-series dump.

To me, revert means "stage a new commit that reverts this commit in the history as if it never existed".

When I first used svn, I really expected 'revert' to mean "revert this commit". I also 'intuitively' expected it to have something like git's index, and ended up just working around that by just laboriously creating my own set of patches to feed it in another checkout. Not everyone's mental models line up — we are both free to consider one another as a moron (see also: politics, religion).


It will be interesting to hear what he thinks of Mercurial after running into some of its warts.

I think it's valuable to read the opinions of people who are just getting into this game. Those of us with lots of experience with the everyday tools of the trade might not see a lot of substance to this critique, but it's important when designing any product to make sure it's approachable for novices. There's often a tradeoff there for power or flexibility, which git has been unwilling to make (probably rightfully so), but it does seem that things could be done to make the tool easier to get into, without necessarily compromising its power.


It's not a trade-off of power or flexibility as much as it is a difference in priorities. Git puts all of the powerful -- and potentially dangerous -- tools front and center (history editing, to name a big one), whereas Mercurial supports all of the same functionality, but hides away some of the more dangerous tools until you're ready to enable them.


If I understand git right, it's designed to allow different front ends - the "porcelain." I wonder if an alternative "porcelain" could be made which would be more intuitive to some?


It was made several years ago, near the birth of Git, called cogito. http://git.or.cz/cogito/ . It's currently deprecated.

It was how I learned Git actually; it made the UI very similar to mercurial's UI. It was actually a surprisingly good learning curve, because it allowed me to experiment with git commands side-by-side with cg commands on the same repo, and I slowly transitioned out of cg into full-fledged git, almost without noticing. I'm a little sad it's not maintained.


Very like Mercurial eh? I wonder if it'd be worth someone's while to pick it up & maintain it.


That thought has been in my mind for some time... maybe one day I'll actually get annoyed enough to write a nice wrapper. Where nice is subjective and == like svn and mercurial, with sane defaults (so no options are needed most of the time) and completely redesigned 'remote'.



I just read the 'intro' presentation ( http://people.gnome.org/~newren/eg/presentations/git-introdu... ) and I have to say I am really excited to try easygit out. It stays very similar to the way git operates, but it seems to make the default actions far more logical to me. Even as someone who has spent time trying to 'master' git really appreciate this effort.


I tried eg - but unfortunately, it's a leaky abstraction. As soon as something went wrong (and to this day I have no idea what), I was confronted will full-on git errors, suggesting I use git commands to fix them.


This seems to be less about Mercurial vs Git, and more Jon Chu vs Git.

Although I haven't used Mercurial, all of the issues he brings up I found really easy to solve when I started using Git (~2 years ago). The number and quality of online resources has only improved since then.


I believe the preference of one system over the other is based mostly on how they feel to the user.

Git is like a swiss army knife. git checkout can do just about everything and anything. Mercurial seems to be more split. hg update and hg revert do separate things.

Again a lot of preference comes down to personal feel. I prefer modularity. Others may prefer one tool solving it all.


Apropos of your comment (and possibly the source): http://stevelosh.com/blog/2010/01/the-real-difference-betwee...


Grb gives you wings:

http://grb.rubyforge.org/


grb will help you create and manage remote branches. Why something like this isn't baked into git, I don't know. I'm just happy grb exists!

  git_remote_branch version 0.3.0

  Usage:

  grb create branch_name [origin_server] 
  grb publish branch_name [origin_server] 
  grb rename branch_name [origin_server] 
  grb delete branch_name [origin_server] 
  grb track branch_name [origin_server]
There are also plenty of aliases for the various actions.

  create: create, new
  delete: delete, destroy, kill, remove, rm
  publish: publish, remotize, share
  rename: rename, rn, mv, move
  track: track, follow, grab, fetch


You don't have a personal preference, you're just ignorant.

Okay, now no one has to comment anymore; I've taken care of all of it.


Troll




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: