64 comments

[ 2.6 ms ] story [ 108 ms ] thread
It is hard... but it also lets you do some insane stuff (patch mode, reflog, cheap branching, pushing to each other, not being centralized, etc).

That being said, for beginners, GitHub's app (albeit GitHub-centric) breaks down the most common use cases and turns them into buttons. It's probably a good place to start.

+1 for github's desktop app. Very very easy to use, and only requires a basic understanding of git. Might still want to have a git expert on call, though.
Used it and managed to decapitate my repository within a week. Couldn't figure out to recapitate. Went back to SVN. Happy ever since.
Honestly, it's a lot easier than SVN if you're doing anything even moderately complicated. I think there's a bias from people who learned SVN first.
I dunno, SVN has had great integration with the Windows Explorer, at least when I learned it a decade ago. It really was pretty intuitive. (Now, granted, SVN had many other imperfections, but it worked pretty well for smallish teams.)
Git has troubles under Windows. If you want a simple dvcs, use Mercurial. It's well supported.
Exactly. The first thing I tell people when moving over to git is to forget SVN ever existed. Thinking in terms of SVN (or another non-Dvcs) is what I find trips people up over and over again in git.

This isn't to say the git cli is perfect, but once a person understands how a DVCS works the typical git use case is easy. And then when someone needs an advance feature they can look it up. Git continues to surprise me with its code wrangling abilities.

It's funny, when I was learning Git, it was the first source control system I'd ever used, but most of the tutorials were for people switching. So all the (justified) emphasis to forget all I know about VCSs was just baffling for me. And with no baggage, the basic mechanics seemed perfectly sensible.
> Git continues to surprise me with its code wrangling abilities.

That's not a good thing. Perhaps it's not that people are "tripped up" by thinking in terms of SVN, but rather, are frustrated that things that should be simple aren't.

Instead, you want them to adopt an anything-goes git model where nearly everything is mutable, no data is sacred, branches and tags can be dropped at will and be gone from the repo refs, and people run around rewriting history willy nilly because they can.

Meanwhile, the poor SVN user wonders why they couldn't just commit, update, and get back to coding already.

Actually it is a great thing. I'm not even sure SVN could do what I often have to do. I have 2 large projects that diverged into different projects awhile back. They each share some code and often bugs need to be fixed in both. With git I can add each project as a remote to the other and cherry pick commits back and forth to keep both projects up to date without much fuss.

Thinking about what should be simple and isn't is branching in SVN. Most people know very little about branching because SVN makes it so hard to use. I would argue that people switching to git are not having a hard time with git so much as they are finally learning proper source control techniques in addition to git.

The basics in git are simple though. If a person is just replicating SVN, git adds 2 more steps (stage and push). Like I mentioned above though, people are not just learning git, they are also finally learning proper SCM.

You have a point regarding things that should be simple, not being simple. I'll agree that can be a problem.

What I don't agree with is the idea that you have to use all the advanced features.

Your last line hits on the idea that SVN users can't just commit, update, and get back to coding. Can't they? Can they not simply ignore everything extra until they hit a problem that the tools they've decided to use can't solve on their own?

Branching, bisecting, rebasing et al are not required in a git-centered workflow, they just make it easier to do Black Magic (tm).

> Thinking in terms of SVN (or another non-Dvcs) is what I find trips people up over and over again in git.

No, thinking in terms of non-Git is what trips people over. I came from Hg and still had to struggle with Git, because it's CLI is a mess and it's system behind is rather weird.

Plus things like Rebase and Cherry Pick did't exist in Hg (not by default and not three years ago). Lots of it's underlying model still leaks when using, that having good knowledge of it is mandatory.

Not if you're a project manager.
> I still love the elegance of the Darcs model and command-line…

I have mixed feelings about it now. Darcs was the first VCS I used and it was very well designed from a command line point of view. It's so simple and easy and it just made sense. The interface for adding hunks was just great and like nothing else that came before it.

But—we (my partner on a project) recently just switched one of our earliest projects from Darcs to Git. It started in 2005 and we've been very happy with Darcs. But we'd been using Git a lot in the past few years and Darcs started seeming a little simplistic. We were really hesitant because it had been working so well for the past years and why change something that isn't obviously broken?

We decided to just do the Git switch and it because clear after just a couple days of working with Git that it was a much better experience overall. Having easy easy feature branches and "git stash" and "git rebase" made our lives so much better and our moods so much happier that we cursed ourselves for not switching years ago.

Git even copied the Darcs hunk interface with their "add -p" and "checkout -p" options, which I use constantly.

Since I became proficient at Git, nothing else looks good any more (even the VCSes I used to love).

There's a `checkout -p`??? You just made my day.
"git stash -p" too (though I use that less frequently since stashes don't compose well).
Pretty sure almost any git commit command has a `-p` counterpart. I think commit and reset have it too. If it touches staging or commit area, I'm relatively sure it has patch counterpart.
I expect most people know about this already, but the interactive git cheatsheet by NDP Software is excellent.

http://ndpsoftware.com/git-cheatsheet.html

I got there from the article, but I'll say this here:

This just blew my mind.

Seriously, I'd never seen it laid out like this, showing how the different commands interact with the different "places". Indeed, the "Places Model" that was explained in the article is super, super, helpful. I found the biggest hurdle to understanding and to teaching Git is not understanding this model.

The people I know who aren't familiar with Git generally use the SVN model, and coming to understand all the different "places" that things can be is often confusing.

I love this article, and I love this cheat sheet!

I agree. Just based on the number of tutorials and posts about how Git is difficult / hard / weird

Seems to me that Git is more complicated than it should be.

I mean code repository as a software developer is an essential tool it should be as intuitive to use as a text editor.

PS: Also the common answers to "Git is complicated" are symptom to me that is harder than it should be 1. "Git is not version control is an application framework" well since it only has a version control build into it I say thay are the same.

2. "Git is difficult but it enables you do to really powerful stuff" Here I quote Kay: 'Simple things should be simple, complex things should be possible.' Seems to me that git took the approach complex things are complex and simple things are complex too!

3. "You just don't understand Git's model" Well many programmers barely understand what a compiler does yet they are capable of writing software.

4. "You just haven't invested the time it takes to master git" I have seen posts from developers working with Git that still can only do the most basic stuff.

Those are the same excuses used for previous technologies just replace git with: Java threads (before Go, Erlang) OOP (before Java, Smalltalk) Functional Programming (before haskell, F#)

In each case when the tool was correct the paradigm became obvious.

Well said. I feel that complaints from users should always be taken seriously. The fact that a piece of software is better than what came before doesn't mean that it can't have flaws, and can't be improved upon. I don't think git's command-line interface was designed poorly or to make things difficult. What I think is that the command-line interface was created as an afterthought, since git was originally supposed to be a low-level component and not a full-fledged VCS, and so the commands were cobbled together rather than planned.
> 3. "You just don't understand Git's model" Well many programmers barely understand what a compiler does yet they are capable of writing software.

I really do think this is the issue. I've been using git for about a year, but I was never confused about what it was doing because I understood it. I eagerly watched the developed back when the whole Bitkeeper thing came to a head. Not only did I see the start, I saw the situation it was born in.

Git is a uni-directional acyclic graph for tracking patches.

Git was designed around the model the Linux kernel had used, sending patch sets around. You merge people's patch sets in, you re-base an existing patch set on the current development, you figure out what the difference is.

Since Git tracks all those patches (which everyone calls commits), it has a full history of them. That history is a simple graph that always moves forward.

The distributed stuff (like origins, remotes, etc) is just a way of formalizing all the "look at my tree" stuff that the kernel guys did.

The basic model really is quite simple (the command line certainly has a few warts), the distributed stuff makes a fair amount of sense, and the patches aspect fits in really well.

I think the problem is that most people come to it from the CVS/SVN model. Commits in those systems are more permanent, where as the patches floating around the LKML were always more ephemeral; you could try to apply them at any point if you could fix the merge issues. I actually wonder if borrowing so much of the existing version control system vocabulary made things worse.

Commits are patches. 'Staging' is the stuff you haven't send to the mailing list yet. Branches are long series of patches. Merging is accepting patches, and re-basing is apply a patch set against a different starting point.

If you go straight from "This is what CVS does" to "This is what Git does", you miss why Git works like that. Whenever your mental model doesn't match reality (in this case, how Git operates) you end up with frustration and confusion.

Or, you understand why git works the way it does, but since you don't work on the Linux kernel and don't consider your code ephemeral, you find git's tooling to be be incredibly frustrating and complex to use when all you want or need is a safe, immutable version control system.
I will say, I only use the command line for a few things like rebasing. 99% of my work is done in SourceTree which is incredibly easy to use.
Thanks, this is helpful.

In designing things for users, I think a lot about the difference between meaning and mechanism. In early computers, you were confronted with a lot of mechanism: switches to flip, magnetic media to treat worshipfully, mysterious incantations to type. But something like the iPad, the surface interactions are mainly about meaning.

When you say, "Git is a uni-directional acyclic graph for tracking patches," I believe you, and I believe that's how people like Linus think of it. But that's mostly mechanism.

For people who were soaking in large open source projects, I think that mechanism reflects their meaning pretty well. But for people putting stuff on the web, or building internal tools, it's very different. The base case is, "thing that is live now," and "thing that will be live soon". Patches? Don't need 'em.

For those people (which I think is the bulk of developers today), they are forced to deal with a lot of git's mechanism, to no real benefit. If git had been designed to be a popular VCS, I'd call that a design mistake. But I think it's hard to claim that; as you say, git makes sense in its original context.

Well, saying "Git is a uni-directional acyclic graph for tracking patches" is a bit like saying "Monads are endofunctors in the domain of (whatever)". It doesn't really explain things unless the audience is really heavily into CS.

Despite the available complexity, you can choose to ignore most of it without issue. If you use a good client (I like SourceTree) you can avoid the command line's warts and some things like staging and remotes become more clear.

When we switched to Git, I had my team (pretty small) basically treat Git like SVN for a little while. Once they got comfortable with that, it was easy to explain some of the differences (like local/remote) and they could quickly pick up the rest.

> Monads are endofunctors in the domain of (whatever)

Monads are monoids in the category of endofunctors.

>>Commits are patches.

True, more or less, although you won't find any actual patches as such in the repository. Internally, git's storage is a lot like a backup system, and if you export a patch, it's generated on the fly.

> I mean code repository as a software developer is an essential tool it should be as intuitive to use as a text editor.

Git's no harder to use than vim.

> "Just based on the number of tutorials and posts about how Git is difficult / hard / weird"

So.. not from actually using it then?

Git is as complex as you need it to be. Much of the 'complexity' in the post is functionality that you can use to make your life easier if you so wish.

And if you don't want to use it, don't. Telling other people their their tool that does everything they need it to do is too complicated? Nup.

A couple obvious questions:

- Is it possible to design a Git-like VCS with only two or three "places" instead of five?

- What would be the downsides of such a system?

(comment deleted)
Sure, and not many. That's more or less Mercurial.
And one day we might even be able to reliably use bookmarks.
The remote repo, local repo and working directory are the strict minimum to work efficiently with git. To be fair, I barely use the stash, and if you're ok with that you can always use `git commit -am`, which commits every changes without going through the index. Lots of people do it, and I believe this is acutally how most people start with git.

It's an error to fear the number of "Places". They are here to help you, not to prevent you from working. If you don't need them, don't use them: if you're working alone you don't need a remote repository. You can always add this place in your places set at a later time. If you don't need the stash, don't use it.

The approach of the post is top-down, which is an enormous error: git is such a beast that it's impossible to grasp all its mechanics before diving in it. You should use a bottom-up approach, start with the simple tools, and gradually go up _as you need it_. Then, you start learning about `git rebase -i`, and you can't make without an index... But that comes at a later time.

git is NOT hard iff you understand the data model. Don't use it until you understand the data model.
Minor point: the stash, the local changes, and the staged changes are all very simple to grasp. In fact, you don't have to use the stash at all and you could even forego the staging area since you can just get git to commit unstaffed files directly. Sure, there is a reason those things exist, but if you are still in SVN world and are using git for the first time, these are not the places likely to trip you up. What you are likely to get confused by is things like rebasing, and the fact that your local repo can be modal, such as when there is a merge conflict while rebasing.
As soon as you want to do 'git pull' with any uncommitted local changes, you're obliged to use the stash.
Because it was created by Linus for Linux, a systems kernel. Very few people need to interact with a kernel. And the ones who do are so technically advanced they put up with the steep curve inherent to using Git. The fact that Git has gained popularity outside of Linux kernel development is secondary.
Betteridge's law of headlines states: "Any headline which ends in a question mark can be answered by the word no."

You have to modify the law a bit with this article but you get something like "Git is not hard". That is the answer to this article.

Why the heck is Git so hard? No?
Ah no. As I stated in the post, in the second sentence: "Git is not hard"

Question: Why the heck is Git so hard? Answer: Git is not hard.

The article is a false premise.

Git provides some amazing tools in a very accessible way:

  1) A great way to find regressions which is easy to automate (bisect)
  2) light-weight branches
  3) nice tools for dealing with patches (am, format-patch)
  4) rebase (squash, amend, fix bitrot)
  5) Super-simple submodules (compare this with gclient DEPS to get around SVN
     limitations!)
Not to mention the main point of Git, the distributed nature, and the ease of moving code between two repositories.

These basics are easy to learn, not demanding at all, and just feel good to use. I have trouble comprehending when people say it's difficult, especially compared to things like Mercurial (and the mq extension), or SVN.

When did blogspot break the back button?
I use both Mercurial and Git. Mercurial is just as powerful but does a much better job at hiding the underlying model and doesn't make it as easy to shoot yourself in the foot. You can see a comparison of the concepts here: http://mercurial.selenic.com/wiki/GitConcepts (maybe a little biased but I think it does a good job)
What I like about mercurial, and especially the TortiseHG interface to it, is that there are a TON of plugins/addons that give you a LOT of power when you need it.

I've needed to strip changesets once in the 2 years of using it, and rebase once. I don't get why these are considered core functionality for git, but maybe I just don't get the workflow.

One workflow with git where you rebase regularly is this (and it's roughly what the linux kernel uses):

3 branches: stable, staging, experimental

The current release is the head of stable.

Everything approved for the next release is in staging

All the patches that might get pulled into staging before it becomes stable are in experimental. This is good because you find out early if two patches conflict with each other (in the "they break each other" sense, not in the VCS meaning of conflict), but unstable stuff doesn't pollute your staging branch.

When a release happens, you destroy the experimental branch and recreate it from the new staging branch. Anybody who wants their patches that didn't make the cut for the release has to rebase them onto the new experimental branch.

I guess I don't see the benefits of this over multiple feature specific named branches off the last node on staging that got merged. Then you simply merge those each into experimental, and if all is kosher, into staging. Personal preference I guess.
Hmm in git you also rebase so a pull-request will merge cleanly when it would otherwise have conflicts. How does hg manage that?
Its not. Work Git in a simple workflow. Start with adding, amending, rebasing and stashing. Additionally incorporate it into your workflow.
Git is hard until you learn more about it. Just like programming. And using servers. And everything we do that makes us worth hiring.
I still think the absolute best way to learn git is to watch the talk Linus gave at Google some years back - http://www.youtube.com/watch?v=4XpnKHJAok8 - just understanding the underlying concepts makes the rest of it easy to grasp.
If nothing else, you can at least see what a Google talk with Linus making more light-hearted remarks looks like, compared to the LKML-related posts discussed months ago.
98% of the WTFs in Git are attributable to the poor command line interface, with badly named commands and forgettable option switches; the underlying workflow is simple. It's only palatable after you make some aliases.
Perhaps the question should not be why is Git so hard compared to SVN. A better question is, why is Git so hard compared to Mercurial. For me the problem is not the complexity of the model -- the value prospect of a DVCS is clear. The problem is the complexity of the interface.
I agree partially.

CVS and SVN lasted so long because a lot of people don't need the complexity of a DVCS model. I think there would be a lot less hate for git if it made it easier for people to remain ignorant of the DVCS magic until they said, "Boy, I wish I could..."

"Perhaps the question should not be why is Git so hard compared to SVN. A better question.."

.. might be: why are programmers so unwilling to learn to use powerful tools? Git is no less complex than your average C++ feature .. yet it gets not as much love when it comes time to learn to use it properly.

Is it really hard? Anybody can use git.
My main beef with git is that the documentation seems written not for someone learning git for the first time, but for someone who wants to develop for git and is already intimately familiar with git and all its nuances. It's dense and obscure, and more often than not it quite simply doesn't answer my questions.

To be blunt, git seems good but the documentation blows.

Maybe it was just that I happened on some good intro tutorials or something, but I found Git ridiculously easy to pick up and have never really had any problems since.

I was using SVN for my job, which was crap (big code base, everything was super sluggish and branching and merging was an absolute nightmare). I tried Git on a little personal project and immediately it felt far better. We switched at work about a year later (it took days to import > 8 years of SVN history).

The CLI has some gotchas, but really it didn't take me long at all to work that out.

And say what you want about the staging area, but I absolutely love it. You can skip it if you want (git commit -a) but I think it's awesome and super-useful.