Hacker News new | past | comments | ask | show | jobs | submit login
What I Hate About Git (steveko.wordpress.com)
417 points by gammarator on Aug 4, 2012 | hide | past | favorite | 301 comments

I found the #1 reason to be incredibly ironic:

> The information model is complicated – and you need to know all of it. As a point of reference, consider Subversion: you have files, a working directory, a repository, versions, branches, and tags. That’s pretty much everything you need to know.

SVN's model is both simpler than stated here, but also much more complex to reason about. First of all, svn doesn't have branches or tags, it just has directories with cheap copy—tags and branches are just directories. The repository itself is also watered down pretty severely because the actual project directory is just nested in there somewhere with no formal locus. This idea of "everything is a directory" sounds simple, but in practice it's a architectural dead-end. The most obvious implication is that merging in svn will always be fraught with peril because a branch isn't a first-class citizen.

I used svn (and cvs before it) for much longer than git, and yet I never felt I had any clue what svn was doing under the hood, and the experiences I had over time instilled a fear of attempting to stray off the well-worn path of the most basic commands.

Although the learning curve was steep, and the CLI quite confusing, the git information model is actually much easier to grok because the primitives make more sense. After 6 months using git, I had a firmer grasp of the internals than I did after 10 years of cvs and svn. The idiosyncrasies of the UI don't really bother me because they are just superficial flaws that are easily memorized or looked up. The fact that I have the confidence to slice and dice commits to any history I can envision, with or without a network connection and remote repo, and do so with the reasonable confidence that I will never lose anything (reflog) make git the best VCS I can imagine.

I fully agree. SVN traditionally had some things that simply didn't work, often related to file renames.

I remember trying to rename a file after 'svn add' but before 'svn commit', and it simply didn't work. Maybe that's fixed now, don't know. Or merging stuff when a file was renamed in one branch and changed in the other.

During my several years of SVN usage I have regularly driven SVN checkouts against a wall, where I didn't manage to recover them into a usable state, not any combinations of revert, update or other commands. This has never happened to me with git.

With previous VCS I couldn't understand the limitations, with git I don't see limits.

I have exactly the same experience. After 3 years working with svn I still hard problems reasoning about the data model and what for example a merge would do, while after just 2 months I understood git way better than I ever had done svn.

Most of his list could easily be changed to be about svn instead. svn has a bad data model, svn has incomplete and poorly written man pages, in svn you need to run many commands to do simple things, svn has illogical command line parameters, ...

>SVN's model is both simpler than stated here, but also much more complex to reason about.

Well, sure, but if I understand his intent it's to demonstrate that Git's not hugely superior in clarity to freaking SVN.

I don't think he's defending SVN, though I'd only be completely sure of that if he mentioned hg at some point.

Number 1-5 are mostly "I don't want to learn new things", so I'll ignore them. Do you remember when you learned source control for the first time? I don't, it was too long ago. Just like you have to learn SVN if you've never used source control before, you have to learn Git if you've never used distributed source control before.

* "Unsafe version control", and then gives examples using -f or +<refspec>, both of which advertise their destructive nature. Yes, you can also go in with SVN and obliterate history too, using svnadmin dump and svnadmin load. Git's reflog will have your back when you make mistakes, as long as the mistakes don't get too old.

* "Power for the maintainer, at the expense of the contributor" Yes, most people write code on one branch for a long period of time. Git does this just fine.

* "Burden of VCS maintainance pushed to contributors" First of all, nobody says that contributors have to merge. That is a decision that each project makes. Plenty of projects have the lead developers merging in everyone else's work. Second, the reason this is even an issue is because merging is such a pain in SVN that most people don't want to do it.

* "Git history is a bunch of lies" Again, this is up to the individual project. Some developers like to work on six different things at the same time, and then they go back and rewrite history so that their six changes end up as six commits. The difference with SVN, is that these same developers would simply avoid committing until they're done with all six changes. Some projects expect rebased patches, some prefer proper merges. Worse, the author says that "filtering" should solve this problem, but doesn't propose how such a filter would work.

* Complexity of simple tasks: Let's try not to artificially inflate the complexity of the Git tasks. For example, the Git examples assume no commit access, whereas the SVN examples assume direct commit access. If you don't have commit access to an SVN project, how do you do it? You either use git-svn and mail them a patch, or you use svn and mail them a patch.

A recurring complaint seems to be that "git add" is not the same as "svn add". I don't see why it would be. It's not the same as "ssh-add" or "useradd" either.

Like others, I think telling people to RTFM is unhelpful.

The OP already pointed out that the official Git documentation is bad, bad bad. So, already it's not just "RTFM" but "Google around for a decent Git tutorial and hope you pick the right one." Great.

Add to this the fact that the Git commands are simply poorly designed. Yes, it is possible to understand what they do after expending a significant amount of time simply learning to think like Linus, but why should we have to do that? I refer you to the gitref.org entry for 'git reset':

git reset is probably the most confusing command written by humans. I've been using Git for years, even wrote a book on it and I still get confused by what it is going to do at times. [0]

This is not a problem of people not wanting to learn DVCS concepts. This is simply people who don't want to jump through a set of arbitrary, confusing, and completely unnecessary mental hoops in order to get to the DVCS concepts they wanted to use.

[0] http://gitref.org/basic/#reset (gitref.org is maintained by GitHub)

> The OP already pointed out that the official Git documentation is bad, bad bad. So, already it's not just "RTFM" but "Google around for a decent Git tutorial and hope you pick the right one." Great.

I have a hard time believing that there are scores of software developers out there who have learned their craft enough to want source control but are somehow overwhelmed by the basic task of finding a good Git tutorial.

The real impediment that I've observed is developers that certainly could learn Git but don't because they don't see it as a good investment. That's where they're so, so wrong. Git is like power tools for your code. If you embrace and learn it, you'll be much better off for it. Yes, SVN is easier. It's also a lot less powerful.

And there's always Mercurial, which is very similar to Git and addresses some of the confusing-API criticism.

The problem with git isn't following a tutorial, the problems I have had are nasty corner cases. I have to keep looking up strange a-symmetries, like why does 'git push' push just the current branch, and 'git pull' pull all branches? Then I have to look up how to make 'git pull' pull just the current branch.

Also, due to inconsistencies in how commands take branches, I sometimes realise I have a branch called 'origin/stuff', when I meant to do something with stuff on origin. It's also hard to find which branches are tracking what. Of course, you can find the options to do all these things. But there are just so many little things to learnt.

The fundamental question is, does the complexity of git come from the power it offers over svn, or does it come from the most terrible UI I think I have ever seen on a command line tool? I think it is the second.

I still use git every day, but I think it is putting usability by less computer-savvy users back years.

> like why does 'git push' push just the current branch, and 'git pull' pull all branches?

It's the opposite, "git push" pushes all branches and "git pull" only pulls the current branch. I think it's because push will only do fast-forward merges while pull will do any merge, and that could require a working directory to exist (but why not make push just push the current branch?)

Sorry yes, I got the asymmetry the wrong way around :)

The problem this causes (for me) is that if I have commits in other branches, 'git push' will fail (as other branches can't be fast-forwarded), but 'git pull' won't fix it. Of course, I can get around it, but it's annoying.

You can configure `git push` to push just the current branch to its configured remote, by setting 'push.default' to 'upstream'.

`git config --global push.default upstream`

The relevant docs (droplr'd, since you can't anchor-link into the online manpages): http://d.pr/Rlqn

What you mean when you say "you can get around it" is just specifying the branch you want to push. Just sayin'. It's not like you have to muck with settings and jump hoops.

The git maintainer is trying to fix this asymmetry by making "git push" only push the current branch (rather than all branches). It's a slow process to change the defaults in something as widely used as git because doing so breaks scripts.

See the new destined-to-become-the-default "simple" mode for "git push" in these release notes: https://raw.github.com/git/git/master/Documentation/RelNotes... .

> why does 'git push' push just the current branch, and 'git pull' pull all branches?

What version of git are you using? "git pull" definitely just pulls the current branch. It will fetch all the other remotes, but will only pull the current branch.

Which kind of makes sense, because you don't normally want to pull in all branches, just one particular be, but you often do want to push all your branches.

"...but are somehow overwhelmed by the basic task of finding a good Git tutorial."

Ummm.... when you don't know the tool, you're not in a good place to judge what a 'good' tutorial is. This is the same reason we've got generations of bad PHP developers out there - they can't tell what's good or not.

"scores of software developers out there who have learned their craft enough to want source control"

How many people 'want' to learn source control, and how many people are told 'this is what we use here, go learn it'? I suspect far more of the latter, especially with git. People would not flock to git purely based on the documentation quality. Further, I suspect that had git just been written by some random dude off the street with no major project behind it, it would have never taken off. Using it for Linux kernel work has ensured a sizeable number of people are going to have to use it, whether they like it or not.

How many kids want to go to school and how many are told by their parents that 'this is what you do so you can be happy and successful later.' I suspect more of the latter.

But like leaning Git, earning your education will pay off. Does that mean Git is without flaws? Of course not. And if you want to work to improve it, and release a better version, go for it. But anybody that sticks with SVN and refuses to learn modern DVCS is not somebody I'd hire.

Maybe this is a problem on IT-department, line-of-business teams (where most software developers work) but if Bay Area tech companies are a leading indicator, a big majority of Engineers I work with use and love DVCS's like Git and HG and there's not this groundswell of resistance.

And while this isn't related to my previous comments:

To anybody who has tried Git and ended up "losing work" because of a misunderstanding of the commands, let me assure you: It's actually a lot harder to lose work than you think.

Anything you add to the Index (eg git add foo.py) or commit is stored in the Reflog (which is just a DAG). The reflog is garbage collected periodically -- see below for details. Within that window, you can recover any lost state from the reflog.

So how long does Git keep things around by default?

Intermediate products of conflicted merges - 15 Days

Unreachable commits (do a git reset --hard HEAD~1?) - 30 Days

Intermediate products of a resolved merge conflict? - 60 Days

Everything Else? - At least 90 days.

> But anybody that sticks with SVN and refuses to learn modern DVCS is not somebody I'd hire.

You wouldn't hire me. I'm OK with that.

I use git (required for an assortment of OSS projects), but for my own work, at at work, I use SVN. I'd never willingly choose git.

It's complex, involved, powerful, and incredibly distracting from the actual thing I want to do, which is write software.

The minute someone says something like this, my eyes glaze over: "Anything you add to the Index (eg git add foo.py) or commit is stored in the Reflog (which is just a DAG)."

Not because I don't understand git's fundamental model, or I'm unfamiliar with a DAG, but simply because I SHOULD NOT HAVE TO CARE.

My job is to write software, not operate heavy revision control machinery to some arbitrary level of dvcs revision control fetish perfectionism.

I don't want to hide my work from my coworkers, I don't wind to hide my work history from my coworkers, and I don't want to maintain wildly diverging branches (the cost of branches is primarily found in code divergence, not SCM headaches). Git isn't for me.

You sound like you've got a "production line" mindset. "This is my narrowly defined job, I'm not interested in learning new things, I just wanna do what I'm paid to do and get out."

That's fine and all, but I want to work with craftsmen. People who give a shit about their trade, love their tools and relish in the oportunity to learn something that will help them do their job better. I wouldn't hire you.

"I want to work with craftsmen"

And craftsmen are picky about their tools.

Git has a terrible, terrible, command line UI. It's entirely possible to do distributed source control with an easy command line interface: Mercurial. I've never had trouble teaching people how to use it, and I've almost never had to sit around scratching my head, wondering what arbitrary set of command line arguments I need to pass to it.

Maybe git is the most powerful chainsaw ever devised, but the fact that so many of its users are either covered in bandages or fastidiously studying man pages and googling proper usage so they don't end up covered in bandages is not a good sign.

I really like Mercurial, but even with it I've had some trouble getting the other developers I work with to really understand it. I could not imagine trying to show them Git. I think those who have mastered Git are blinding by how Smart and wizard-like they feel.

I also think its worth pointing out that many of the people here complaining about Git (including the OP), use it very frequently. These are the people who have bothered to invest the time in learning the tool and hate it anyway.

I'm fine with learning new things. I do use git on a number of projects: I just don't think it helps me do my job better.

The job of a SCM, in my opinion, is to be as invisible as possible. Record my commits, and then stay out of the way of what I'm really here to do: write code, architect systems, engineer products.

Futzing around with an overly complex revision control system doesn't help me do a better job.

This is also why I switched from Linux & BSD desktops to Max OS X. I can still write an XFree86 config file by hand, and the fact that I spent time and effort learning this is mind bogglingly awful.

I almost had an heart attack after doing `git push --mirror`.

It deleted 95% of branches locally and on origin without leaving much of a trace, or any way to undo (well, none that i know of).

Good thing I had a clone on a machine at home, so I drove home, made local branches for each remote branch and then pushed each.

So yeah, there might be a way to get that stuff back, and I don't even have experience with non-DVCS, but the lesson I learned a long time ago with darcs is that you better have up-to-date off-site backups of your repositories, never trust yourself or your DVCS too much.

The upside is that keeping backups is easy, and good practice anyway, so if you're not doing it yet, don't wait.

My worst experience on that front was with jekyll.

Running jekyll without parameters compiles the source in the current directory, putting the output either in $PWD/_site, or wherever the config file for the project says.

I was in the parent directory, and thought I'd try to run jekyll projectname rather than having to cd in and out of the project.

The end result? It tries to compile the project in the current directory, writing output to the directory specified. As an added bonus, it completely nukes the target directory, including the .git subdir. And to add insult to injury, $PWD didn't even contain a valid project, so it error'd out immediately after wiping out the entire source.

The morale of the story: Always keep offsite backups.

I started out with VCSes with bzr, which spoiled me very much, as everything's straightforward, it does whatever I want it to do, and it just works. I then moved to git, because it was much faster, but I couldn't handle it. Which command does the equivalent of "bzr revert -r -3"? What do I do to unstage things? What if I want to only revert some files? I don't even remember which of these things I know, because git threw random errors about things while running commands that were supposedly straightforward, or did things I didn't expect.

I tried hg for a time, which was much better, but in the end I went back to bzr (hg confused me in merging, with it thinking that "what is this three-way vimdiff window with all the colors? I'll just leave this and examine the files one by one" meant "okay, everything is correct now"). It interoperates with everything, and it's the sanest of the three, so why wouldn't I use something that just works, rather than fight my tools?

> Which command does the equivalent of "bzr revert -r -3"? What do I do to unstage things? What if I want to only revert some files?

git has well-documented and simple commands to perform these operations (except if you're talking about reverting some files in a commit, that's not a thing git does afaik? though it might, but I doubt it would be straightforward).

If you're confused by hg & git and just wound up back where you were it sounds like you just didn't have the patience to learn a new tool. Either that or you failed to evaluate what each tool did before you tried switching.

\sarc{bzr revert -r 3? What does that do? Jeez, bzr is so confusing.}

I don't think git's CLI design is that bad, but the commands for quotidian usage are hidden among a large and confusing array of commands for which serve to make git more powerful for the experts. This is also where the manuals are confusing: all the commands are listed, and beginners don't know where to start. It's like a woodwork hobbyist walking into the workshop of an expert carpenter and wondering where in the hell the hammers are.

As for subversion, try using it for branching and merging many parallel versions of code for very long and you'll welcome the arrival of git like that of Jesus into a leper colony.

Stop defending bad design. We can do better than this.

Here here. Any design that needs to be defended so vociferously and causes so much confusion is clearly flawed.

Distributed version control is not as complicated as this.

Feel free to fork and make it better. Not sure what you want improved though.

Learning Git would be an investment with a much lower cost if it wasn't so terribly obtuse.

I don't see that it's obtuse. If you learn the basic concepts (as you have to do when you are a beginner to subversion or CVS) then you shouldn't have much of an issue.

Now why would that be voted down? Obtuse means "mentally slow or emotionally insensitive", so that could hardly have been what was meant. I assume that by "obtuse" you meant "hard to understand". So I stand by my comment that if you learn the basics then it shouldn't be that hard to understand!

yb66 - you are hellbound. Not sure why the OS X dictionary would consider obtuse to be the same as abstruse (that's wrong!), but at least I now know what is really meant. Which is what I had assumed was actually meant (if you followed my original comment, then that's what I said!).

Tried to learn the basics to manage the code for my thesis. Gave up widely confused. After trying to revert changes, I went back to it, this time trying eGit and playing with the commands. Managed to get it to work, but still struggling with branches and merging of changes into master.

The whole time I was thinking if I'm stupid or talentless.

The discussion here showed me that git is indeed far from perfect.

> but _why should we have to do that?_

This is exactly my feeling. Sure, I can, but why should I? I just want to get work done, not become a git fanboy.

The place I work at compared DVCSs and chose mercurial, and I'm very happy, I've never looked back, and heres the point... I really have no understanding of HOW mercurial works. It just works.

> Number 1-5 are mostly "I don't want to learn new things"

Git has a lot of wonderful properties, but it has horrible usability. Things like rebasing, remote branch tracking and push/pull, merge conflict resolution, stash management, and reverts are straightforward concepts! Once you grasp the concept of distributed VCS, those things should be a joy to use. But the standard Git CLI and most interfaces to it basically just drop everything on the floor and tell you to sort out the mess yourself as soon as something non-trivial happens.

This learning curve has no reason to be so steep. There need to be clearer explanations, better discoverability, and better interactive modes for all of the things I listed, and more. Telling people to RTFM just misses the point.

This is not to say that the OP makes a particularly coherent point. Just that the overall sentiment has merit.

  > Telling people to RTFM just misses the point.
To be fair, most of these "git sucks" posts in the past have been people moving from svn and complaining that git doesn't do it the Right Way(tm) "like svn does." In most of these cases, it has boiled down to:

1. I tried to use git like svn without attempting to do much learning at all and it bit me in the ass.

2. svn does things The Right And Only True Way(tm) and git doesn't, therefore git sucks.

3. svn has a command named 'svn <action>' and git has a command named 'git <action>' but they do different things. Therefore git sucks because (obviously) svn has the One And Only Correct Definition of <action> that 'makes sense.'

The other arguments amount stuff like:

1. I use mercurial all of the time and I don't understand how anyone can use git because of <filter-branch | commit --amend | rebase --interactive | etc> that allows you to rewrite commits. If people are allowed to rewrite commits, then obviously all developers using git do things like rewrite the X year-old commit that introduced the bug rather than creating a new commit to fix the bug. <Here is where I continue to rant about how scary the ability to rewrite commits is while demonstrating that I have little to no actual experience with git, or a single bad experience that I'm extrapolating from>.

In general, I find that I can empathize with people that get worked up over "git sucks" rants, because for the most part they either make no compelling arguments, or they bury a couple of compelling arguments under a ton of unstructured ranting about strawmen.


I'm someone who is neither unwilling to learn, nor attached to how Subversion did things. And I dislike git.

Superficially, I dislike it because it seems very little thought has been put into giving it a coherent interface. TFA points out instances of this, and it's true: whether something is implemented as its own command or as a flag to another command sometimes seems to have been decided via dartboard rather than any sort of intelligent process.

I also do intensely dislike git's own man pages, which are the first thing I'd ordinarily turn to. Unfortunately, the concept of an acyclic graph has not yet arrived in that part of git.

I dislike the way git overloads "branch" with multiple meanings or, rather, forces end users to do so. Mercurial does a better job of this currently, and has built-in support for the most important case (bookmarks vs. branches, in hg's terminology).

I dislike the fact that every repository and every branch is on equal footing except for all the commands that work differently with a remote branch or require you to do extra setup before they do work.

I dislike the fact that side-by-side inspection of different branches requires me to jump through hoops, since git only wants me to see one branch at a time. SVN, for all its faults, at least got that one right -- I can actually see two different branches, at the same time, using tools that require no knowledge of anything beyond my filesystem.

I dislike the fact that even people who use git day in and day out still can't seem to agree on a workflow. And I'm not just talking about things like whether rebasing is fashionable this week, but very basic things like when and how to branch.

I also agree with the article's point about contributor workflow; git and GitHub are more complex for contributors. There's also very little that's "decentralized", since GitHub is full of canonical central repositories, which makes me wonder what we gain from pretending we're using the "D" in "DVCS".

And that's really just the tip of the iceberg.

Superficially, I dislike it because it seems very little thought has been put into giving it a coherent interface. TFA points out instances of this, and it's true: whether something is implemented as its own command or as a flag to another command sometimes seems to have been decided via dartboard rather than any sort of intelligent process.

The examples given weren't illogical. The author's examples were git pull, which he complains is a git fetch followed by a git merge... which is quite logical, given that to pull from a repository you must first fetch the files, and then merge the files into your repository.

The second example that he complains about git commit not commiting a file if it's not specified on the command line. This makes sense, as you need to explicitly add the files via git add - something the documentation makes clear. As one of the complaints is that the documentation isn't clear, I think it worthwhile mentioning that the git-commit man page specifically says:

  The content to be added can be specified in several ways:

  1. by using git add to incrementally "add" changes to the index before using 
     the commit command (Note: even modified files must be "added");
  3. by listing files as arguments to the commit command, in which case the 
     commit will ignore changes staged in the index, and instead record the 
     current content of the listed files (which must already be known to git);
  4. by using the -a switch with the commit command to automatically "add" 
     changes from all known files (i.e. all files that are already listed in 
     the index) and to automatically "rm" files in the index that have been 
     removed from the working tree, and then perform the actual commit;
The third example he used was that the shortcut for git branch and git checkout is git checkout -b. However, this makes sense because a branch doesn't populate automatically with any files and needs a checkout. Thus git checkout -b makes perfect sense.

Perhaps there needs to be a git branch -c?

I also do intensely dislike git's own man pages, which are the first thing I'd ordinarily turn to. Unfortunately, the concept of an acyclic graph has not yet arrived in that part of git.

I think some of the opening descriptions are a little terse, but not entirely sure what you mean by the acyclic graph comment... I haven't been able to find anything obvious in the man pages that references a man page that then references the original man page... of course, I might have missed something!

I dislike the way git overloads "branch" with multiple meanings or, rather, forces end users to do so.

Could you clarify what you mean? Branches have only one meaning in git!

I dislike the fact that every repository and every branch is on equal footing except for all the commands that work differently with a remote branch or require you to do extra setup before they do work.

Could you clarify what you mean?

I dislike the fact that side-by-side inspection of different branches requires me to jump through hoops, since git only wants me to see one branch at a time. SVN, for all its faults, at least got that one right -- I can actually see two different branches, at the same time, using tools that require no knowledge of anything beyond my filesystem.

Can't gitk do this? Genuinely interested...

I dislike the fact that even people who use git day in and day out still can't seem to agree on a workflow. And I'm not just talking about things like whether rebasing is fashionable this week, but very basic things like when and how to branch.

I really can't see that's a valid argument. Some folks need to branch differently than others. This isn't just a git thing, the same can occur in SVN. As has been pointed out, branching tends to be discouraged because merging can be a regular pain.

I also agree with the article's point about contributor workflow; git and GitHub are more complex for contributors. There's also very little that's "decentralized", since GitHub is full of canonical central repositories, which makes me wonder what we gain from pretending we're using the "D" in "DVCS".

I disagree. The github workflow might be a little tricky, but as has been pointed out there are other workflows possible in git. git != github!

Thus git checkout -b makes perfect sense.

Does it? Pull and then merge is a common operation; it gets a top-level command. Create a new branch from the one I'm working on and check it out is a common operation; it gets a flag on an existing command. What logical, coherent process decides that in each case?

Branches have only one meaning in git!

Hence the "forces end users to do so". There are two very common ways people use branches: one is as a temporary place to do a quick bugfix, the other is as a long-lived place to do a major rewrite or refactoring. With respect to the history of the codebase, these have very different implications, but semantically are the same type of thing in git.

To pick on Subversion: when you had a long-lived branch in SVN, sooner or later you'd merge it back into the mainline... and then what happens? You want someone to be able to look at the repository and see that something major happened here and easily watch the progress, but you also want a way to say "this is done and merged". This required inventing a convention to indicate that -- in SVN, typically the finished branches would go in an "attic" directory.

In git you face the same problem: making a temporary branch, doing the work, merging and then deleting the branch is what you're supposed to do in git. But for those long-lived major branches, you need to invent a convention (commonly, tagging the merge point) to indicate that they're done.

I mentioned Mercurial because it has two different concepts for these things: the ephemeral deleted-once-it's-done line is a bookmark (which is pretty much exactly equivalent to a git branch, in that it's a named head that moves as you commit), and the long-lived major branch is... a branch. Which has additional semantics to indicate things like being finished.

This means that in Mercurial you don't have to invent and re-invent ad-hoc conventions to handle common development patterns, while in git you do.

Can't gitk do this?

Every time I say I want to see two branches side-by-side without invoking the VCS, someone says "well, here's a tool that invokes the VCS to do that!" Which shows a lack of reading comprehension.

Some folks need to branch differently than others.

Sure, but why isn't there a clearly-documented "most projects will get along fine with this" workflow? Or, rather, why are there dozens of them? We've had VCS tools for long enough that the best practices for common cases are out there.

The github workflow might be a little tricky, but as has been pointed out there are other workflows possible in git.

Oh, there are. But git + GitHub has been relentlessly hyped as an Oatmeal-ish fantasy of unicorns farting rainbows onto a field of lollipops, so that's how people actually end up using it, and so it's valid to mention that it's a more complex workflow for contributors since it is a very common case and becoming more common.

Every time I say I want to see two branches side-by-side without invoking the VCS, someone says "well, here's a tool that invokes the VCS to do that!" Which shows a lack of reading comprehension.

I'm guessing you check out a branch to a particular directory, and another branch to a different directory, then do a compare?

You could create a directory, stash you uncommitted files, then checkout the branch ad do a recursive copy to the directory you want to do the compare in. Then rinse and repeat for the next branch. After this checkout the original branch you were working in and retrieve the stash.

You could easily script this.

I'm not necessarily asking for solutions at this point; I'm asking why the "solutions" involve jumping through so many hoops to work around the VCS in order to do something incredibly common.

Isn't this is the same as subversion:

svn co remote_repo_path/branches/bugfix bugfix git clone -b bugfix ./local_repo_path bugfix

It could be simpler if you removed the trailing target folder name (but git would name the checkout according to the repo name, instead of the branch name).

Joel Spolsky had the same concerns about Git when he first started using it. He changed his mind and wrote a great post on why distributed version control is way better than SVN.


He also happened to write a tutorial for mercurial that explains the same concepts. The tutorial is linked to at the very end of the article.

Hg Init: a Mercurial tutorial by Joel Spolsky http://hginit.com/

It's a pretty good tutorial. But to me the mere fact that there are so many posts on How-to use a tool that is basic in a programmers arsenal, tells me that DVCS are a solution that lacks usability.

Ah, so it's by Joel.

I tried Git but failed miserably with it. It could probably be attributed to the lack of quality tutorials at that time. I then thought, "Fuck it, let's try Mercurial" and stumbled upon hginit. That is one awesomely written tutorial. I use mercurial for my programming needs and find it totally intuitive to use.

I definitely found it easier than git, but that could be possibly chalked up to my bad introduction to git.

Personally, I think anyone familiar with cvs or svn can pick up hg really easily. The commands and concepts in hg map onto equivalents in cvs very nicely. My mental model of hg is just cvs + cvsync. Done.

git does not work like that. It's like each command was cut in half and recombined differently, like interlaced video or something. It's all there, it's just harder to recognize.

I tried Hg first and failed. Then I tried git and for some reason worked it out. DVCS concepts are hard when you're used to SVN.

Hmm. I can't really comment on that since I've never used SVN. I was kind of lucky to jump directly into DVCS. The reason why I'm comfortable with Hg is because at the initial/first step the only commands I was told to remember (by hginit.com) were `hg commit` and `hg init`. Slowly, from there I took on a steady pace and grew comfortable with it. Currently on Windows I use tortoiseHg and bitbucket (I'm strictly a hobbyist coder only).

When I tried to learn Git (before Hg), I looked for tutorials but everything was all over the place and maybe they introduced too much too soon. Anyway, at the end of the day I find Hg good enough for my usage - init, commit, push, pull so far.

We are talking about programming tools here, not tools for home kitchen chefs to track their recipes. A little intelligence and hard work on the part of the user is expected.

No that's just programmer masochism. If a tool is easy to use, then I get whatever I needed it for done, and done quickly. I can then move on to doing more interesting things (e.g. programming) rather than wrestling with the tool.

We are talking about programming tools here. A little intelligence and hard work on the part of the DESIGNER of the tools is expected.

Intelligence can be expected. Hard work should be unnecessary.

Interesting non sequitur.

Why do you say that?

Because it does not follow that if you are intelligent then you will not have to do any hard work.

Edit: appear to have annoyed someone with that comment! But do go on - prove to me how high intelligence means that you don't need to do hard work, which is the proposition of the OP.

I think his point was that software should be designed so that if someone is intelligent, they won't have to work hard (remember, "hard work should be unnecessary", em. mine). But he optimized for pithiness over clarity.

What on earth are you talking about? Git currently requires intelligence and hard work to learn properly. Regularfry suggests that we shouldn't need hard work to use a version control system. This statement isn't a proposition on the human condition, and doesn't need any proof.

Actually, I disagree. It took me no more than about half an hour to understand and use git properly. I don't particularly consider it to have been hard work.

As for it not being a proposition on the human condition - I mistook what he was saying, but then after it was clarified I understand what was meant. It was unclear to me what was being said - interestingly enough, that is the entire argument being expressed for the reason why git is "hard work".

> Because it does not follow that if you are intelligent then you will not have to do any hard work.

I don't think anyone's said that, or tried to say it (least of all me), at any point.

You seemed to. You said "intelligence can be expected. Hard work should be unnecessary". What did you actually mean? I apologise if I misunderstood what you were saying!

I'm saying that while it may be valid to assume intelligence on the part of your users, that doesn't make it valid to make them work hard. I'm not saying that intelligence gets you out of hard work, I'm saying that it shouldn't necessarily get you into it - and from where I'm sitting, git requires both where it should only require one.

Ah. I'm following you finally. Yes, I agree that unnecessary hard work shouldn't be needed.

Really? How many how-tos are there on text editors, programming languages, build systems, deployment systems, unit testing frameworks, frameworks, APIs, libraries, debuggers...?

I spend at least an order of magnitude, if not several, more time with each of those things than I do with a goddamn version control utility.

I put in effort where it's worth it. Version control doesn't even come close to hitting the top of that list.

You build and deploy ten times as often as you commit? Apparently you really don't think version control is worth it!

He said he spends ten times more time on building than on managing revision control. That doesn't mean 10x more deployment or development.

On the other hand, I can tell you we have almost 10x more downloads than we have svn commits ;-)

There is very little that is hard with managing your source code on your local workstation.

To commit any changes, you type in:

  git commit -a -m "thing that I changed"
To branch, it's:

  git checkout -b newbranch
To switch back to the master branch, you just type in:

  git commit -a -m "changes made on branch"
  git checkout master
To merge in that branch, should you so wish to do so, then you type in:

  git merge newbranch
What is exactly so hard about that?

"Way better" at what?

The thing that people need to get through their head is that distributed version control is a whole different concept. There are some things it is great at. There are some things it sucks at. Centralized version control is great at some other things, and lousy at some other things too.

I am thinking for example that if you are going for a PA-DSS-certified application, git, particularly with the ability to rewrite history, is going to be a problem, but dvs generally will provide more problems in assuring the auditor that you can locate, trace, and take corrective action if someone introduces a security issue (perhaps intentionally) into your application. I don't see git really working in that environment.

On the other hand, if you have a lively project that everyone is experimenting with and you need to merge patches occasionally to create a stable release, yeah, it's much better.

Why would dvcs cause problems for auditors?

For any given project, no matter how distributed the development, you will have a "blessed" repository, from which the official releases are made. The history of this "blessed" repository is made not rewritable, even if anyone can push new stuff to it. The config files and hooks can be made writable by only admins.

Or you use a maintainer model, where the "blessed" repository is not even pushable. A maintainer (or a group of them) chooses what he merges in.

A post why DVCS are better than SVN doesn't state anything about the qualities of git (unless it's actually about git, of course).

I have concerns about git and used distributed version control years before git existed.

I use mercurial all the time even when I am forced to interact with git projects (thanks hg-git!) and I have no problem with rewriting history. What I do have problem with is atrocious CLIs that require you to remember cryptic incantations to do the simplest things. Two anecdotes:

- Colleague #1 has become sort of comfortable with git but only after heavily customizing gitconfig and setting up a dozen or so aliases for the most common commands.

- Colleague #2 is a devops, lives and breathes inside the command line, and still uses a GUI instead of the cli for git.

So you have had good luck with hg-git, then? Does it play well with github?

I've read mixed reviews... I'm OK with git but am deeply displeased with how difficult the learning curve is for a casual user. I'd much rather that Mercurial won.

Here's the thing though. I have been using SVN for years and am not learning Git. For a long time I figured I was just disoriented and eventually it would come. Now I am less convinced. The article really described my experience pretty well to the point where I am thinking the only sane way to use git is along with subversion.....

In essence, the more I learn, the less I like it, and the more convinced I am that it isn't what I need right now. Building accounting software there are certain things I need in a revision control system. These are:

1) revision control as audit trail. I need to know who committed a change and I need an audit trail on that. SVN isn't perfect here. I'd like to be able to audit changes to commit logs too, but that's pretty minor stuff.

2) collaboration among a smallish number of committers (right now maybe 4 active at any given point in time).

Folks have pushed git because it makes it easier for users to share modifications with eachother. That's fine, and it's a good point, but it isn't worth getting rid of a clear and reliable audit trail in order to achieve. To this end I suspect we are more likely to pursue a hybrid solution with all the complexity that provides (and indeed it is already partly implemented) than a pure git solution.

Allowing rewrite of commits is a problem not because developers might do it but rather because you can't show that developers didn't do it. If there is a question about whether a security issue was intentionally added to the code or not you need to have a clear audit trail. A basic principle of any audit trail is that your audit trails may not be overwritten.

Git version numbers are actually SHA1 hashes that are based on all the files and the entire history of the project up to there. If you modify the history in any way, then that will be a new version number and you know something has changed.

You can optionally GPG sign a commit/tag which, again, will be invalid if any part of the history is changed.

Just require commits that are signed off with GPG keys. Then you have a clean, verifiable audit trail through git. Beyond that, you'll have the full development history on your machine, which they can't just arbitrarily change.

Do you think that's more or less complex than just using svn-git to manage the authoritative audit-trail repository?

Less, managing two version control systems seems like insanity (speaking as one who's had to do it in the past). Having people sign their commits is dead simple in Git, and you could setup hooks to make sure every commit is signed before you accept it.

An alternative (or additional) solution is to setup a server like Shawn suggests in this e-mail: http://git.661346.n2.nabble.com/Implementing-commit-signing-...

This actually is the usage scenario for which Fossil[1] was created (in fact DRH made it to be in accordance to some aviation industry norms, don't remember details). Furthermore, one of the ideas behind Fossil's design was to minimize the learning curve for someone who already knows SVN.

Disclosure: I occasionally committed something to Fossil.

[1]: http://fossil-scm.org/

Fossil looks promising. Thanks. I have bookmarked it.

Of course there was a typo in my previous post. I am "now" learning git, not "not" learning git.

I disagree with the very first thing you said. git has far more concepts that it just throws out at you than svn. I don't think it's fair to say they've equivalent. Even as a fairly long-time user who is quite comfortable with git, it is sometimes overwhelming. With svn, I basically had to know what a revision was, and maybe a branch, and that's about it. To use git effectively, I have to know about commits (and their graph-y nature), remotes, the concepts of pushing and pulling, rebasing vs merging, and if I'm reading the documentation, I am rapidly going to begin running into concepts like "refs". Of course the rabbit hole keeps going deeper, but a lot of that stuff you won't really need to know.

Personally I know what all these things are, and again I'm quite comfortable with them at this point, but there was absolutely a learning curve, and I'm reminded of it every time I start explaining something to a more novice coworker.

Also, for the record I like git a lot. But it's not immune from criticism.

I would further argue that #10 is wrong. He compares commits to a project you own to contributing to a project you don't own. If you don't have commit access to a svn server you are for the most part out of luck. Emailing the patch to a mailinglist or some dude is about the best option and even then it has a good chance of either not making it in or taking a very long time. So meanwhile you want to keep your changes going, how do you do that? A bunch of patches you apply every time you svn update? Run your own svn server, import their code and apply patches on that? What about merge (hell) time? Perhaps you do want commit access to the svn server. Just first mail this form via the post office to me or maybe fax the form and then after that first contribute 100 perfect patches and maybe then we will give you commit access. Ugg. Comparing this with Git where making your own fork where you can potentially make contributions from is _easy_ and you can publish this repo in many places.

Nothing against learning new things, but why defend user interfaces or workflows that are needlessly complex or unintuitive? DCVS is certainly a significant advance over centralized VCS, but that doesn't mean Git couldn't be made significantly more accessible. More readable documentation alone would have made learning git a great deal easier for me.

Number 1-5 are mostly "I don't want to learn new things", so I'll ignore them.

The whole post is about a system that is badly designed or implemented, making it unnecessarily complicated to learn and use. Not wanting to have to deal with unnecessary complications is not the same as not wanting to deal with necessary complications. People unfamiliar with good UX design can't tell the former from the latter.

If you find yourself confused and frustrated like the author, here's how to make git make sense:

1. Temporarily forget everything you know about every other system, and imagine they didn't exist, and that you have to solve this problem yourself. How might you do it?

2. Read Tom Preston-Werner's "The Git Parable" (http://tom.preston-werner.com/2009/05/19/the-git-parable.htm...).

Read it very carefully - the minute you start skimming, you'll start filling in gaps using your Subversion knowledge and be lost again. If you really want to understand, read this aloud.

Couldn't disagree more. Git throws too many unnecessary things at a beginner to learn. Sure you could read every damn book about git and learn it. But why should you in the first place? I don't know what it is with this attitude amongst so many nerds that "oh it's hard? you're not smart enough, just go learn it" this is not the attitude that pushes us forward.

This is absurd. It is a tool to aid the development of software. If you can learn a goddamn language, you can spare 20 minutes to figure out the extra couple of steps git can add.

I can tell you it took me a lot longer than 20 minutes to master working with git. Sure, you can tell someone how to clone, branch, commit and push in 20 minutes, but that's not really understanding.

For example, last month I was at a meetup, and had to help someone who was contributing to an open-source project. She had been following the project's instructions on using git, but was stuck. It turned out that she had hit a snag in the middle of a multi-commit patch that was applied with "git am" and as a result, her repository was in an intermediate state and the usual commit, add, reset etc. commands weren't working. I helped her back out to a clean state, but it took me several minutes of scouring documentation to do it, and I consider myself proficient with git. If I hadn't been there, I expect she would have given up on the whole thing, and all because git has some bizarre interactive processes that leave your repository unusable while in progress.

I think it's undeniable that git is unfriendly and obtuse at times, and the people who think otherwise are just examining it too close. They have mastered it, they see all of the justifications for each quirk, and because of that they can't see the big picture, which is that it is extraordinarily difficult for a new programmer to pick it up and be proficient.

So what? A goddamn language is easy compared to git - they all mostly work in the same way.

I don't understand this attitude. Why can't our tools be so easy to use that you don't need to read the instruction manual?

Conceptually, there's nothing that difficult about using git. I have some files that I want to be versioned. Yet, the commands are inconsistent and any non trivial operation requires consultation of a variety of tutorials.

Why do we have to settle for this? Why can't the tool be internally consistent?

20 minutes, hey? Not in my experience.

* "Unsafe version control"

* "Git history is a bunch of lies"

These come up time to time. If you need safe Git history, you're supposed to sign your commits with GPG. Git has built-in tools for that. Linux kernel and many other major projects use signed commits. In addition to keeping the repository safe from changes in the history, it will also protect you when your git server gets hacked (where Subversion will fail).

If I read one more blog post that brings this up, I will cry.

What comes to the squash/rebase/rewrite history part, it's a good idea to not commit any revisions that do not build and run to your master branch. If you push a revision that doesn't build, you'll have a harder time doing "git bisect" (you can skip broken builds, though). It's a good idea to squash and rebase before commit to master. Use git merge --no-ff if you want a merge commit in.

Git is alright. You can learn it just like anything else. Yeah, it could have been simpler. Agreed. It comes from Linus, who judging only from the talks I've seen online --don't know him personally, can be very opinionated and "asshole-ish" at times.

My pet peeve with Git is that it stopped once it supported Linux kernel-type projects. If you are working on anything other than that it is likely that you are going to run into all manner of non-text resource files and Git sucks at helping you maintain these. Case in point: Graphically intensive iOS apps.

The point of the article was, that git's UX sucks. People complaining is by definition bad UX. Experience, which people complain about, is not good.

> Number 1-5 are mostly "I don't want to learn new things", so I'll ignore them.

Then I take it you'll agree C++ is better than C?

Non-sequitur. My point is that if you assume C++ is just like C, you'll end up writing bad C++ code.

Good analogy to C++ vs C. C++ gives you a lot of power previously unavailable, as git does. And there seems to be no canonical ways to do anything neither in C++ nor in git. And that does confuse a lot!

I believe in the power of user interfaces, and I believe tools should be as easy to use as possible, and I dislike the "I don't like to learn new things" argument because actually, yes, your tools should make you learn as little as necessary to use them. But quotes like:

here’s a diagram illustrating the commands a typical developer on a traditional Subversion project needed to know about to get their work done. This is the bread and butter of VCS: checking out a repository, committing changes, and getting updates.

make clear that when this author says they're listing ten things git does wrong as a version control system, but what they're listing is ten ways git isn't Subversion, and I'm sorry, but maybe if instead of writing blog posts about how a tool's user interface wasn't like what you unfairly expected of it, you actually learned how to use the tool, you'd be using it right now to make something awesome.

What I'm saying is, I think I'd rephrase

Number 1-5 are mostly "I don't want to learn new things"


Number 1-5 are mostly "I'm going to blame my tool for me refusing to do the bare minimum to learn how to use it"

> Number 1-5 are mostly "I don't want to learn new things"

More like overcomplicated things. Git can be made simpler.

>Number 1-5 are mostly "I don't want to learn new things", so I'll ignore them.

Ignore them at your own peril.

"Not wanting to learn new things" is very different from "Not wanting to learn needlessly complicated mess of new concepts because nobody bothered to clean up the conceptual spaghetti".

Which is the case here.

Have people done hallway usability testing on git?

i.e. just take a smart undergrad CS major and record their screen (& audio) while they try to figure out how to use it. I think this would definitely turn up some tasks within it that are way harder than they need to be. Do people really feel confident that learning git is a smooth process, not involving a lot of swearing?

The answer you mostly hear when complaining about programming tools is that you need to toughen up - yet startups are founded on the idea of not doing this to their clients. Making processes super easy for clients is a good thing, and we should gather information, find the common problem spots, and fix them for our own tools! We shouldn't just keep insisting that the customer (programmers) needs to toughen up and learn (as the default answer, anyway; some things really are hard)

Why isn't there user feedback tool for man pages, where it asks "Was this information helpful to you?" every time you use a man page? I bet the success rate would be pretty low.

In general why isn't there any information about which man pages are good and which are terrible? They just seem frozen in time. Compared to the analytics startups get about their customers, info about man pages is nonexistent. Yet there are probably ones out there which would be rated "useless" 99% of the time, and have been for 10+ years with no change.

I think you bring up some good points of open source projects vs. commercial ones. In open source projects, most of the time when seeing critical feedback by users you see those "it's open source, just change it the way you want" comments. No one makes money, therefore no one depends on users being happy about the software. That's why B2B is so attractive: Your users actually WANT to pay you such that you are dependent on their happiness.

Maybe we should invent a new model that combines open source with paid incentives for user desired changes. Let's say User A uses Gimp, sees something that could be simplified or added. He can't program it himself but what he can do is describing the feature he wants, possibly with screenshots or even an interface prototype. He then auctions this on a marketplace website. Other users can upvote or even chip in to A's auction such that the probability of a good developer implementing it rises. Developers have their profile with reputation, possibly linked with their stackoverflow reputation. The change gets implemented within a branch of gimp, installable by anyone using a modified package manager. If the maintainers of gimp like the change, they can merge it in such that everyone profits - the number of user downloads being a good indicator that the change is desired.

I agree with you. Unfortunately one thing I keep seeing in the developer community that frustrates me is this competition-like demand for learning new things. Sure I love learning new things. But I don't like learning new things just for the sake of learning things. You look around forums and websites, every time someone's asking for help and is confused about something, the average response roughly says "you are a lazy ass and you should feel bad about yourself because you didn't read the 60 pages of manual someone else wrote, oh you are also not smart enough, go learn new things, look at all these command line arguments that I have memorised..." our memory and human resources are too precious to have to deal with this stuff.

This. There's two basic types of commercial software (yes over-simplification) turn-key or custom. I work for a shop that does the latter. If I brought software to our clients with the explanation: "toughen up, read the manuals, we adhered to your spec!" then we simply wouldn't get paid. Git or DVCS in general isn't this nature though and is turn-key like MS Office for example. If some part of Office was a usability nightmare most people would simply avoid it. Some may not purchase the software altogether if they were to say take a trial of 30 days and couldn't get passed File->Save As or some rote "simple" command. That is a trite example but the analogy isn't that far off base.

I will caveat everything by saying I have drank the Hg kool-aid and will be drunk for some considerable time. It wasn't that it was SVN-like, but as I explore more complex features on my own, my hand isn't slapped in the process. I've hosed repositories in Hg and SVN. I've fixed Hg repositories from codeplex that seem eternally broken given that is the "authoritative master". It didn't take any research at the time but I couldn't recall if the knowledge was entirely latent (i.e. discovered previously) or I had researched it at some point in the past to bring it up in the future.

I'm of the notion that if you can jump to any DVCS for the most part you're doing an excellent job. It doesn't hurt that there's hgsubversion or hg-git to make transitions easy but even the more obscure DVCS' are a leg up. I don't bash Git on some crusade, as I look at OSS projects and realize if they use it I probably should too at some point but the barrier to entry is inherently steep. I look to articles like this posted to hopefully stir interest in fixing the usability problem and it's extremely comforting to know that so many people share that it most definitely has a usability problem. I'm not the only derpy one here apparently :>. I really want to learn Git but I definitely do not want to be tasked as the Git-guru of my small developer team. We use a paid hosting firm that only has svn or git to choose from and I can get away with pushing people towards Hg with hgsubversion much easier than playing tech support.

Interestingly, in my experiance the chances that a random CS undergrad is comfortable with git is much higher than the chances of a random dev who has been in industry for a while being so.

I read this post and see a number of ideas that could be turned into products by someone enterprising enough to do it, and who honestly believes such a market for them exists.

Amen! I've felt like this for so long.

Ignoring the unnecessary parts about GitHub, he hits the nail right on the head with:

> Git doesn’t so much have a leaky abstraction as no abstraction. There is essentially no distinction between implementation detail and user interface. ...Its weakness is the complexity of simple tasks.

I swear, someone needs to invent a Git-wizard program. Interactive with a wizard-like interface, it will walk you through all the common kinds of tasks, even if they're fairly advanced, explaining all the ramifications along the way.

I haven't seen any programs like this -- all the GUI interfaces to git basically just translate to command-line commands, instead of trying to help you intelligently manage your workflow.

I don't think it would be easy to write a wizard interface like this -- it's a UI designer's worst nightmare -- but it would certainly help.

> I swear, someone needs to invent a Git-wizard program. Interactive with a wizard-like interface, it will walk you through all the common kinds of tasks, even if they're fairly advanced, explaining all the ramifications along the way.

Sounds like a great idea for making one type of workflow easy. The great part about Git not having an abstraction is that it supports almost any workflow. You can choose what flow is right for your project.

Which is, by the way, why the documentation is not task-oriented, it's data-model oriented. The same command might be used for two completely different tasks in two different processes.

Other tools that aim to make the basics for committing easy do so at the expense of implicitly supporting only certain workflows. Think of something like Perforce. You don't enforce your process with Perforce, you choose your process so that it will work with Perforce.

That's why I said it's a UI designer's worst nightmare.

Because there are a lot of different kinds of workflows, and I don't even know how you'd begin to organize them. I mean, maybe it's not even possible.

It would just be nice if it were more possible to "ease into" Git, rather than feel like you have to go through the equivalent of a college semester learning it.

> That's why I said it's a UI designer's worst nightmare.

This is the point where I think it's appropriate to link another front page article: http://news.ycombinator.com/item?id=4338845

I've learned Git about the same way I've learned *nix systems and programming languages in general: piecemeal, a step at a time, on a largely need-to-know basis. It's been 4 years now and I feel like a complete novice, but I rarely need to do anything other than (1) synching local with remote repo, (2) committing a change, and (3) using a feature branch.

Then maybe there should be tools that use git to create a specific workflow. What I have now is a text file with all the git commands I need to follow the chosen workflow. I don't have that for any other command line tools I use.

you mean bash scripts don't count? ;-)

Just because something is very flexible and supports many ways of doing something doesn't mean it has good UI and doesn't mean it has good discoverability.

I don't understand where you think I said it did. I specifically said it was a great idea to slap a better UI on git, but mentioned the caveat that to do a good job, the interface would have to be geared to a specific work flow.

Have you seen https://github.com/nvie/gitflow/ ?

It's a workflow level abstraction over git operations.

Upvoted because git-flow does address many of the points in the OP, but it's also an opinionated add-on that pushes users toward a particular workflow model that may not suit all applications. In my usage of git-flow, I've found that I still need to be pretty comfortable with the "raw" git interface in order to effectively manage everything, so it also doesn't really get around the weaknesses of git itself.

Exactly I feel the same way... and when one dares to say that git is unfriendly the answer typically goes along the lines of: "...is because you don't study it enough..." so just another expression of RTFM.

But the mere fact that there are so many How-to's on Git is an indication that is not an easy to learn system. But it should be since is one of the basic tools of a programmer. Or for a car mechanic how many manuals are there on how to use a wrench? For a doctor how many books are there on how to use a stethoscope?

As a counter-example, my great-grandfather, Morris William Travers, was the first director of the Indian Institute of Sciences in Bangalore and I gather that he said that he had to design the engineering curriculum there with a significant emphasis on learning how to use things like screw drivers and wrenches because the upper-caste Hindus were not familiar with these details of manual labor.

So I don't think that you can discount the cultural factors for our familiarity with hand tools. Certainly even in India, even in 1906, you wouldn't have had to teach a repair man how to use a wrench. But you would have to teach the engineering student. That's a bit of a humbling thought.

>>I swear, someone needs to invent a Git-wizard program. Interactive with a wizard-like interface, it will walk you through all the common kinds of tasks, even if they're fairly advanced, explaining all the ramifications along the way.


Git is far from perfect. But, there's roughly half bullshit, half "yes but is it really an issue?" things here to me.

Things like detailing the github process and blaming git just does not work for example.

Blaming additional git features that svn simply does not have.. is also nonsense to me.

Finally, you CAN rewrite history in svn, its just extremely painful. In git it's not and.. its a good thing. I prefer USEABLE history than trashy commits. And don't tell me its about having proper devs making commits. As pointed out, you get external commits in git. You can't control them without refusing them and then what? In svn you don't even have the possibility to refuse them.

Don't get me started on how svn is way more about the maintainer due to this...

> I prefer USEABLE history than trashy commits.

Yeah the other day I got into an extended debate about rebasing with another dev who just didn't get this. He maintained that it should not be possible to modify history because it all may be relevant later. I rebutted with a question: do you want a commit every time you type a character in your text editor? Version control is just another tool for code craftsmanship. You should strive to make your commits as atomic and well-described as humanly possible. git-add -i and git-rebase -i are tools that allow you to approach a more perfect history.

> I rebutted with a question: do you want a commit every time you type a character in your text editor?

I don't get it. I want a commit every time I say I want a commit, not upon arbitrary criteria the software decides for me. And I want that commit to be irrevocably and permanently immutable, because I said I wanted it and because it might be relevant later. What am I missing?

When you want a commit, you tell git to commit and it will commit.

When you don't want to revoke or mutate a commit ("irrevocably and permanently immutable"), you don't tell git to revoke or mutate the commit and it won't revoke or mutate the commit.

When you fucked up history and you want to change it, there are some simple git commands to do this and some very, very tedious svnadmin commands to do this.

Some of us fuck up history and want to change it. Some of us don't. Git serves both of us well. Subversion only serves one of us well. A lot of the time we have to use the same version control system, because we want to collaborate.

Additionally, if I have admin access to the SVN repository and rewrite history, how would you ever find out unless I told you about it?

In that sense Git has stronger support for immutable commits, since rewriting published history will actually cause everyone downstream to stand up and notice.

The thing most people seem to miss is that you can't actually mutate a commit in git. You can only appear to do so by removing the old commit and replacing it, and all of its children if it has any, with new commits.

If someone depends on your "mutated" commit, they will notice that it's gone, and you can deal with the issue.

The most common use for rebasing and commit editing is to make commits actually sensible.

Huge end-of-the-day commit-all-my-work chunks do not benefit anyone. The index and rebasing allow you to create commits that make sense, regardless of the state of the working tree. In subversion, this is a painful, dangerous and error-prone operation that involves manually using diff and patch. Git frees the developer from having to worry about when to commit.

smsm42 already said it, and you say you're still missing something, so I'll try another try another way.

If I want to work on some code locally, I might want to experiment and break things, and in the process of doing so I want the ability to commit and have the safety net of version control. That said, a lot of those experiments might be garbage, and I don't want to send garbage to my co-workers when I make a pull request.

So instead, I splash about in my local repo and make tons of commits and screw around with my experiments until they're fully baked, and have tests, and comments and docs and so on. Then I can use rebase to clean up that mess and present them with something atomic and contained that makes clear what I really wanted to publish. The garbage can be tossed from the history or it can be kept around locally, but at least I'm not asking my colleague to trudge through my own thought and work-process.

Does that not sound like a worthwhile feature? If it doesn't that's pretty cool too, you don't have to use rebase at all. Feel free not to, Git works fine without it.

Git's commits are immutable (their identity is an hash signature of their content, they can't be changed), what you want are non-removable commits, ie forbidding the user from moving refs to a commit that isn't a descendant of the current commit.

In practice this is what happens when you share your commits with the world (through push or someone pulling from you). As long as some commits are only in one computer git lets you happily nuke them, but why should it be otherwise? No one can force you to publish your commits anyway, you can always make a new clone and rewrite history there...

Actually you can make something more or less like that by signing a tag, and, as you pointed out, releasing it. this makes it convenient to check that no previous commit as been removed, as git signs a hash of the tag which is a hash of all the hashs in the history

(the tag can still be deleted, but just to show the convenience added)

I don't want anything my computer ever does to be irrevocable. If you want to always commit one at a time and never change them, that's fine - you can just never rewrite your history. But for many people rewriting history is useful, because it's easier to see what the correct commit boundaries in your change are after you've done the whole thing. That git allows these people to do that can't possibly be a disadvantage to using git.

Right, so the greater point I was getting at is that committing is something under the programmer's control. It's not "sacred history", it's all created by programmers as part of their craft, saying you shouldn't rewrite history because you might need it is not much different from saying you should commit every keystroke—they both mean you are of the opinion that you need to know every transformation to the code that happened.

Exactly right. I commit very often when I develop something, and I can have typo commits, test fix commits, really fix it now commits, etc. But nobody really wants to see that when code goes into main project branch - my fellow developers want to see one clean commit that says "fix bug #1234" or "introduce FooBar functionality" and don't care about seeing the tiny details of my process. Rewriting history works wonderful for that.

Alternatively, could you do your trashing about in a development branch and then once you're done make one merge into your main branch? That way looking at the history of your main branch, you'll only see the clean commit merged in, but if people wanted to, they could look at your development branch as well to see how that clean commit came about. If they don't care, they can just ignore that branch.

It doesn't really work like that because a branch does not have a clear, canonical start point in gits history; every branches history goes all the way back to the initial repo commit. You can do some fooling around with diffing the merge parents to try and get some idea of the changes, but it's going to show all the differences (what changes are on master but not on the branch).

Having a single atomic commit to "add feature x" is a lots cleaner when you're git blame'ing then git show'ing the commit, as you get to see the whole picture, instead of a log message like "fixing typo" and a 1 character diff.

That said, this should definitely be done off on a branch, and there's no reason not to have multiple useful commits on a branch merged in as such, but trashy typo/forgot to add X style commits are completely worthless to someone looking back at history

What if when you git merge a branch into master, it collapses all the branch commits into a single commit that appears on the master branch, but the branch commits can still be viewed as being contained within the merge commit?

Meaning you could expand a the merge, see the branches that were merged into the branch, and the individual commits made on that branch.

In a hypothetical DVCS where that was possible, I think it'd be fine.

You can do that (there are options to git merge that will let you squash the merge into a single commit), but IME that's too coarse. I usually want what I've done on a branch to be several distinct commits, just not the hundreds of false starts and minor syntax changes you'd see if you looked at my "real" commits.

The histories actually get merged in when you do a merge between branches. However, it's possible to squash your commits before doing a merge to achieve this effect.

Right, that's what I mean by rewriting history.

I very much want a commit every time I type a character. There is no good reason that undo and version control should be separate things. Of course you want a way to group a bunch of commits into a larger commit and name that, but you want that anyway.

Ah the old TextMate undo debate. Personally I prefer the vim model, but of course that requires modality.

Rewriting history is probably the best part about git. Yes, it can be dangerous if you're not careful but I've found a clean history is very important.

I regularly use the history as a view of what others on the team have been up to and to find when bugs were introduced. If many people are developing on the same branch, rebasing makes the history so much easier to read than having to parse merge commits and trying to mentally reconstruct the state of the individual developer's code base before the merge.

Yep. SVN having a culture where history is expected to be full of junk commits is not a feature.

Pretty much all of the points here are things I love about git.

I'd personally hate working in this author's ideal repository: too many people with direct commit access, no tracking of feature branches, messy merges, noisy history.

Well that's unfair. I think there are legitimate arguments to be made against rewriting history besides "I've been brainwashed by SVN."

Assuming that you restrict your rewriting to your own local repository (as is the widely-agree-upon best practice), what are some of these arguments?

Rewriting history was the motivation behind commit-patch [1]. Granted, it doesn't actually let you rewrite history per-se, but it allows you to selectively check in parts of a file, which is very similar--You're effectively saying, "checkpoint this portion of a file, even though I've not really ever had the file in this particular state". It allows nice, fine grained commits even on version control systems like CVS and SVN.

> In svn you don't even have the possibility to refuse them.

Too true. One thing we did to try to fix the trashy commit issue was to mail out patches of each commit to a team mailing list. That allowed 2 things to happen:

First, just seeing your trashy commit next to a commit to which someone has payed attention motivated you to be a little more careful next time. If you're just sending your commits into the void you behave differently than if you know what you commit will have a bunch of eyes on it.

Secondly, anyone on the team could just reply to the email and suggest that it be split in 2 commits next time.

[1] http://porkrind.org/commit-patch

Excellent article, this reflects much of my personal experience working with git in the last year.

Our whole department (>100 people) switched as part of a move towards decoupled development/continuous integration, we used perforce before. Luckily there were three people with excellent git knowledge who could answer all questions so this helped a lot.

However, I find myself relying on stackoverflow/google for some not-so-common small use cases where a glance at the manual just doesn't help (find all changes in local branch not in upstream branch x?). Also, the git commands and their options are sometimes not very logical as the article mentions (i.e. git show vs. git blame, the first needs the syntax "branch:file", the second "branch file", why? Small things like that take away from the beauty)

git is powerful and I prefer it to perforce for it's possibilities, but I think tools like mercurial are a better DVCS which just didn't have enough hype at the right time.

This generally sums up why I prefer Mercurial. It provides all the benefits of a distributed VCS, but with less of the complexity, at the expense of some (usually unneeded, at least for me) flexibility.

I find mercurial is a little easier but a mouse could starve on the difference.

That having been said, while I wish git were easier, I can cope with it. I can't cope with both git and mercurial. I haven't got the brain capacity to remember how to use both of them without them blurring together. I want to standardize on one or the other. And once I ask which to standardize on, git wins by simple market share. That's why I ended up choosing it over mercurial.

Given that "everyone" knows git, and essentially no one uses hg, I think saying it involves "less complexity" is very much missing the forest for the trees.

essentially no one uses hgs

Difficult to take what you say seriously when you make comments like this.

No one except for the entire Python development team. And me.

And all of Mozilla. And Oracle's Java dev team.

Windows support was a big deciding factor.

And Adium and pypy and Sphinx and gevent and almost every project on bitbucket. But _apart_ from them, "essentially no one" uses mercurial! :P

And the vim team.

I see by your quotes that you are probably aware of this, but I think the set of developers that knows how to use git is at least an order of magnitude smaller than the one that doesn't.

Probably true. But at least in the open source community, it's pulled even with CVS and svn and is at least an order of magnitude higher than that of hg (or any of the other also-rans). Obviously "someone" important is going to use any product (see the irate comments for some great examples).

And there are very high costs to heterogeneity in this world. Using a weird SCM means that every new contributor needs to learn a new tool and new workflow, and that hurts. Using the one that "everyone" knows is a big advantage to projects.

And git is good. Not "the best" perhaps; and undeniably ugly in places. But it's more than good enough. And the existence of a community like github make it, frankly, better for new users than other options.

"If the power of Git is sophisticated branching and merging, then its weakness is the complexity of simple tasks."

The power of Git is its distributed nature and the fact that you can maintain local commits. When you have a single remote repository that everyone commits to, then sure, it's really easy to do things (have fun maintaining the ACL and merging any changes contributed by anyone outside the committer list via patch). If you think "it's really easy to branch" is the primary reason to use Git, you're using it wrong.

> The power of Git is its distributed nature and the fact that you can maintain local commits.

that's actually the power of any DVCS.

Yes, that was my point. He's comparing a VCS with a DVCS and then complaining that the "D" adds overhead.

I think the biggest problem I have with git is that I don't understand how people can't get it. (That's assuming they understand DVCS, but don't get git. Not understanding DVCS is unsurprising.) It's like when my nonprogrammer friends who took CS101 didn't understand for loops. What?! It's just applying a concept you already understand.

It's unfortunate that git re-uses some verbs from cvs/svn with different meanings, but is that really such a big hurdle?

And I'm always surprised to hear complaints about git's user interface. I find the command-line interface far friendlier than others: auto-paging, colorized output, text hints of what I should do next, and fantastic tools (like bisect) in the same package.

And looking through my bash history, most of my commands don't use any options (the biggest exception is git commit). Possibly this is because I do most of my git interaction through vim-fugitive (and I have aliases for commonly-used complex commands). But I think it makes more sense to have a smaller set of commands that are logically organized (rebase mangles your history, reset re-aligns based on your history, ...) than a single command for every function.

Defenses of git sound remarkably like defenses of C++ syntax and feature design. In fact, I'd argue they are similarly written by people who are overly proud that they are smart enough to figure out some convoluted and arbitrary complexity, but not wise enough to realize that level complexity is unnecessary.

Your comment sums the issue amazingly well. Well you look at the user interface it is clearly evident that these guys had forgotten that not everyone is a kernel hacker. And it seems as if they tried their best to make everyone else feel like an idiot because they don't have the time or want to understand the arbitrary decisions they made or are simply not smart enough to understand it.

I'm all for trying to find ways to improve Git's learning curve, especially for non-technical users.

That said, if you're calling yourself an engineer, you've worked at a Git shop for over a month, and you're still complaining about how "hard" it is? I have absolutely zero sympathy. You're being paid twice the national average to do a job that's supposed to be mentally difficult. You use version control every day. Stop whining, learn to use your tools correctly, and stop subjecting the rest of us to your crappy, disorganized commits.

Ever try to commpile git statically?

Git makes you believe it's lots of small little utilities that work together.

Far from it. Git relies on Perl or another scripting language, not to mention it's reliance on curl.

You cannot run Git without these other sizeable programs.

I can make static binaries of RCS, CVS and SVN no problem. CVS uses SSH. No silly SSL and the certificate mess. I value the simplicity.

Mercurial (which seems to be a favourite among connoisseurs of versioning systems) relies on a Python intepreter, but it's reasonably contained to a single Python script; no installation required. You point Python at hg and it works.

Of course, it's been said that most of the time people who ramble on and on about these systems and their esoteric features do not need the advanced features. They rarely use them, except as points in a debate over which versioning system is "the best".

This is, by far, the strangest git complaint that I have ever heard. What are you trying to do, ship embedded devices with git on them?

"avoid holding it that way"?

Honestly? Yes. Sometimes that is just the only reasonable response.

is there a complete list of ways I should avoid to hold git?

I love git and prefer it to svn, but he's right. It succeeds in power and usefulness, but utterly fails in the complexity department. Someday, someone who understands the virtue of simplicity and can control their "how dare you insult my favorite tool" response will take this criticism to heart and rework git (or at least, re-porcelain it).

I think the re-porcelain option is really the most viable option here, for those who complain about git's arcane invocation. So many Git commands actually do two or three different things depending on invocation.

Sounds like someone's just discovered how different DVCS are to centralized VCS.

Still, tools like Tower, Smartgit and Github for Windows, especially Tower, make interface to Git less painful.

With time, the interfaces to Git workflows can only improve, whereas what can you do with SVN?

That said, he may have a point about (branch &) merge message management in Git. Perhaps this can be improved closer to git with git extensions, e.g. implementing some sort of ranking and filtration system. Related to that is users should not really have to change the structure of the VCS itself just to filter messages.

I have to admit, it confuses the heck out of me. I am always in fear of destroying code because the documentation part is spot-on. I read and reread, and still feel like I am working on a best guess interpretation.

Using man files and in-built help is probably always going to only give you half the story. Have you considered reading the Pro Git book? http://git-scm.com/book

I can't count the number of times I've googled for simple commands like "how do I revert an uncommited file to its original state"?

    hg revert bla.txt
    git ???
... and I would still have to google for it (it's something with HEAD iirc). Its usability is atrociously bad and I don't want to spend time learning some badly designed cli interface when I can focus on more important things and use tools that make my life easier, not harder.

git checkout bla.txt ? I'm not sure how I get how that's harder. I'll throw one back, how do I do the equivalent of git stash and git cherry-pick in hg?

Ah, good to know. Everytime I've googled this it was something about reset --hard (or --soft) and HEAD or ^HEAD or whatever else.

git stash is hg shelve. Don't know about cherry picking (I've never needed it).

Anyways, the argument I'm making is not "which tool is more powerful" but "which one is easier to use while being powerful enough". For me that is Mercurial, hands down.

cherry-picking is amazing for the "oops I did that fix on master instead of the 2.x branch". git cherry-pick <hash>. done.

Just for the record, the transplant extension [1] seems to be how you do cherry picking in Mercurial.

[1] http://mercurial.selenic.com/wiki/TransplantExtension

Transplant is a great extension and very useful in a pickle.

Can you elaborate? I haven't had to use cherry-picking or rebasing and I'm not sure if I'm missing out on anything.

Cherry picking: I forget to change to a branch where a commit was supposed to go, or I did a single commit change that needs to go across multiple branches without merging the entire branch. Do the commit, get the hash for the commit (git log is useful here) and switch to the branch where you want the change. git cherry-pick <hash> does a merge of just the single commit. Of course you can still end up with conflicts to fix, but git has been light years ahead of svn in doing merges, in my experience

Rebase: Oops I committed something I shouldn't have. Must be done BEFORE you push. My favorite is git rebase -i HEAD~<n>, where n is usually something small like 5. You'll get a vim-like view where it lists each of the last n commits by hash and message. Delete the line for each commit you want to remove, save/quit, and git merges out those commits. Of course be cautious here because you can lose work completely.

One more I like in the same vein, git commit --amend. For when you did a commit, and forgot to include something. This commit will just be added to the last.

> git stash is hg shelve.

Or hg qnew -f, which I personally prefer.

I can say this: I've used both Mercurial and Git professionally, and for distributed version control, I found Mercurial much simpler to use.

My issue with git is the defaults. Generally the defaults and behaviour are geared towards large projects. It is absolutely correct in that sense - you don't want hundreds or thousands of contributors messing things up. An additional simple example is that push doesn't send tags.

But generally you want the opposite defaults for small projects/number of users. For example you do want tags pushed by default so every sees them. This places a large learning curve on the small scale projects and users. Remember that most users will be perpetual intermediates.

My analogy is that git is like a sharp knife. In the hands of an expert it can produce art, but in the hands of others we get blood. Some of the responses here are marvelling at the sharpness and what can be done with it, but are missing the point that others end up bloody!

Aren't you more likely to cut yourself with a dull knife though?</strained-analogy>

I think you're more likely to feel pain with a dull edge, but a sharp edge cuts easier.

The point is it slips off the tomato and cuts your finger.

I find his complaint about git's lack of abstraction strange. Yes, git's syntax could definitely be more consistent, but I can't think of how you could abstract away very much of git without quickly losing power.

On the other hand, one of the things I hated most about svn is that it doesn't abstract away the remote repository details at all. To do something as simple as check out a branch you have to type in the full absolute url to your repository, since a branch is basically a different folder higher up in the hierarchy. Talk about a leaky abstraction.

The abstraction between version control tools and the remote server(s) you back everything up on and the power of git's underlying model are both such big wins that I really can't get too worked up about the syntax.

Yet another anti-git rant which will merely bounce off the deflector shields of the git faithful. I doubt anything will change in terms of git usability and misfeatures until someone proves that there's a better way to do it by building an alternative that's all around better than git. But that raises the question of why one would continue to use git at that point.

Using Mercurial daily, I don't understand why it isn't widely viewed as the alternative to git that you mention. It seems to avoid some of the pain-points the OP lists.

The idea that there are "git faithful" is a sign of how immature (in every sense) the software development field is. Masochism and complexity-worship seem to blight our field(not necessarily referring to git, which I'm not qualified to comment on)

Git is _awesome_. Once you "Get it", there really is no big problem. Sure you may have to look up some syntax occasionally and make an alias or two for your common uses, but really, it's no big deal.

And the benefits are compelling. Enjoy the amazing power of committing early, and committing often. Being able to revert to "10 minutes ago" is so freeing when trying out a refactoring idea. And being able to "uncommit" the last X commits to recommit them in a different order and with cleaned up messages and structure before sharing with colleagues... amazing.

All the quibbles about syntax really miss the point and the power of Git.

He mentions three ways to irrevocably lose data. Is that really accurate? I would think old refs are still present in the repo and accessible from .git/logs, but I don't have any experience actually collaborating with git.

Rebasing isn't really destructive. Try it: open `gitk --all`, do a rebase -i and squash all the commits together, then switch back to gitk and refresh. You'll see all the old commits still in the database, but the HEAD and master branches point at the new commits. Totally not destructive, but it does take a bit of knowledge to undo the change.

Git maintains what's called a "reflog" to help with this. It's a record of every place that every ref has ever pointed in your repository. Try it: `git reflog master`. You can even see when you did pulls, and what they merged in.

The only truly destructive thing you can do to your git database is `git gc`.

> The only truly destructive thing you can do to your git database is `git gc`.

And of course we should expect garbage collection to be destructive of information that is not garbage?

Didn't know that? Just read the man page. Whoops, it doesn't actually mention that, but it does mention that it may happen automatically at times.

So only clever people like you know archaic undocumented side effects of git's inscrutable design, except nobody ever really knows the full story because there is so much unnecessary crud to learn in addition. Clearly more can be destructive than gc if gc can be executed by other commands and triggers by repository state.

git gc be default does only prune things older than 2 weeks so to lose your recently lost commits you would have to explicitly give a prune which is today.

I do not think one can do this accidentally:

git gc --prune=2012-08-05

The information is garbage - it's no longer referenced by the current state of the repository. "git gc" just delays collection in order to give users an opportunity to restore recently-unreferenced commits they decide they wanted after all. Also, the man page for "git gc" on my system describes exactly how long commits are kept around after they're no longer referenced, what this depends on, and how to change the default settings.

You can solve the majority of such issues by disabling pushes to a remote repository. Assuming all developers collaborate through a central repository, disabling force push there should avoid commits being lost.

In practice however, I've found a force push can be useful. For example, we once had a dev push code to our deployment branch which wasn't in fact ready for production. We could have just reverted all the commits which were added, but this would be messy and make merging again later painful. Instead, just `git reset --hard` to before the merge and force push.

If you understand the implications of rebase and force push, you shouldn't have to worry about losing data.

Allow me to add one to the list:

11. Completely different concepts for the same commands as other SCM systems.

Case in point: Checkout. In every other system prior to git, going as far back as CVS in 1986, checkout meant grab a remote repo and copy it locally.

In git, it suddenly means to switch branches in a repo you already have. The real "checkout" was renamed to "clone".

Why not use something like "switch" instead?

That's nearly 20 years of muscle memory everyone needed to relearn because.. why?

Git add and SVN add do completely different things as well.

Was it simply not thought of that people who use git would be switching from another system at the time, very likely to be either svn or hg?

Yeah, but you could also argue that it doesn't make as much sense in git to call cloning a repository "checkout". Because you are cloning the repository to your very own local repository, then you make your changes from that repository and then you push back to the original repository, which is a remote repository.

Essentially, a checkout in git is to checkout files from a particular branch into the current working directory. And that branch is actually in the index, which I would really call the repository - so actually you are indeed "checking out" files from the repository. Once you make your changes, you commit them right back into the index.

Dear OP,

If you're still using git from time to time and get frustrated please feel free to ping @gitdoctor on twitter. It's an account I run to try and help people use git right when they need that help.

Thanks and good luck!

You don't need github to make pull requests:


You dont need github for anything, period. So its very strange that it is mentioned at all when comparing it to other version control systems.

Let me translate:

3 things I hate about (the culture surrounding) git(hub):

1,3,4,5 - I'm expected to understand the information model.

2 - The CLI is inconsistent.

6,7,8,9,10 - I'm expected to work harder so that life is easier for the maintainer.

He also just uses a shared repository in subversion to do this which he could have easily have done in git with the same amount of effort (of course with all the problems with comes with the svn way).

Having used both git and hg, I very strongly agree. I learned hg first. Hg took less time to master than git took learn the basics of. The syntax of git is incredibly cumbersome in comparison -- I type a lot more. It's the standard, but relative to hg, not a very good standard.

git is only complicated because it lets you do everything you may possibly want to do, often a superset of what you actually want to do.

If you want svn-like commands, you can borrow someone's scripts or use a shiny GUI. I don't want svn-like commands because centralized version control is obnoxious.

Don't complain because it's hard. Programming is hard, math is hard, and if you know how languages, data structures, and algorithms work, git is actually pretty easy in comparison.

I disagree. git is complicated because it does not have defaults, command line intelligence and does not have a consistent user interface. It forces you to constantly be repeating yourself and to learn a lot of detailed incantations (Like mentioning HEAD and origin and master over and over.)

I say to you, don't complain that people are complaining. People are complaining for a reason.

Have you tried some of the other DVCSes? Mercurial, or Darcs, or bazaar? Gits problem is not the problem domain, nor the backend. It's the user interface. That's the hard bit.

Git doesn't seem to have been developed with ease of use in mind. I've found that it's very powerful, and that most things that you want to do with it are possible, but not always as easy as it could be.

I'm working on a collaborative project with several inexperienced developers using various editors and operating systems, and dealing with line endings has been a serious time sink. The first step was "* text=auto" in a .gitattributes file to override everyone's local settings, as some had used custom settings when they installed Git.

Apparently the developers of Git decided to not support \r as a line ending, which ended up causing headaches for us because some legacy programs still use it. Several times, someone committed changes to a file where \r\n line endings had been replaced with just \r, for whatever reason. To Git, they had just deleted the entire file and replaced it with one long line. This frequently resulted in edit conflicts where it was very difficult to tell what had actually been changed.

The solution ended up being a filter:

    clean = LC_CTYPE=C awk '{printf(\"%s\\n\", $0)}' | LC_CTYPE=C tr '\\r' '\\n'
...which everyone now has to duplicate in each of their local .git/config on every copy of the repository they use. Coming up with that little bit of command-line wizardry, and getting everyone to install it (and making sure it worked on Windows/OS X) ended up wasting the better part of a day to accomplish what seems like a relatively simple task.

So, in the end it was possible, but the process could've been much friendlier.

I will say, though, that git bash is absolutely amazing and blows Cygwin out of the water for ease of use.

> ...which everyone now has to duplicate in each of their local .git/config on every copy of the repository they use.

You can use git in your .git. Add those hooks to the repository. Every dev will get them automatically on checkout. No one should have to install anything. (Well, aside from Awk.)

That never occurred to me. Thanks for the suggestion.

Breaking all the line-endings in a file should never get as far as a merge conflict though. It should get to a failed code-review and no further.

I'm going to be contrarian and say that he's mostly right for all of them. SVN was simpler, git is more complex. SVN did some things well that git does not so well.

But this all misses the point. Git is many many times more powerful than SVN. And that complexity is really useful, even for relatively small projects. You can learn Git's complexity, removing many of SVN's advantages. But you can never get Git's power into SVN.

I've been using git for several years on multiple projects with teams of various sizes (admittedly none larger than 10, though I avoid projects of that size for a multitude of reasons) and have loved it a lot. Especially compared to the merge headaches of svn. Or cvs. And mercurial just gets in my way more often than not. git stash I awesome

> The fundamental promise of any version control system is this: “Once you put your precious source code in here, it’s safe. You can make any changes you like, and you can always get it back. Git breaks this promise”.

Right there. I don't know who made this promise, but it's not what Git is supposed to preserve. Git is distributable is it not?

Number 10 is a total apples-to-oranges comparison. For an apples-to-apples comparison, the question is, do you want to give your contributors write access to your master repo? (and deal with the consequences)

If contributors have write access, then Git is almost as easy. There's just one more command ("git push") compared to SVN.

If contributors don't have write access, then there's no easy way to do this with SVN. Most places that I've seen will either have users submit .patch files via email, or put their changes in SVN branches (ugh). Or, they convince themselves that they'd rather just give contributors write access. Either way, Git has many handy ways to solve this problem (Github pull requests are just one of those ways), and it definitely wins on this front.

I tend to summarize it like this:

Git is built by people smarter than you for people smarter than you. Deal with it.

Now, seriously, Git is a) immensely flexible and b) born out of the needs of Linux kernel developers (or, more specifically, Linus' needs). I would expect it to be optimized for that case.

There sure is a lot of evangelizing for it if it's only intended for the 1% elite developer.

That's exactly the problem, i.e. those people who endlessly promoting git so that they can be seen as elite developer. Their favorite past time is to share their "get it" stories with the rest of the world.

Not unlike the "Are You There God? It's Me, Jesus" episode of South Park.

Git is a tool. You use it if it solves your problem. You can certainly use it the same way you'd use Subversion and it's not any harder - it'll just behave as a version control system that can buffer commits offline with two "levels" of commit - local and remote.

If you want to use the more complicated stuff, then there is no way to avoid learning the more complicated ideas.

There is a lot I don't understand about Git, but, as far as my usage patterns have gone, I'm very satisfied.

> You can certainly use it the same way you'd use Subversion and it's not any harder - it'll just behave as a version control system that can buffer commits offline with two "levels" of commit - local and remote.

That's hg. With git, you got the index / staging area, which is unique to git (no idea if bitkeeper has it). In other tools such as svn or hg, there is no need for flags such as "commit -a", "diff --cached", and "add -N".

> If you want to use the more complicated stuff, then there is no way to avoid learning the more complicated ideas.

And this is what we hate about git. Version control shouldn't be complicated for 99.9% of projects. I have used svn for 3 years and hg for 2, they get the job done just fine without cryptic commands and flags.


Git questions on SO with more than 300 upvotes should be considered bugs.

There are plenty of abstractions on top of git - most UI implementations abstract away the hard details, at the cost of not being able to understand what happens when something bad occurs because you never had to learn its intricacies prior. Seeing the consequences of such things it makes me appreciate git is left as raw interactions. Git is not for people that do not want to understand it. To me, it's similar to vim - its basic implementation is bare essentials and complicated concepts, but once mastered, far outweigh competitors who roll those concepts up into simpler ones and leave you with workflows on their terms.

I completely agree with you here. Having used Visual Studio as my primary editor for a long time, I finally decided to give vim a try last year given how all my hacker friends raved about it. It definitely took a few days of understanding the basic concepts and going over the steep learning curve, but now I'm way more efficient with my coding than before.

It's been the same experience with git. It definitely has a steeper learning curve, especially coming from a centralized source control system like TFS and Perforce (for me at least), but having worked through that curve, I feel git has been much more useful to my workflows than what TFS or Perforce (or insert any central source control system) has ever been.

> Power for the maintainer, at the expense of the contributor

Interestingly, SVN and Perforce are about power for the maintainer, with no benefit at all for the contributor. You can't even version control your own work with those tools.

Issue #10.

    alias commit='git add && git commit && git push'

I know what you're going for, but for anyone following along at home: "To avoid confusion and troubles with script usage, aliases that hide existing git commands are ignored." (from git help config)

This is true, namely that git aliases in ~/.gitconfig cannot override git built-ins.

That said, the parent post showed what looked like a bash alias, not a git alias.

The bash alias is correct. The issue was "too many commands", which is a non-issue. You type in the commands once, make it an alias, and be done with it. When switching to another repository system, change the "commit" alias, not what your fingers have to remember.

git::mercurial vhs::betamax

I'll also say that tech folks don't like not being able to understand something, and enjoy understanding arcane things others don't (and once understood, no matter how hard it was to learn, it is suddenly "trivial"), further strengthening git's hold. I'm happy to see the author seems to understand git well enough to say, yes, I get it, and I still don't like it. I just wish he had talked about mercurial as the plausible user friendly alternative instead of svn, since svn is not distributed and therefor unsuitable for the use cases where git thrives.

Whoever designed Git was both a skilled programmer and a crappy designer.

I started dvcs with Darcs but it was too slow despite having a really really good CLI. Then I switched to Git because it was fast and within a week ran into so many sharp corners I had metaphorical blood all over my codebase. After a while I learned the useful subset of Git commands and life got easier with only an occasional sharp corner intruding every few months or so.

Then I discovered Mercurial. The speed was acceptable. The UI was intelligible. And I didn't hit any sharp corners. Life has been way way better ever since.

i had to work on a big corp job once they were using VSS5 in 2007. made me appreciate even CVS.

if you want to have a really simple way of working with git get the github for mac client. at the same time insanely inflexible.

but hey you know what in theory vss5 is quite "simple" as well. i mean how complex can a program be where distributed work is essentially happening by locking files.

I had hoped op would've said something interesting that might've led into 3rd generation DVCS, but this is definitely far from.

This sort of article sounds like s/unix/git/g of rants against UNIX/Linux command line & filesystem concepts that were common in the late 90's, as it was becoming clear that UNIX wasn't actually going to be killed by Windows NT, but rather was resurgent. Examples included:

- "Yuck, why such different terminology from DOS?" - "Commands are inconsistent and there are too many, where's my One Command or (better yet) One GUI that does everything they way I think about it?" - "Yuck, scripts that make things easier for my particular workflow, why didn't they just build it right the first time?"

Fundamentally it comes down to people who believe version control is a simple problem, and git confuses that for no good reason, or those who believe version control is an inherently complicated problem, and tends to require some study to understand the concepts. Git doesn't hand-hold, it exposes the core concepts at the data level, thus supporting any workflow for any size of team or work style. If you prefer a dictated workflow and task structure, there are plenty of wrappers that will help you - just don't be surprised if not every team agrees with your preferred workflow.

> it exposes the core concepts at the data level

But it exposes them poorly, from a user interface standpoint. The beauty of UNIX, actually, is that it provided a few simplifying abstractions (block files, character devices, pipes), and everything used that. Imagine if catting the contents of something from /dev was different than piping the contents of a tarball. That's the sort of UI/UX frustrations that TFA (and others) rant about.

This is not a "DVCS vs. SVN/CVS" issue. This is about git's usability.

OP might have just professed "I am not technically advanced, Git has powerful features I'd never use, it should cater to me."

In general, there are too many of these articles on HN about "I don't know how to use it, so it's terrible."

What OP fails to grasp is the purposeful difference between Git and other revision/version control systems. Git attempts to cover anything you would ever want to do. Git is the Photoshop to SVN's Instagram.

You can use Git as if it were SVN, no problem. You can do Git commit-push-pull all day long as if you were SVN commit-update, and be none the wiser.

The one thing Photoshop has (as a similarly complex piece of software) that Git doesn't have is a single user interface. I don't see this as a problem. There are a bagillion Git GUI clients if you don't like the command line. Some are good, some aren't.

As far as having a good strategy for using Git on a real project. I think OP needs to spend some more time on Google. Here's a good article describing the most common workflow:


As a new DVCS user, I today just started playing with both using tutorials and books freely available on the web. I am using Mint 13 and the CLI. Of the two, the feel I get is that Mercurial is easier (more straightforward) of the two to use and Git is the more micromanage-able of the two. JMHO, but as a newcomer, it's my impression.

I especially liked the first comment about Subversion "anybody can write a simple VCS if they don’t have to make it distributed." It reminds me of my days working on a parallel compiler team. We always used to say, "we can get you answers very, very quickly if you don't mind whether they're correct or not."

Just as a parallel compiler developer must worry about recurrences and data dependencies breaking parallel programs, distributed version control adds a huge level of complexity which you cannot safely hide. However, I agree with the poster that the next major version of Git should clear up several inconsistencies.

(As a side note, some binaries labeled as ASCII in our Subversion repository back then caused massive corruption and shut down all development for days. Having too many assumptions made by your VCS and too few options specified by developers is bad simplicity!)

Subgit and Subhg are interesting.


Just use Mercurial for random private commits, send the Git people your changesets every so often:

    $ git init && git add . && git commit -m "Initial commit" && git remote add origin git@github.com:acct/repo.git && git push -u origin master
    $ subgit setup
    $ hg init
hginit.com <-- great resource


In Google's own words: "In terms of implementation effort, Mercurial has a clear advantage due to its efficient HTTP transport protocol.

In terms of features, Git is more powerful, but this tends to be offset by it being more complicated to use."

I really can't agree with point #1. Most of the things he lists as being part of the complex information model are equivalent and make perfect sense once you take a couple hours to understand how git works internally.

And no, that's not too much to ask for a tool that you will be using nearly every day. Once you understand git's data model and "patch-oriented" behaviour, you won't have to wonder about namespaces, the index, rebasing, cherry picking or fast-forward merges.

Point 5, or the fact that Git doesn't even try to hide its internal workings is actually why I prefer it over everything else. The UI can be weird at times since it evolved from just a collection of tools to operate on an on-disk, persistent and immutable data structure, but as far as being good at what it does, it's hard to beat Git.

Translation: “It’s easy, Granny. Just rev to 6000, dump the clutch, and use wheel spin to get round the first corner. Up to third, then trail brake onto the freeway, late apexing but watch the marbles on the inside. Hard up to fifth, then handbrake turn to make the exit.”


I felt the article had some fair complaints. The problem is that the author felt that going back SVN was the resolution to those complaints which I found ridiculous.

My question is how does mercurial compare to git on all of the author's points?

As someone who jumped from svn to hg a long time ago, I can answer simply: the transition was smooth like butter, http://hginit.com/ explains everything on the concept, while hg's ui provides abstraction and is very svnuser-friendly, so - everything just works. http://hgtip.com/ is also very useful.

IMO it's easier to embrace git after mercurial, because the part where you understand how a DVCS works is already behind you, and you jump into the syntax and specific differences.

I'm also very much curious about that.

I've had enough of Git lately, and after reading first couple hundred pages of Git Pro, I decided that Mercurial has a better design. Shame that bitbucket is not as good as GitHub, but BitBucket gives you unlimited private repositories...



The issue with git is that's got all this cruft built around it, but for the most part it's very rare you need to jump into it in that level. I've been using git for about 2 years and only needed to rebase for the first time very recently.

There are issues, and flaming the author saying he needs to read more is disrespectful (and ignorant of the issues), but git is a community, open source project. Not happy with the existing docs? Rewrite them, call it git for humans and off you go. I've seen projects doing work to 'nice' the command structure, so there's other people attempting it.

But we can all agree git reset is weird.

I have used subversion heavily. So many things are not at possible with SVN. But, it can be done in Git easily. Of-course, it requires learning and a bit of change in the mind-set. But, it is worth it.

I hate blogs that put pop-ups over part of the content with no way to close them (I'm not subscribing to your mail list or following you).

I don't hate Git but I do agree with many of your points. There's ccomplexity that should be hidden (or more hidden) and there's inconsistencies that still catch me occasionally. I've never actually lost code on Git though it's taken me a while to find my code.

It's also not fair to confuse Github's "Pull request", "Fork" and "Merge" with Git. These are still just branches and merges.

1. Not sure his issue here - I count 9 things you need to know for Github (one of which I have never needed to know - treeishes), and 7 things for SVN. It's really not that complex.

2. The command line syntax:

But the shortcut for “git branch” combined with “git checkout”? “git checkout -b”

Indeed. You can branch your code, but not check out the files from the index into the working tree.

Perhaps the confusion here is because the author is coming from an SVN background, where checkout means something different.

As for git am being obscure - sure, seems a little, but then there are two things: 1. don't use it if you don't need it, and 2. for kernel development, this is remarkably useful!

3. Documentation: completely invalid. The man pages might seem a little terse, but then if you are looking up a command and you don't understand the terminology, then you should probably consider typing in

  man gittutorial 
Which, incidentally, can be found here: http://www.kernel.org/pub/software/scm/git/docs/gittutorial....

Alternatively, if you are trying to understand how to use git (and it might be worthwhile for the author to follow this advise) then try reading the git user's manual, which can be found here:



git rebase is explained here: http://www.kernel.org/pub/software/scm/git/docs/user-manual....

To understand how git checkout works, read here: http://www.kernel.org/pub/software/scm/git/docs/user-manual....

4. Information sprawl: actually, I consider myself to be a git newbie (mainly use github!) and frankly I've not needed to learn that much about git so far. However, whenever I've come up against something new, I've checked the documentation and after about 5-10 minutes I've understood the concept needed to get me going. I don't consider myself to be an expert in git in any way. However, as someone who has to program, I tend to find that for any system with enough power, I have to learn new things regularly. git is one of those things. Learn to love it :-)

5. Leaky abstraction: first, don't make the title "leaky abstraction" if you don't believe that there is any abstraction in the first place.

Secondly, it looks to me like they are trying to take your branch and insert it into another repository? Can't quite tell what is required here... certainly I'd love to see the way that this would be done in SVN!

6. Power for the maintainer, not the user...

??? I'm sorry, but the author is complaining that git is powerful, and works really well in highly distributed systems where you have a lot of parallel commits? Well, uh... duh?

The complaint here is that it's not usable for "ordinary" repository users. I would consider myself a fairly ordinary user, and I can honestly say that I don't consider that git is that hard to use.

7. Unsafe version control


8. In the traditional open source project, only one person had to deal with the complexities of branches and merges: the maintainer. Everyone else only had to update, commit, update, commit, update, commit…

Which meant a massive bottleneck when doing branching and merging. That's the whole point of git - it's version control done large. Or otherwise known as "distributed version control". I'd recommend the author read up on some of the advantages here: http://git-scm.com/about

9. I don't really have much of an opinion on this.

10. Github != git. For the record, I love github and I really don't find it that hard to use, or anything so complex that I can't do it fairly quickly.

    3. Documentation: completely invalid. The man pages might seem a little terse, but then if you are looking up a command and you don't understand the terminology, then you should probably consider typing in

      man gittutorial 

    Which, incidentally, can be found here: http://www.kernel.org/pub/software/scm/git/docs/gittutorial....
I disagree. Just look at the man page of 'git push', a very common command: http://www.kernel.org/pub/software/scm/git/docs/git-push.htm...

It says it does "Update remote refs along with associated objects". What is a remote ref? It's not mentioned in the man page nor in git tutorial.

So maybe I can deduce it from how it used? I see in the syntax that I specify a 'refspec'. What is a refspec? It is explained in terms of 'ref's. Hence, I still cannot make sense of ref, refspec or that man page. Things like these pop up all over the place.

I love git. But it took very long until I even understood some basic stuff. And according to the OP, I am not alone.

Documentation: completely invalid. The man pages might seem a little terse, but then if you are looking up a command and you don't understand the terminology, then you should probably consider typing in...

I think a cardinal virtue of documentation is to but info where people expect to find it. Saying "Oh, you read the MANUAL. When I said RTFM, I mean the MANUAL for the TUTORIAL" isn't much of a help. If the documentation isn't where novices expect to find it, it doesn't exist.

Unsafe version control


How many can be done by accident? Are you using revision control at least in part for the ability to recover from a stupid accident? The fact that it isn't safe means you can't count on it being safe. You can't use it as essentially a way to have real point in time recovery for your repo, and it also means you can't count on it being an audit trail because at a minimum it could bet wiped out. That's fine, but it's worth stating up front that this is something Git doesn't do very well. Fine. Understand it is a tradeoff.

Doing those "unsafe" things in git by accident in a way that is unrecoverable pretty much requires you to be so drunk that you wake up the next day not remembering what you have done.

forcefully pushing things to remote repositories can be denied with hooks, so if you really do not trust the people with push access you can use that. For anything else, it's pretty much always possible to undo any damage by using the reflog.

In my experience, git is the least unsafe VCS I've used. if I commit a file, I know it's safe from accidental removals (as long as I don't touch .git). If I push the commit to a remote (private or public. Could even be on the same machine), it's safe from anything I do locally. So if I am going to do a complicated merge or a rebase, I first make a temporary commit to save the state of the repository and ensure that I can always undo any mistakes. You can't always do that in svn, since commits are immediately public.

Doing those "unsafe" things in git by accident in a way that is unrecoverable pretty much requires you to be so drunk that you wake up the next day not remembering what you have done.

Or more likely not knowing what you are doing, getting disoriented and combining the wrong options.

I haven't been using git for that long but I could totally see myself getting confused and typing something like that in by accident.

Even then, you can get back to something sane by using the reflog: master@{yesterday} refers to the master branch as it was 24 hours ago, and you can view the different things you've done to HEAD by just running `git reflog`. It's really really hard to blow away the reflog without meaning to -- you're much more likely to just `rm -r` the whole repository by mistake.

As long as you can remember what you did and realise within 30 days you can use the reflog to recover.

The documentation is, in fact, in a place where novices can find it. There's a man page with tutorial information.

What I find amusing is the paucity of information you find in man svn. Try it, you might be a little surprised! Though I have to admit, svn's inbuilt help is quite good.

With regards to not doing the things that can destroy data, in actual fact (as has been pointed out below) there is only really one thing that can't be backed out of is git gc, everything else can be recovered from the git reflog.

As for git having an "audit trail", it has never claimed this.

As a git newbie, perhaps you have not encountered many of the seemingly simple edge cases that end up being agonizing searches for incantations.

Please feel free to name a few :-) I've come up against a few of them, but nothing that I've not been able to work out with the documentation available.

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