10 things I hate about Git


Git is the source code version control system that is rapidly becoming the standard for open source projects. It has a powerful distributed model which allows advanced users to do tricky things with branches, and rewriting history. What a pity that it’s so hard to learn, has such an unpleasant command line interface, and treats its users with such utter contempt.

1. Complex information model

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. In fact, branches are tags, and files you already know about, so you really need to learn three new things. Versions are linear, with the odd merge. Now Git: you have files, a working tree, an index, a local repository, a remote repository, remotes (pointers to remote repositories), commits, treeishes (pointers to commits), branches, a stash… and you need to know all of it.

2. Crazy command line syntax

The command line syntax is completely arbitrary and inconsistent. Some “shortcuts” are graced with top level commands: “git pull” is exactly equivalent to “git fetch” followed by “git merge”. But the shortcut for “git branch” combined with “git checkout”? “git checkout -b”. Specifying filenames completely changes the semantics of some commands (“git commit” ignores local, unstaged changes in foo.txt; “git commit foo.txt” doesn’t). The various options of “git reset” do completely different things.

The most spectacular example of this is the command “git am”, which as far as I can tell, is something Linus hacked up and forced into the main codebase to solve a problem he was having one night. It combines email reading with patch applying, and thus uses a different patch syntax (specifically, one with email headers at the top).

3. Crappy documentation

The man pages are one almighty “fuck you”. They describe the commands from the perspective of a computer scientist, not a user. Case in point:

git-push – Update remote refs along with associated objects

Here’s a description for humans: git-push – Upload changes from your local repository into a remote repository

Update, another example: (thanks cgd)

git-rebase – Forward-port local commits to the updated upstream head

Translation: git-rebase – Sequentially regenerate a series of commits so they can be applied directly to the head node

4. Information model sprawl

Remember the complicated information model in step 1? It keeps growing, like a cancer. Keep using Git, and more concepts will occasionally drop out of the sky: refs, tags, the reflog, fast-forward commits, detached head state (!), remote branches, tracking, namespaces

5. Leaky abstraction

Git doesn’t so much have a leaky abstraction as no abstraction. There is essentially no distinction between implementation detail and user interface. It’s understandable that an advanced user might need to know a little about how features are implemented, to grasp subtleties about various commands. But even beginners are quickly confronted with hideous internal details. In theory, there is the “plumbing” and “the porcelain” – but you’d better be a plumber to know how to work the porcelain.
A common response I get to complaints about Git’s command line complexity is that “you don’t need to use all those commands, you can use it like Subversion if that’s what you really want”. Rubbish. That’s like telling an old granny that the freeway isn’t scary, she can drive at 20kph in the left lane if she wants. Git doesn’t provide any useful subsets – every command soon requires another; even simple actions often require complex actions to undo or refine.
Here was the (well-intentioned!) advice from a GitHub maintainer of a project I’m working on (with apologies!):
  1. Find the merge base between your branch and master: ‘git merge-base master yourbranch’
  2. Assuming you’ve already committed your changes, rebased your commit onto the merge base, then create a new branch:
  3. git rebase –onto <basecommit> HEAD~1 HEAD
  4. git checkout -b my-new-branch
  5. Checkout your ruggedisation branch, and remove the commit you just rebased: ‘git reset –hard HEAD~1′
  6. Merge your new branch back into ruggedisation: ‘git merge my-new-branch’
  7. Checkout master (‘git checkout master’), merge your new branch in (‘git merge my-new-branch’), and check it works when merged, then remove the merge (‘git reset –hard HEAD~1′).
  8. Push your new branch (‘git push origin my-new-branch’) and log a pull request.
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.”

6. Power for the maintainer, at the expense of the contributor

Most of the power of Git is aimed squarely at maintainers of codebases: people who have to merge contributions from a wide number of different sources, or who have to ensure a number of parallel development efforts result in a single, coherent, stable release. This is good. But the majority of Git users are not in this situation: they simply write code, often on a single branch for months at a time. Git is a 4 handle, dual boiler espresso machine – when all they need is instant.

Interestingly, I don’t think this trade-off is inherent in Git’s  design. It’s simply the result of ignoring the needs of normal users, and confusing architecture with interface. “Git is good” is true if speaking of architecture – but false of user interface. Someone could quite conceivably write an improved interface (easygit is a start) that hides unhelpful complexity such as the index and the local repository.

7. Unsafe version control

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. Several ways a committer can irrevocably destroy the contents of a repository:

  1. git add . / … / git push -f origin master
  2. git push origin +master
  3. git rebase -i <some commit that has already been pushed and worked from> / git push

8. Burden of VCS maintainance pushed to contributors

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… Git dumps the burden of  understanding complex version control on everyone – while making the maintainer’s job easier. Why would you do this to new contributors – those with nothing invested in the project, and every incentive to throw their hands up and leave?

9. Git history is a bunch of lies

The primary output of development work should be source code. Is a well-maintained history really such an important by-product? Most of the arguments for rebase, in particular, rely on aesthetic judgments about “messy merges” in the history, or “unreadable logs”. So rebase encourages you to lie in order to provide other developers with a “clean”, “uncluttered” history. Surely the correct solution is a better log output that can filter out these unwanted merges.

10. Simple tasks need so many commands

The point of working on an open source project is to make some changes, then share them with the world. In Subversion, this looks like:
  1. Make some changes
  2. svn commit

If your changes involve creating new files, there’s a tricky extra step:

  1. Make some changes
  2. svn add
  3. svn commit

For a Github-hosted project, the following is basically the bare minimum:

  1. Make some changes
  2. git add [not to be confused with svn add]
  3. git commit
  4. git push
  5. Your changes are still only halfway there. Now login to Github, find your commit, and issue a “pull request” so that someone downstream can merge it.

In reality though, the maintainer of that Github-hosted project will probably prefer your changes to be on feature branches. They’ll ask you to work like this:

  1. git checkout master [to make sure each new feature starts from the baseline]
  2. git checkout -b newfeature
  3. Make some changes
  4. git add [not to be confused with svn add]
  5. git commit
  6. git push
  7. Now login to Github, switch to your newfeature branch, and issue a “pull request” so that the maintainer can merge it.
So, to move your changes from your local directory to the actual project repository will be: add, commit, push, “click pull request”, pull, merge, push. (I think)

As an added bonus, 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.

“Bread and butter” commands and concepts needed to work with a remote Subversion repository.

And now here’s what you need to deal with for a typical Github-hosted project:

The “bread and butter” commands and concepts needed to work with a Github-hosted project.

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

Update (August 3, 2012)

This post has obviously struck a nerve, and gets a lot of traffic. Thought I’d address some of the most frequent comments.

  1. The comparison between a Subversion repository with commit access and a Git repository without it isn’t fair True. But that’s been my experience: most SVN repositories I’ve seen have many committers – it works better that way. Git (or at least Github) repositories tend not to: you’re expected to submit pull requests, even after you reach the “trusted” stage. Perhaps someone else would like to do a fairer apples-to-apples comparison.
  2. You’re just used to SVN There’s some truth to this, even though I haven’t done a huge amount of coding in SVN-based projects. Git’s commands and information model are still inherently difficult to learn, and the situation is not helped by using Subversion command names with different meanings (eg, “svn add” vs “git add”).
  3. But my life is so much better with Git, why are you against it? I’m not – I actually quite like the architecture and what it lets you do. You can be against a UI without being against the product.
  4. But you only need a few basic commands to get by. That hasn’t been my experience at all. You can just barely survive for a while with clone, add, commit, and checkout. But very soon you need rebase, push, pull, fetch , merge, status, log, and the annoyingly-commandless “pull request”. And before long, cherry-pick, reflog, etc etc…
  5. Use Mercurial instead! Sure, if you’re the lucky person who gets to choose the VCS used by your project.
  6. Subversion has even worse problems! Probably. This post is about Git’s deficiencies. Subversion’s own crappiness is no excuse.
  7. As a programmer, it’s worth investing time learning your tools. True, but beside the point. The point is, the tool is hard to learn and should be improved.
  8. If you can’t understand it, you must be dumb. True to an extent, but see the previous point.
  9. There’s a flaw in point X. You’re right. As of writing, over 80,000 people have viewed this post. Probably over 1000 have commented on it, on Reddit (530 comments), on Hacker News (250 comments), here (100 comments). All the many flaws, inaccuracies, mischaracterisations, generalisations and biases have been brought to light. If I’d known it would be so popular, I would have tried harder. Overall, the level of debate has actually been pretty good, so thank you all.

A few bonus command inconsistencies:

Reset/checkout

To reset one file in your working directory to its committed state:

git checkout file.txt

To reset every file in your working directory to its committed state:

git reset --hard

Remotes and branches

git checkout remotename/branchname
git pull remotename branchname

There’s another command where the separator is remotename:branchname, but I don’t recall right now.

Command options that are practically mandatory

And finally, a list of commands I’ve noticed which are almost useless without additional options.

Base command Useless functionality Useful command Useful functionality
git branch foo Creates a branch but does nothing with it git checkout -b foo Creates branch and switches to it
git remote Shows names of remotes git remote -v Shows names and URLs of remotes
git stash Stores modifications to tracked files, then rolls them back git stash -u Also does the same to untracked files
git branch Lists names of local branches git branch -rv Lists local and remote tracking branches; shows latest commit message
git rebase Destroy history blindfolded git rebase -i Lets you rewrite the upstream history of a branch, choosing which commits to keep, squash, or ditch.
git reset foo Unstages files git reset –hard
git reset –soft
Discards local modifications
Returns to another commit, but doesn’t touch working directory.
git add Nothing – prints warning git add .
git add -A
Stages all local modifications/additions
Stages all local modifications/additions/deletions

Update 2 (September 3, 2012)

A few interesting links:

About these ads

459 thoughts on “10 things I hate about Git

  1. #7 only irrevocably destroys data in the remote repo if you 1) have no direct way to interact with it (eg. GitHub), 2) nobody has cloned the data in question and 3) if you don’t have your local repo to recover it from again.

    As long as (3) doesn’t apply, you can run `git fsck –unreachable` to recover your lost commits.

    Git is not meant to be user friendly or uncomplicated to beginners. Anybody who tells you otherwise is pulling your leg. Mercurial is meant to be (and still survives because of it), but it’s not quite as powerful as a result. Bazaar complicates things even more for reasons that escape me.

    Subversion doesn’t even count, because anybody can write a simple VCS if they don’t have to make it distributed. (Just like anybody can build a simple cluster, so long as it doesn’t have to be fault-tolerant.)

    • Tim, you assume (as I think many Git users and developers do) that power and user-friendliness are somehow mutually incompatible. I don’t think Git is hard to use because it’s powerful. I think it’s hard to use because its developers never tried, and because they don’t value good user interfaces – including command lines. Git doesn’t say “sorry about the complexity, we’ve done everything we can to make it easy”, it says “Git’s hard, deal with it”.

      Here’s an interesting example: “git stash”, until a recent version, was basically broken: it left untracked files behnid, even though its man page stated that it left a “clean working directory”. They’ve now added a new option, “git stash -u”, which behaves the way git stash should always have worked. Now, making “git stash” perform incorrectly without the extra option is not “more powerful” – it’s just that they don’t value a sensible, intuitive user interface high enough to be willing to change the default behaviour from one version to the next.

      I also think the mess that is Git’s interface arose because DVCS was basically a new concept and they didn’t know all the features it would need. If they’d known about rebase at the start, it would have been more deeply integrated, something like “push –linear-merge”.

      (And your point about recoverability of “unrecoverable” Git commits is well made.)

      • Steve, I didn’t mean to imply that powerful and user-friendliness are mutually incompatible. I completely agree that Git really doesn’t even try.

        I’ll come back to Mercurial (Hg) here to counterpoint – it’s the rival project, and it tries to be usable first, and powerful second. It does most of the things Git does, but tries to do it without hurting beginners. If the command is dangerous, you have to enable it on first. A good example is “rebase”, because it destroys history (though by default there’s a local backup). The equivalent to the Git “clean” command, “hg purge” is likewise an “only if enabled” command.

        There’s a trade-off though. There are things in Git, like “replace”, that will never be user-friendly because of what they do. In many cases Mercurial doesn’t even provide them, because a work-around exists and adding excessive numbers of commands works against their “user-friendly” aim.

        In Hg, you can’t remove or hide remote commits. Period. You want to rebase and push those commits again? You’ll need remote login access to strip the previous commits first. (BitBucket now provides a user interface for doing this.) Git makes it very easy to do this, on the assumption that you “know what you’re doing”. Hg makes it hard to do stupid things (like blow away public history), because it assumes you probably don’t.

        At my last job, I picked Hg for our developers for precisely this reason. I was very happy with it, and used to think all the Git enthusiasts nuts. I used to loath Git’s “shiny with sharp edges” nature. However after using it extensively it really is a better expert tool. I think the reason it’ll never become more user-friendly is because nobody who develops Git is interested in usability – there are other options for those that want them.

        Oh, and “rebase” is a separate command in both Hg & Git for a very good reason – it always modifies history, unlike a merge (which doesn’t ever modify history).

      • I totally agree with you that they didn’t try on the user interface, and that they were still discovering some of the features they needed out of DVCS.

        However, I think that the reason they didn’t focus on the UI was for the sake of the developers who would use the tool (and because they ate their own dog food). I would argue that the complex set of commands, and even some of the inconsistency, is for the sake of easy extension and integration. I think the set of commands is complex because they act almost as an API for applications to interface with Git, in a way similar to how many standard Unix utilities are useful for programming. The lack of abstraction leading to complexity is planned, I think, so that applications can have more control over how they interface. The inconsistencies are likely there so that they don’t break any existing applications which may depend on certain functionality (even if it isn’t to spec).

        Basically, Git is not intended for those who don’t want to learn a new, complex tool. It’s intended for developers. Not planning for it’s wide-spread adoption may have been a fault of the project. However, I think the API-like interface also provides opportunities that would not be available had Git gone with a clean, abstracted interface.

      • “Basically, Git is not intended for those who don’t want to learn a new, complex tool. It’s intended for developers.”

        I think your assumption that developers want to, or at least can be expected to, spend time learning developer tools is misguided. It was more reasonable 20 years ago. These days, we have so many tools and technologies to deal with, that they all must be made as learnable and intuitive as possible.

      • I don’t feel like your git stash example is entirely fair.

        Nowhere in any of the git documentation does it say that it will operate on untracked files other than in the documentation for git add and commands which do an implicit add. git stash worked exactly the way it was described. Just like the vast majority of the git commands they work on the working directory’s tracked files. Not every file in the working directory regardless of if it is tracked or not.

        Honestly if git stash worked the way you describe (the -u option being the default) it wouldn’t work the way I wanted it to and I’d be much more hesitant to use it!

        To say that git stash performed incorrectly is to push your own opinion on what the correct action of stash should be while ignoring the way that git operates.

        If git stash -u was the default you probably still wouldn’t have liked it. You’d just cherry pick it as a completely different example. I could see you having written something like the following:

        “Yet another example of the inconsistency in git is ‘git stash’. Where most of the commands in git operate on a set of tracked files in the working directory, git stash works on the working directory as a whole. This can cause confusion when you end up stashing and essentially removing hidden or meta-data files in your source code which weren’t meant to be tracked by version control as a side effect of temporarily stashing some changes.”

        It feels a little bit like you’ve started with the conclusion “I hate git because it is inconsistent and the commands are needlessly confusing” and are searching for examples to prove it. Instead the better action would be trying to learn how git is used as git, why it works for the developers using it, and forming a conclusion afterwards.

        That said, it does seem like you have in fact given git a try. I’m not sure the above characterization is entirely fair… but it is the impression I get from the cherry picked examples with no care given to how it fits into the workflow of a developer using git.

      • “Subversion doesn’t even count, because anybody can write a simple VCS if they don’t have to make it distributed.” You truly have no idea what you’re talking about. it was a wholly different world when Karl Fogel and company wrote SVN. You seem to have no concept of how difficult it is was to create SVN in a world where there were few good tools, very little OSS, and a much more limited concept of VCS. That SVN succeeded so well at the task you dismiss out of hand is corroborated by its wide and enduring popularity.

  2. So in terms of useful functional for you daily work, what couldn’t Mercurial do that Git could?

    One thing I find a bit frustrating in this whole debate is that in theory, interface and underlying capabilities should be separate and interchangeable. It ought to be possible to have a git-like interface Mercurial if you want that extra power (eg, rewriting published history), and it ought to be possible to have a Mercurial-like interface to Git for ease of use. But for some reason (perhaps because of CLI’s dual role in scripting) that never really happens.

    Incidentally, notice that “git clean” also by default is disabled: clearly the Git developers are capable of making intelligent user interface choices. But instead of this output:

    fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean

    how about:
    “clean wipes all untracked files from the working tree. Use ‘git -f’ or unset clean.requireForce if you’re sure. Use ‘git -n’ for a dry run.”

    Ok, now I’m just dreaming.

  3. > So in terms of useful functional for you daily work, what
    > couldn’t Mercurial do that Git could?

    Very little. Mercurial doesn’t have the index (modified files are just committed) but it has the “MQ” plugin which can handle the same behaviour. Light-weight branches are slightly more fiddly with Hg bookmarks, but they’re a reasonable approximation to Git’s branches now. (Took long enough though….)

    I could not have easily done the CoreTardis-MyTardis history join with Mercurial, but that’s hardly day-to-day.

    > It ought to be possible to have a git-like interface Mercurial
    > if you want that extra power (eg, rewriting published history),

    That would be nice, but the Hg devs would probably prevent any core changes that would allow that behaviour, and I don’t think plugins can influence the wire protocol. Their aim is to avoid lost commits at the expense of “things you misguidedly might think are a good idea”. You might be able to trigger it via remote hooks somehow though.

    This is a good example of the mindset of the average Hg user:
    http://jordi.inversethought.com/blog/i-hate-git/

    “I didn’t even *consider* that a VCS could remotely *delete anything*.”

    > and it ought to be possible to have a Mercurial-like
    > interface to Git for ease of use.

    It’s called Hg-Git. ;-)
    http://hg-git.github.com/

    • Average hg user here…

      hg-git is a crutch. I’ve tried it a few times. It sometimes didn’t work at all, and I was unable to push from an hg repo to a git one. I didn’t figure out what the problem was, but the real problem for me is that people use git, and I have to work with them.

      The are also other more fundamental problems that git-hg can’t solve, such as how hg stores different metadata (e.g. branch names) that are unrepresentable in git.

      I wish I could just avoid using git, I really do, but there’s a whole community of people there who make it impossible.

      • I use hg-git whenever I interact with a git repo. When I use it for larger-scale development, I use a bridge repo (hg clone git://… git-bridge) so I have one point of interaction with git. For working on something I then clone the bridge-repo, hack on it, push back into the bridge repo and push from the bridge repo into git.

        (that’s the old outgoing-incoming repo structure :) )

    • For merging history, did you check the convert extension? That can rewrite filepaths, get partial history and all that stuff.

      If the history is similar you likely don’t even need that:

      The honest way (shows the real merge: do this if dishonest history is no requirement):

      cd repo1
      hg pull –force repo2
      hg merge
      hg commit -m “merged repo1 and repo2″

      The rebase way:

      cd repo1
      hg pull -f repo2
      hg phase -d -r “all()” # allow rewriting published history
      hg rebase -s -d .

      The regrafting (can join anything, but is more work):

      hg init newrepo
      hg pull -f repo1
      hg pull -f repo2
      hg graft $(hg log –template “{node} ”
      hg phase -d -r “all()”
      hg strip
      hg strip

      • hm, lost a tag to the filter… rebase way again:

        The rebase way:
        cd repo1
        hg pull -f repo2
        hg phase -d -r “all()” # allow rewriting published history
        hg rebase -s [first commit of repo2] -d .

        and regraft:

        hg init newrepo
        hg pull -f repo1
        hg pull -f repo2
        hg graft $(hg log –template “{node} ”
        hg phase -d -r “all()”
        hg strip [first commit of repo 1]
        hg strip [first commit of repo 2]

  4. Your git diagram illustrates how to contribute to a project that you are not an approve contributor on.

    How would you contribute to a subversion hosted project that you didn’t have permission to contribute to? Most projects have tight reins over who can contribute, and they would tell you to submit a patch.

    These extra steps should be included in your subversion diagram.

    • My guess, based on admittedly limited experience, is that it was much more common to grant direct commit access on Subversion projects than Git ones. MediaWiki is a case in point: it had dozens, perhaps hundreds of committers. It’s currently switching to Git, and simultaneously switching to the “gated trunk” model with very few direct committers. They’re also using Gerrit, a code review tool, which I understand to be a whole extra source of VCS pain :)

      But yes, perhaps I should include patch submission as an alternative path in both diagrams.

      • The way it used to work when everyone used CVS/SVN was to submit patches by email. Commit access was still pretty guarded, as unknown people can’t be trusted not to be assholes.

      • Keep in mind that just because many Open-Source projects does that, doesn’t mean all have to, if you feel more like just allowing people to commit to your repository, then by all means… After all Forks and Pull-Requests isn’t even a Git thing, it’s a Github thing… (and other Git tools tend to begin to follow suit, like Stash)

        I see it as a great feature…

        Just allowing commit access to your repository is fine as long as there are few contributors, but how will you ever make sure that your projects stays on it’s track towards it’s vision if you allow thousands of contributors commit access?, even open source projects need someone at the rudder… I know from a “patchers” perspective, it may be a bit cumbersome, but as the tools get along it gets easier and easier to work this way, and today it’s mostly done with a single click of a button… All the commands are neatly hidden beneath…

        Turn it around, many/most open source projects are handled in spare time, giving the repository owners more tools to manage what is accepted into the project at the expense of the developers time may seem ridiculous at first. But for each 15 minutes you may spend extra, you may save 5 minutes of the owners time… Try to multiply that by a thousands… If it becomes to big of a task to accept incoming patches, they bulk up and some of them will never be accepted because there simply isn’t enough time…

        The Github model speeds that up for the owners by an incredible huge factor… Yes at the expense of your time… But in the end it means that more contributions are accepted in the end, doesn’t that serve everybody’s interest?

  5. Agreed, it is complex.

    #7: Contributors with push access need to be painfully aware of what forcing a push does. It’s pretty rare that you should have to use it. If private hosting with Gitolite you can use ACLs to prevent rewinds on branches; a force push being an extreme form of rewind+ff. It’s a pity this isn’t possible on Github. However it’s worth noting that the old history is probably still available in your reflog and in other people’s clones.

    #9: Much the same applies to rebasing. It’s a really useful tool. Many SVN users procrastinate committing their work before they are 100% happy. That’s a complete anti-pattern for VCS. Git encourages you to commit frequently with the promise that you can tidy up later. The only rule of thumb being that you shouldn’t rebase a commit that has already been pushed; which would require a force.

    #10: That’s a poor comparison. You assume that the SVN user has direct commit access to their own project but the Git user is collaborating with third-parties on Github.

    • Re: #9, I think the same “anti-pattern” applies to Git. The difference is with Git you commit frequently to your *local* repository. If you frequently commit small, poorly-defined chunks of work to a public repository you will soon receive complaints. And while Git “promise[s] that you can tidy up later”, for novice and intermediate users, that tidying up is extremely difficult. (Witness the lead maintainer of a Git hosted project confessing insufficient “Git-fu” to cherry pick a series of commits here)

      Re: #10: Intentionally, because SVN is associated with a culture of direct committing, and Git isn’t. (And because that’s my direct experience based on three projects I’ve worked on that switched from SVN to Git.)

      • Your assumption that those local commits have no value is wrong. They ability to locally commit and use it as a worklog is fantastic, and if you fix a bug you can just cherry-pick it to a production branch from that local branch. Following on that, the idea the squash and cherry-pick are complex commands is borderline insane to me, they are both exceptionally straightforward, some of the easiest parts of git to learn… it sounds like someone has never bothered to try them if they are having issues with them.

        Seriously, let me teach you git cherry-pick. Find the commit you want… note its hash. Checkout the branch you want that applied to… git cherry-pick … you now have enough git-fu to cherry-pick.

        Regarding cleaning up existing commits (extremely difficulty according to you). So, lets say you have done 8 ugly commits, and you want to clean them up…. git rebase -i HEAD~8 … it will combine those into one commit and pop up your editor with all your commit messages allowing you to summarize / write-up whatever you want.

        I suspect people are confusing git being hard, with an absolute inability to be bothered to learn the tool.

      • I’ve used ‘git squash’ (or rather, ‘git commit’ in interactive mode), and find it unintuitive – I rarely get the result I want on the first try. The problem is that “squashing” a commit really means combining it with another – but I never remember if it combines it with the previous or next commit.

        ‘git cherry-pick’ is fairly straightforward, and works – but usually feels like a workaround when something has gone wrong.

        “I suspect people are confusing git being hard, with an absolute inability to be bothered to learn the tool.”

        Not in my case.

  6. Understanding that mq is hg’s answer to the index/rebasing/etc. –
    that’s a problem for me, because I find mq pretty awful. It amounts to a new VCS, except its interface is not really more usable than git. So why am I using hg, again? Even if hg is easier and saner at the beginning, if you need staging then git very quickly becomes easier because hg requires you to use mq to work on your commits, while git allows you to use a pretty good VCS to work on your commits (namely, git).

    I should not be forced to start proliferating working copies just to put together clean commits to a public repo, that is insanity.

    • Why use mq at all? Hg doesn’t force you to have a stage area as git does. I have never needed something like this and I’m pretty fine this way.
      The workflow should be kept as simple as possible. I think that #8 “Burden of VCS maintainance pushed to contributors” is particularly interesting.

      Great article!

      • One of the main points of git is that maintenance is pushed to the edge, it allows for greater scaling. Imagine if Linus had to do the house keeping for every coder on the kernel; nothing would be achieved. It’s not a bug, it’s a feature.

      • Matt :
        It’s not a bug, it’s a feature.

        It’s a system which is easy to use for maintainers but hard for contributors and which places most of the workload onto the contributors.

        Shouldn’t a system which places more work on the contributors be especially easy to use for contributors?

  7. I’ll get yelled at for this one, but before all of these systems there was BitKeeper, we’re still here and if you want the power of DVCS and not all the gotchas of a sharp and pointy Git, check us out. Expensive but we do stuff that you can’t do in Git (yet, I’m sure they’ll catch up).

    • The annoying thing about VCS, compared to say, an editor, is that the basic rule of “if you don’t like it, use something else” doesn’t apply. (So in my case, since I never start open source projects, I’ll never get to choose a Git alternative.) It’s a pity the DVCS authors haven’t been able to separate interface from infrastructure, coming up with a robust information model that different front ends could support.

    • I wouldn’t mind paying for bitkeeper if you made it free. I have paid for free software, but the non-free stuff you did to Linux about forbidding reverse-engineering the protocol is unforgivable, especially if you plan to keep on doing that.

  8. I Agree!!
    I’m still trying to figure out how to use Git. It’s just not logical … well for me at least. Most of the time I’m the only one working on it and just want to be able to securely store it off-site at my hosting provider with the ability to roll-back if needs be – Simpler would have been much better

  9. The very defensive counter arguments from self proclaimed powerusers, is very shaky. There are just so many permutations of potential error and problems with Git that even power users are most likely ignorant of just how many errors they introduce into thier beloved system.

    Reminds me of the DOS WordPress defenses.

    Glad to find out about Mercurial

  10. Heh, what you expect from “below average” Torvalds, who created such rubbish as Linux?? :) He writes as he thinks.
    Mercurial, having the same powerful features, looks way more professional.

    • I’ve got nothing against the approach that led to Git being created. I just wish that:

      1. Its developers recognised the value of clear abstractions and good UI design (even for command-line)
      2. Its users and developers were more willing to break backward compatibility of the interface in order to improve it
      • Since git relies on shell scripts for extensions, you cannot actually change the commands without breaking everyones scripts…

        That porcellaine is pretty much set in stone, but the name fits since it makes everything built on it extremely brittle…

      • steveko :
        I think some issues with Git can be summarised as “it forces you to structure the *changes* to your code, in addition to the code itself”. Sometimes (in established, large projects), that forced structure is a good thing. Sometimes (for beginners, and in smaller projects), it’s a hindrance.

        How are you forced by git to make feature branches? If you like you can work directly in mater and never create any branches. Or, if you can prefer, you can make all your changes in the same branch (and then pull that into master, this might be good if you are using github).

        I hope that at least some people here are able to distinguish between “git” and “github” as well as being able to distinguish between “a good idea” and “being forced”.

        Arne Babenhauserheide :
        Since git relies on shell scripts for extensions, you cannot actually change the commands without breaking everyones scripts…
        That porcellaine is pretty much set in stone, but the name fits since it makes everything built on it extremely brittle…

        Why should you need to change the commands?

        In general, when dealing with an interface of any sort, you never change existing interfaces, you only add new interfaces. You do not even deprecate old interfaces until after you have addressed most all of the needs being addressed by the older forms. (And deprecating basically means you go for some period of years with the old interfaces working, but setting off warnings when they are used.) In some cases you can get away with deeper changes (like when there’s an accepted spec and you are living within it), but you need to be careful — that way lies madness if you go too far. Actually, introducing new interfaces can get crazy also. The most useful thing you can do with most interface changes is to reject them…

        Still, when you have a good interface change, and you’re ready to deploy it? You can do that.

        For example, currently git clown will not do anything except ask whether you meant “clean” or “clone”, but if you had a good interface design for git clown, nothing would conflict with your implementing it.

        Of course, and this is worth repeating: then you have to ask yourself, why anyone should need a “git clown”…

      • How are you forced by git to make feature branches? If you like you can work directly in mater and never create any branches.

        Git, despite its protestations, is a social tool. Decisions like these “If you like, you can do X” are rarely up to one person – you need to do what the team does.

      • steveko :

        How are you forced by git to make feature branches? If you like you can work directly in mater and never create any branches.

        Git, despite its protestations, is a social tool. Decisions like these “If you like, you can do X” are rarely up to one person – you need to do what the team does.

        This implies that solutions to these issues need to be social rather than technical.

      • rdm :
        Why should you need to change the commands?

        Because if you are not already used to git, the current commands are pretty unintuitive and hard to learn.

        If you want an unchanging interface, you have to design it cleanly from the start and be extremely conservative with changes. Otherwise you get help output as the one seen in `git help pull`, because you can never throw out a bad idea later on.

        And the easiest way to state that you want an unchanging interface is to tell people to use it in scripts. As soon as you have enough users, every change to an existing option wreaks havoc to so many scripts which you do not control, that you cannot actually do the change.

      • Arne is confusing the API, where your semantics are fixed once you name them, with user interface. The fact that the API and the commands can both be accessed by the shell *is* confusing.

  11. This kind of simplified FUD is just not constructive. Anything you can do in subversion you can also do in git.

    Try to maintain a large project in Subversion before you say such things. Its a horror and all the simple things about the subversion api is just not worth anything.

    No, FUD is what it is.

    • Actually to maintain a large project in SVN is quite easy – you can easily checkout partial bits, merging and branching can apply to sub-sections of the repo (which is why svn merging isn’t quite as good as gits, it has to deal with more complexity). I worked on a 3Gb repo at a previous company, without any problems.

      Part of the problem is that no-one considers the cases of a system they always prefer to spread FUD in favour of their preferred system. Don’t criticise someone else for spreading FUD and then do it yourself!

  12. Git has beautiful technical design but quite appalling usability design.

    You can Commit, Fetch, Merge, Publish, Pull, Push, Rebase, Stage, Stash and Track. To a beginner these all sound like they might do the same thing.

  13. #6 and #8 and #10 strike at the crux. git is thoroughly decentralized, to the point where everyone is a peer. Everyone is a committer, everyone is a maintainer. Branches and tags are unshared by default. Someone could potentially interact with many other peers, and hence have many “remotes”. To some degree, this level of decentralization is just a total paradigm shift. As others have mentioned, Mercurial is more moderate in this way.

    No argument from me about the learning curve and negative usability of the information model, documentation, and commands.

    • “Everyone is a committer, everyone is a maintainer.”

      Well put – humble contributors never had to be maintainers before.

    • «Visual SourceSafe Is still around, there’s a reason for that.»

      And for both that reason it’s called “loss aversion”.

      • You mean “transition costs” rather than “loss aversion” I believe. And that’s a perfectly valid reason to stick with something if the benefits from switching aren’t high enough.

  14. A rubbish article, compare apple with orange. Please identify what you are comparing? Distributed VCS or Centralised VCS, you should either present how SVN being use in distributed environment in order to compare with the Git having the same usage, or present how Git being used in centralized environment in order to compare with SVN having the same usage. This will benefit newcomers to learn how thy should use them and which tool is more suitable.

  15. one of the best complaint about GIt I’ve ever heard, I completely agree with you !

    I can even add :
    1/ no decent IDE support (for ex, in eclipse Git has a completely different GUI from svn or cvs : where is my commit messages history, the possiblity to ignore untrack files, …)

    2/ once you’ve screwed something, it is really hard to go back.
    For ex, if you fetch then commit then push … OMG you’ve forgoten to merge so the remote repo say “no, you can not commit” but this can be a real pain to merge you own local copy with “itself”

  16. For my code to be safe I have to feel in cotrol of it. With git I feel lost and insecure. How safe is my code?
    Glad to see I’m not alone with this feeling…

  17. I like git. I have used SVN, TFS, and though shamed to admit it, VSS (against my will).

    Here is an assessment from my point of view.
    TFS – Hands down the best option for a large team of .NET developers working a single project. However I find it’s overkill in smaller project with say 1-5 developers. It’s just too involved.

    VSS – Total Crap! if you use this product willingly, you should be drug out into the street and shot. This is where I could go an a rant but I wont. Just google VSS and you will see.

    SVN – Great open source source control. There is not a lot to complain about. There are a lot of great add-on’s available for visual studio as well. As a mater of fact my home development server ran SVN for years. However, I did switch every thing over to git. My issue with SVN is the same as my issue with TFS, It’s just too involved. You have t have a server just like TFS. There is administration work involved just like TFS. I didn’t realize I could git by without these tasks until I started using git. Like TFS though, it’s a better option for larger teams.

    GIT – Fast, Flexible, and easy. It’s takes me all of 2 seconds to set up a new repository. I have retired my “development server” and just use Dropbox, Github, or Bitbucket (Check out Bitbucket if you don’t allready know about it. The are just like Github, but you can have free private repos) as my remote. It’s so fast and simple that for me it takes the work out of source control. I do feel that TFS or SVN is better for larger groups though due to all the Administration options available. There are just more ways to manage them that are not really necessary for smaller teams. The other downside of git is that some folks are afraid of command line tools for some reason. My advice to this person is to grow a pair and learn the tool because it’s worth it. You won’t find me talking that way about any other command line tool period and I have to use svcutil, stsadm, and a couple of others out of necessity. I don’t go around talking them up because they would be better as GUI tools in my opinion. With git I feel this is not the case. The BASH makes it faster which is what I truly love about git to begin with.

    That’s my 2 cents. Take it for what you will.

    -Adam

    • As someone who is forced to use TFS in a situation that TFS wasn’t made for (non Visual Studio work), I loathe it with a passion.
      I’m sure it’s great for VS users, but us linuxy guys get totally shit on.

      And as a related note, who the hell thought it was a good idea to use the write bit of the permissions as the is-this-checked-out flag?!

  18. git follows a simple unix philosophy: make it scriptable.
    and also “do one thing, do it well” (this applies to the individual parts, git is made of a bunch of smaller programs that make up the whole suite not just one monolithic program)
    all the command line things are made to be scripted and if someone wanted to make a simple GUI for git they could, just no one care enough. just about everyone who uses it, and everyone who uses it and has the capacity to make the gui, don’t care enough to make one. they are fine with the script and programs that make up the git suite.

    also you mentioned above the basic commit:
    git add
    git commit
    git push
    you can script that to have one script do all those, call it “checkin.sh” or something
    #!/bin/bash
    (git add && get commit && git push && echo “done”)|| echo “failed”;

    anything you find yourself doing often can be dumped into a script, that is the philosophy behind it, leave matters of interface to other people, design the system to be fast, handle merging well, be distributed, etc but allow it to be scriptable so people can build interfaces on top of it to their hearts content.

    • I actually think git fails on both those counts.

      1. “do one thing, do it well” – Git tries to be both the infrastructure (which I think it does well) and the interface (which it does terribly). The hodge podge of really commands (“git am” being my favourite) is testament to this.
      2. “make it scriptable” – It’s much easier to script things with consistent behaviours and easily understood commands.

      But yes, you can obviously script your way around anything for one local environment. Not a great solution, in my experience, if you’re frequently working on different environments, and in different teams. (“You’re having trouble committing? My “gitcommit” script runs just fine…”)

    • By making it scriptable using the basic commands, they pretty much barred their way towards ever having a simple interface.

      If they change one of their core commands in a backwards-incompatible way, all user-scripts break. And this already happened (there was a simpler git ui whose name I forgot. It tried to wrap around the git commands and regularly broke down because of some incompatible change).

      You cannot be scriptable, fast evolving and easy to use at the same time.

      • “You cannot be scriptable, fast evolving and easy to use at the same time.”

        You can if you use good abstractions for your API. But that requires more careful thought up front….

  19. Thank you for this. I’m struggling with trying to contribute to a GitHub hosted Open Source project. I thought it was me. Glad to know it’s git.

  20. Pingback: 我痛恨Git的10个理由 | 曹志士

  21. Pingback: 我痛恨 Git 的 10 个理由 - 博客 - 伯乐在线

  22. One day on a big project using GIT I got an email saying not to commit any changes or pull anything because the repository had been inadvertently reset to the state it was in three weeks before.

    It appears a developer had returned from holiday and having found it hard to merge their work simply forced a push.

    This could be seen as an argument against git. I suspect Management would consider it an argument against holidays.

    I cannot think of anyone who has used git and liked it.

    Could someone point out what advantage a distributed version control system has over (say) a clustered SVN system?

    • They should have enabled the non-ff option on the remote – which is there for precisely this reason.

      Anyway, to answer your question, if you’ve ever had to work on a less than 100% available link, or a link that’s slow and/or expensive, then having git is invaluable.

      In a more prosaic setting, I’ve found found git awesome for being able to track an upstream project with git, pull in and review their changes at regular intervals, and apply my local platform changes over the top.

      I don’t even know how I’d approach that with subversion without a whole bunch of jiggery-hackery.

      • Right, well I wrote this blog post in a fit of rage at the crappy user interface decisions one has to deal with; I’ve never really doubted the great benefits the underlying Git infrastructure has to offer, with its superior branching and merging features. The user workflow could be still improved further though: on one project, I’m now in the situation of having to create a branch, commit code, push, then issue a pull request, then later delete the branch (and push the deletion) for every minor feature – sometimes as few as 2-3 lines of code. This could definitely be streamlined – but Git wasn’t written for contributors, it was written for maintainers.

      • It used to be that you’d contribute your changes upstream, and people would work to produce stable, well-defined, documented, clean projects.

        Now everybody just hacks and slashes there way in, and then proclaims git to be a godsend because it enables work-generating decisions like “I’m (and everybody else) is going to maintain a fork forever”. So then you wind up wasting time, forever, instead of just paying the up-front cost to design software properly.

        In terms of market share, Linux is a success, In terms of technical quality, Linux is an unmitigated disaster zone of low quality code, failed designs, and rewrites. Git was built to support that development model.

      • “I’m now in the situation of having to create a branch, commit code, push, then issue a pull request, then later delete the branch (and push the deletion) for every minor feature – sometimes as few as 2-3 lines of code. This could definitely be streamlined – but Git wasn’t written for contributors, it was written for maintainers.” — That’s not quite fair; part of git’s core design involves accepting emailed diffs as full patches. Pull Requests (and the concomitant branch mania) are a relic of the Github Era, not Git itself.

    • That is a serious reason not to use it. The whole point of a SCM is to protect your commits. Anything else is just gravy.

      I’ve worked at a place where every so often someone would pop up to the git guru and ask for assistance as they thought they’d just trashed their work. That might be ok in an open source situation, but totally unacceptable if you got paid to write it. I’ve used git for a project and all I did was commit and push to master (it was just me using it) but even then one day I found it had pushed to a branch and required a pull… I still have no idea how I managed that given my workflow.

      Maybe when the SVN guys add shelving, the reasons people use git will go away, but I doubt that. The reasons to choose it seem more political than anything else. Maybe someone will create a ‘centralised SCM for decentralised teams’ that had the ease of SVN with the convenience of git.

  23. SVN is great as long as 1) you have a fixed set of developers, 2) you don’t do much branching. Git supposedly – I don’t have much experience with it myself – makes exactly these things (“anonymous” commits and branching) easy.

    If you want to include contributions from anyone, then the simple “update, code, commit” workflow turns into something like “update, code, diff >> foo.patch, find bug tracker/mail address/whatever that project uses, open issue/write mail, attach patch, submit, download patch, apply, commit”, which must rely on big complicated hard-to-automate stuff designed for completely different purposes (like a mail client or a web browser), and most of the easy-to-automate stuff (like syntax checking and unit tests) can only be run after all this has been done manually, so integration becomes a huge bottleneck.

    If you need to merge between branches, as far as I understand the information model of SVN is just not really good for that, and so you are continuously confronted with stupid behavior (such as your own commits causing tree conflicts when you merge them back from trunk), and operations including deleting and renaming files can become quite destructive. (Worse, they often seem innocent when performed and become destructive when merged – e.g. if you delete a file and add some other file with the same name, that will be fine as long as you make them in separate commits, but when someone tries to merge them in at once, all hell breaks loose, and usually you have to delete the whole working copy, check it out again, find the offending commits – great fun if you were merging half a year’s worth of work! – and merge in multiple steps so that they do not get applied together.)

    • Yup. SVN is really not at all suitable for distributed open-source development. I have not tried, but I can well imagine the excruciating pain and inconvenience that it would cause.

      Having said that, for small, co-located teams undertaking typical development activities in an SME-like environment, particularly when one or more team-members do not have a software development background, ease of use is paramount.

      When coupled with TortoiseSVN on Win32, Svn knocks the socks off command-line Git (Although in my mind SVN could be made simpler and less intrusive still).

  24. Create an organisation on github and your problems will be solved. It has been two years when I moved my colleagues onto git and github. None of them are programmers, and none of them had any experience of git or for that matter versioning systems. Now everybody is happily working with no problems. The workflow is nothing more than git pull, git commit -a, git push.

    Sometimes new branches are created, then you need to say precisely onto which branch to push, and you need to use git checkout to switch between branches. In two years, I had only one cock-up, but after 10 minutes of swearing I fixed the problem in 10 minutes with no changes lost. The only thing which bugs me a little bit is merge commits in history. I could do something about it, but I am too lazy.

    As a maintainer sometimes I had to dive into deeper waters, but I had no problem in finding information how to do that. I also prepared mini documentation for my users, which contains everything they need to know.

    • Yeah, the problem with advice like this, though, is that it comes from the perspective of a codebase maintainer. As I noted in my post, Git is written by, and for, VCS maintainers. My frustrations mostly stem from having to adapt to existing GitHub repositories: even if creating an organisation solves issues (I don’t know), it’s not something I could do.

      If none of your users are programmers, you’re obviously not a typical case. What are you maintaining – documentation? Do you worry about keeping a clean history, encouraging your users to rebase? If not, that’s also atypical. (I’m not trying to discredit you; I just want to clarify the situation on which my post was based, that causes so much frustration).

      • Well I call myself maintainer, but I am really only the most knowledgeable user, which pays for private repositories. Several projects are running happily without my intervention, I only participate in them for my real work, statistical consulting.

        I work on statistical projects, and git is used for sharing R code and data. I do not worry about clean history, because I did not find it useful. As I said merge commits are annoying, but they do not interfere with blame history, so I can track who did what.

        And yes I understand that my setting might not be typical. But my experience contradicts several of your points made. Hence the comment.

    • I think you highlighted an importan point here. The maintainers of the code base /repository should send a one page manual to the users / contributers that includes all the settings during setup, the commands to make changes etc..

  25. Pingback: fl0blog » Blog Archive » Learning git

  26. Thanks Steveko..
    The ironic thing is your instructions and especially your diagram and helped me understand what is going on..
    Your diagram should be included in any git tutorial / manual.

    • Yeah. Because Git documentation tends to focus entirely on the relationship between your working directory and your local repository. It glosses over the relationship between your repository and remote repositories, even though that’s where much of the complexity in DVCS arises.

      • it’s because the Linux kernel developers don’t really use shared remote repositories I believe. My impression is they instead each have their own repo and either email patches or ask others to pull from them. This quirk of how kernel development works means they do things differently from most git users. But some UI decisions were made with the kernel workflow in mind.

  27. Pingback: Free GIT repository hosting | rizwaniqbal.com

  28. #7 is simply false. Git *never* destroys anything. It only adds. If you do anything you cited on your article with the repository, you could always use reflog and checkout to a pre-destroyer push.

    • denomus, it is a recurrent myth that git doesn’t destroy data. It does. garbage collection destroys data. push –mirror can destroy refs, another kind of data (the reflog may only store hashes, but not the actual names of refs, which can be useful metadata). History-editing operations like a bad rebase can also destroy data.

      Most “common” uses of git don’t destroy data, but if you’re learning git, it’s not that difficult to destroy data accidentally until you learn to not do it.

      • Well, I agree with garbage collection. But you can recover yourself from a push –mirror or a bad rebase checking your reflog (unless it has already been garbage collected).

        But you have a point. Git is not a mere toy, and you have to take care of some things to make a good use of it. I just don’t think this is as common as the complainers imagine it to be.

  29. Amazing post! I totally agree with most of your statements. I am still a SVN/VSS user, but I also really like git; For One reason only. I care for the fact that I can use git commit without an internet connection, obviously can’t push without internet but I work on a lot of projects alone and on the go. So I like to be able to pull from my repo anywhere with connection.

    Because i have a home server, which is also my php server as well as my svn remote repo, I wanted to configure git with my current xampp virtual host setup. But having been at it for around 4 days now, looking at a lot of tutorials and blogs about setting up serving git over http. It is just so damn complicated and not user friendly. I got to the clone stage over http but just can’t get the push to work. Setting up svn under my xampp was extremely simple. I wish git was simpler, but it just isn’t.

    I wish I could use git for my primary source control but because of its complicated and the “Git’s hard, deal with it” part. I just gave up.

    But I like this article because its honest and shows a different perspective from the git enthusiast/fanboys blog post and comments, git is not for everyone.

  30. For me I find Git slow as hell a lot of the time compared to SVN. I am using Git because it is as I am told “better” but I am waiting several minutes for commits to complete when SVN would have taken seconds.

    • Really? What’s the setup? Where is the repository and how big is it? I’ve never heard Git criticised for speed before – other than the initial clone, which can be very slow.

  31. You have quite a few very valid points about Git’s usability and I won’t argue most. However, you are being overly kind towards subversion. I currently am a git-svn user and I have to deal with subversion’s limitations on a daily basis: extremely slow checkouts (think extended coffee break), my svn work directory is 4 GB, my .git directory with full history is 600MB and another 500 MB for a checkout. We have a rather messed up corporate intranet that makes interfacing with the remote svn server quite painful, especially the latency is an issue. Branching and merging requires a single person dedicated to that job. That is both stupid and costly if you are used to git. Most of the non git-svn users in our 50+ people team are eternally deadlocked on such backwards concepts as code freezes, elaborate and really messed up branching strategies, having to work one commit at the time, conflict resolution and waiting for ages for our build servers to churn through our builds. Our use of subversion is a poster child use case for why using subversion is a bad idea. It wouldn’t be fair to blame subversion for all our problems, there are many things that need fixing in this team. But it is certainly a big part of it.

    Git-svn has liberated me from that madness. I can work for weeks on my private branches (while keeping up to date with the latest changes in svn) and routinely git svn dcommit large changesets. I actually use a remote git repository for storing and sharing my branches and commits (we have a nice github like facility where I work). Scares the hell out of my colleagues because they are not used to seeing that much change in a short time frame appearing in svn. But I do my due diligence of making sure all tests pass before I dcommit so no harm gets done. Basically by the time I dcommit to svn, my work is in a releasable state. Piling up large changesets and testing them in one go would be painful in svn, which is why people don’t tend to do feature branches in the svn world.

    But Git is definitely hard to master and there is a quite high barrier for getting started. I struggled with it myself and I’ve seen other people struggle with it. It doesn’t help that it has a large overlap in the names for certain commands with svn because the semantics of those commands are quite different in the git world (e.g. git revert).

    However, the reason git is rapidly replacing subversion as the vcs of choice (most OSS projects and many corporations) is that overall you are better off with git than with svn. It enables teams to change their work flows and not be blocked on a central resource (i.e. svn). Changing the work flow is essential because it is entirely possible to use git like you would use svn, which is not a way you are going to get much out of git.

    Especially with larger teams changing the work flow is a very big deal. I agree it may seem like overkill if you have been treating your VCS as a glorified file server that you use for backing up work in progress. Which is pretty much the way most engineers tend to use it (sadly). But then, if you work that way, maybe you should consider using a version control system properly. If you use subversion properly, you’ll find that most of what you do is faster, less painful, and less error prone in git. You’ll be doing stuff you wouldn’t even dream of doing in svn because it wouldn’t be worth the pain. Fear of branching and merging is a wide spread thing among subversion users. And for good reasons: subversion absolutely sucks for these activities and you can seriously mess up a code base with a botched svn merge, thus blocking your team. The hard part of using git is learning to merge and branch properly and then unlearning that these activities are somehow dangerous, tedious and scary. They’re not. Everything is a branch in git. Your local repository is a branch. The remote git repository is a branch and if you use git-svn, svn trunk is just another branch. Git is a merging and branching swiss army knife.

    So, if you are stuck with subversion, do your self a big favor and learn how to use git-svn. I’d say career-wise picking up some git skills is essential at this point.

    • Yeah, I agree with basically all of that. SVN is easier to use, Git is more powerful. What motivated this post was the realisation that that trade-off is not inherent – it’s simply poor interface design on the part of Git. There’s no inherent reason why Git arbitrarily uses “repo branch”, “repo/branch” or “repo:branch” notation in different places.

      In my sector, SVN is basically dead – no one (myself included) really uses it by choice anymore. Partly as a result of this post, my Git skills are actually fairly decent now – because I’ve spent the time to work out the different use cases, and get my head around Git’s torturous information model.

      And yet I still constantly rub up against its irritations, and find fresh ones – like why on earth repositories don’t actually have names. The model of “I name your repository whatever I want” is much weaker than “your repository has a name which you gave to it”. Default names like “origin” work out horribly in practice (I soon forget from which repository I originally cloned), meaning you need to keep inventing procedures and workflows to avoid making mistakes – not the sign of a well-designed tool.

      • Distributed naming is very hard. What if you have two people named Steve who decided to call their repo, “Steve’s Repo”? The moment you have to start adding disambiguating information, you start ending up with something that looks like a URL: i.e, git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git. So if you want a globally unique name, that’s it. If you want to create a short name, then it should be up to you to choose what you want as a short name.

      • That’s true if you want zero chance of clashes. If you relax that constraint (with the fall back position of URLs) then you could improve usability. Imagine this:


        $ git remote add http://github.com/steve/my-repo
        Repo "my-repo" added.

        $ git remote add http://github.com/tytso/my-repo
        Failed: Default alias "my-repo" would clash with existing repo "my-repo" (http://github.com/steve/my-repo)

        Etc.

      • And yet I still constantly rub up against its irritations, and find fresh ones – like why on earth repositories don’t actually have names. The model of “I name your repository whatever I want” is much weaker than “your repository has a name which you gave to it”. Default names like “origin” work out horribly in practice (I soon forget from which repository I originally cloned), meaning you need to keep inventing procedures and workflows to avoid making mistakes – not the sign of a well-designed tool.

        Think about it for 3 seconds, and you’ll see that it’s impossible to name repositories in a distributed environment.

      • skinny :
        And yet I still constantly rub up against its irritations, and find fresh ones – like why on earth repositories don’t actually have names.

        But repositories do have local names. A repository name is the file system path to the repository.

      • Those aren’t really notations for the same thing however, which is why they are different.

        repo branch # is working on a remote repo named ‘repo’ on the branch ‘branch’ ( generally )

        repo/branch # is working with a *LOCAL* (tracking) branch

        repo:branch # would be confusing to me, as far as I’ve seen, its only branch:branch , one side of the : being “local” and the other side being “remote”

      • “There’s no inherent reason why Git arbitrarily uses “repo branch”, “repo/branch” or “repo:branch” notation in different places.”

        Yes, there is.

        “repo branch” are two independent arguments. Like when you do “git push repo branch”.

        “repo/branch” is a branch name which is a pointer to a branch of a remote repo. For example, if a remote repo has a branch called “feature-a”, you can “checkout at it”, make a change and a commit. and now you have your own “feature-a” branch with your commit, and the original “repo/feature-a” branch, with doesn’t contains your commit.

        I don’t know about a “repo:branch” syntax, but there’s a “branch:branch”, which is used when you need to deal with branches from a remote and your local repository. For example, if you want to push your new “feature-a” branch to remote, but you don’t want it to update the remote’s “feature-a”, instead, you want it to be called “steve-feature-a” there, then you can do something like “git push repo steve-feature-a:feature-a.

    • Yeah, I can understand why Svn might be getting in your way: 50 developers provide quite a large number of moving parts to coordinate.

      My Svn experience has been in teams with between 10-20 developers, using really simple branching strategies (all development in trunk), so my experience with Svn has been very very positive overall. I am currently using Hg, and (with my current use-case) can see no overwhelming advantage for one over the other. (Although I can clearly see the benefit of a DVCS for a distributed team).

      It is worth saying that much of the development that I have done has involved compute-intensive testing and performance measurement, typically run on a limited-availability resource (High Performance Computer or cluster), driven by a Continuous Integration server.

      As a result, there was never really any practical alternative to the develop-everything-in-trunk branching strategy, and distributed development was never really an option either (If the only way you have of performing a non-trivial test of your code is to run it on a centralized, shared compute resource).

      It is also worth noting that code was usually pretty well organized, and fairly “functional” in nature, meaning that change-sets normally impacted only a small number of (closely related) files, so that concurrent changes affecting the same file were a very very rare occurrence. It is also worth noting that developers were encouraged to check in several times per day, which further limited the scope of each individual change, and further reduced the probability that two changes would affect the same part of the same file.

      In summary: for small to medium sized co-located teams, I think that Svn provides sufficient functionality. Indeed, its simplicity gives it a distinct advantage in these situations. For large, distributed teams on the other hand, where developers are forced to work independently anyway, Hg or Git are obviously more suited.

      For large, co-located teams, such as the situation described above, I suspect that much of the pain of using Svn is related to the use of complex branching strategies, as well as the manner in which code is organized and development carried out. Using Git may well reduce the amount of pain, but it seems that there are other, more fundamental problems that need to be addressed, such as how the code is organized, and why (presumably independent) changes are hitting the same lines of code.

  32. I find Git much easier to use than SVN. You only need to memorise (or write down) about half a dozen commands for 95% of your work. Of course Git ninja’s like to use all the funky obscure stuff, but it’s not necessary.

  33. I have a Q actually (really looking for answers): instead of an entire repo + all branches; how about just a subset, master [+ another].

    What’s the difference between a local branch and a remote tracking of a branch?

    And why not a working dir per local branch? instead of flipping/”checking out” a branch?

    • You can just clone one branch X if you wish, but you have to bear in mind that this branch might depend on commits from another branch Y (i.e. some of branch’s Y’s commits got merged into X). In this case, you will get X’s commits plus any of Y’s commits that are necessary for X. Both Mercurial and git allow this.

      About the difference between local and remote branches, this is a gitism due to how a branch *name* IS a branch in git. Because branches locally and remotely might be in different states, they also need different names, and there’s a mapping between local names and remote names. When the local name is mapped to a remote name, this is called a “tracking branch”.

      This concept is not exposed directly in Mercurial and is seldom necessary to worry about it there.

      About one filesystem tree per branch, there is another DVCS, bzr, which actually takes this approach. With Mercurial, since local cloning is so easy, I also do this sometimes. I have local clones for major branches (the named branches) and push and pull locally. In git, this is a bit more complicated to setup since local pushing is broken (you have to “fix” it with another gitological concept called “bare repos”). It’s also possible to do this in git, but it’s not a very natural way to work with it.

    • I STRONGLY recommend keeping different branches in different working directories:- It lets me work on two or more features at once (one feature branch can be running unit-tests while I modify the source code of a second feature branch, and review the changes made on a third). It also lets me diff files more easily, and run tests & and compare performance metrics for multiple candidate features.

  34. I recently switched from Subversion to Git. My ONLY complaint about git is (as mentioned in this post) the steps to do the equivalent of “svn add/commit” seem strangely verbose. Perhaps there is some deeper reason to this I am not aware of yet, but since that is what I am doing 90% of the time, you’d think it would be faster.

  35. I submit the anecdotal evidence that I have accidentally destroyed many hours of work by running commands that sounded totally reasonable but turned out to permanently destroy data.

    • same for me, though I only destroyed about an hour and then wasted a few hours trying to undo the damage. In the end I recloned, accepting the loss of time instead of investing much more time which I could use for recreating the work instead…

  36. Git is distributed version control and subversion is not. Hence there are extra steps in commiting cause there is a remote repo to consider which is not necessary to update on every single commit. As for the then having to issue pull requests thats just again an extra step as its not needed on every commit. So actually more often than not git has same number of steps in storing code changes as subversion.

    • You probably could write an “auto-fetch/push” system for git as a wrapper/extension somehow, just have a list of peers ( instead of a central server ) in the config, and set it up so that “git commit” will do a “git fetch” , and upon no new changes in your current branch from other peers , completes the commit and pushes it to all the defined peers.

      Could be made to work. Just, why would you want to, that sounds awful.

  37. I have a pet phrase, “Gitguessing,” which means to execute a Git command that you don’t totally understand in the hopes that it gets you what you want. It also refers to making a frustrated and ignorant assumption about the current state of your local repo, index, or working directory. I’ve seen every developer I’ve ever worked with on a Git project do some form of Gitguessing. Often they end up in some bizarre state where their delicate balance of remote/tracking/index/working states has been corrupted and ultimately they manually copy their modified files into a temporary directory, re-clone the repo from scratch, and copy the files back in. That’s something I will admit to doing occasionally in the first couple years I was using Git.

  38. As far as i know, git was born out of necessity. Git was designed to be used for versioning the linux kernel (which is not a software project that you and me work on daily basis). All the hacks were not put in place but were designed into the core model.

    I feel it is insane to compare a DVCS to a VCS. It does not go by mangoes to mangoes. A DVCS _is_ a complex system than a VCS due to the Distributed features. If comparing is necessary then one could point out what Linus says in a talk that, subversion is the single most software that was started without a good reason.

    • This rant might more accurately be titled something like “7 things I hate about Git and 3 things I hate about DVCS”, but that wasn’t as catchy.

  39. > 9. Git history is a bunch of lies

    Code is meant to be read. If you’re sharing code with others, your commits are meant to be read, too.

    Rebasing lets you work however you want on your repo, then clean things up so that your commits are easier for others (and your future self!) to understand. This is a good thing.

    If you really wanted to preserve the original commits, you could probably work in one branch and then rebase onto another branch. Of course, nobody would want to accept your clean commit(s) AND the original messy ones, so you’d just be maintaining the extra branches for yourself.

    • I should add that I can’t really disagree with anything else you’ve said, so I guess it’s time to evaluate Fossil.

      • Fossil is good, which provides a fully implemented DVCS and could be simplified via autosync mode. The only weakness is it cannot handle huge source tree.

  40. About some of your things I can’t say anything since I didn’t work so much which git yet (in large projects etc.). But for the first two points: yes the information modell is somewhat complex, but from my point of view the problem is not the number of features git supports, but the number of things you have to know before you can work with git (e.g. wth is staging ?!?). Everytime I try to teach someone some basic git commands, nobody understands the staging thing the first time. I might be a bad teacher, but I think is just a little too abstract. On the other hand, I don’t know any way to make it easier without reducing the functionallity of git.
    Secondly the poor cli syntax: Somehow I don’t like anything which comes after $1. Nevertheless, those arguments can really help to shorten the workflow (git commit -am “My commit message”). Finally you can user whatever front-end you like to use with git. But I would recommend to just move to the git workflow, since it makes some things possible which weren’t before (git log is much faster than svn log, what happend when your svn-server was offline/broken, git diff can be faster too).

    So I hated to learn the git concepts, but I love to use them.

  41. This is more tongue-in-cheek than anything else, but: If you’re griping about the number of commands and the amount of knowledge required to do anything with git, why don’t you, uh, drop down to the internals for a try? Have a play creating blobs, trees, and commits :)

  42. Edward :
    @steveko: In a nutshell, if github turns around tomorrow and demands money, or it cuts off access, then everyone who currently uses github will simply switch to another repo for upstream. By git’s nature, everyone already has a copy of all the data anyway.

    The problem is that this is probably not the case. Your code is in a git repository which you clean take away; if I recall correctly, even the uncommonly used wiki features are stored in a git repository; but what about the contents of the bug tracker which you’ve been diligently using? Unless they provide a way to get that data out, you’re stuck with a very important part of your project gone. I don’t understand why they don’t make it text-based under the covers and put it in a git repository, but they don’t (or at least, if they do, they don’t give you access to it). So, there at least is some lock-in.

    (For the record, I am one who loves hg but has found git difficult to work with and has also found hg-git to work very well.)

  43. That is why I never fully committed to totally learning Git. I am dead sure it will be replaced by something simpler in the future. Git is like the J2EE of VCS sitting in its complexity, waiting for Rails to kill it.

    • Yeah, there could be some truth in this. Or maybe JSON vs XML or something. It took something like Git to make everyone see the benefits and potential of DVCS – now someone just needs to refine it.

  44. In other words: Waaahhh! I’m not smart enough for this! So I’ll call it too complicated (for me) and stupid! :P

    If you can’t handle the power of a professional tool, get a consumer grade toy like Subversion, instead of complaining that you don’t like what *you* chose.

    The complexity serves a purpose, and is actually very elegant. And we won’t dumb it down for you, since we’re actually *using* those features!

    But it’s unfortunately always the dumber ones who loudly complain. Until we end up with an iPad with Clippy running on it, that is useless for anyone with a working brain.

    • But of course few people get to choose their VCS software anyway. Refusing to use Git vastly reduces the number of open source projects you can contribute to.

    • > In other words: Waaahhh! I’m not smart enough for this! So I’ll call it too complicated (for me) and stupid!

      More like a waste of time. It’s great so long as all you need is add, commit, merge, branch, etc., and the occasional rebase, but I’m not sure I’ll ever advocate for its use at $WORKPLACE.

      Being decentralized is great (and so are easy branches, etc.), but it would be a huge waste of my time to have to provide tech support every time somebody has trouble with a merge or doesn’t know how to undo something.

      > The complexity serves a purpose, and is actually very elegant.

      No it’s not. There’s nothing elegant about git’s UI once you get into significant history manipulation.

      > But it’s unfortunately always the dumber ones who loudly complain. Until we end up with an iPad with Clippy running on it, that is useless for anyone with a working brain.

      And you’re an idiot.

  45. Well said! Git is my VCS of choice, as I’ve learned how it works and have use for its power. But the badly (or apparently not at all) designed user interface is still a problem, and not just because I have to read the man page every time I need to know which git reset flag I need. A big problem is that it’s difficult to introduce Git to a team of non-hipsters used to SVN. (I teach Git courses, so perhaps I should be happy that it’s difficult.)

  46. This is a nice write-up, and many of your points are valid. Please correct me if I’m wrong, but it sounds to me like you have started to use Git after working with SVN for a long time. Would it surprise you that I felt the same way about moving to SVN as a long-time Git user? The problem is that they both work *very* differently and you need to change the way you think about version control to switch between them.

    The thing that I like about Git is that (despite what you say in #5) there is a lot of abstraction and quite a few nice shortcuts. For example, you can skip the whole staging process (git add) by passing the -a flag to git commit. If you really want to have an SVN-like experience with Git by pretending that it isn’t distributed, you can set up an alias so that git commit also performs a git push.

    • I haven’t actually used SVN all that much, to be honest. Less than 100 commits, over the years, let’s say. But the SVN concepts were easier to grasp.

      Taking shortcuts like ‘git commit -a’ doesn’t really help with the complex information model: you still have to know exactly what’s going on, or you’ll shoot yourself in the foot. An extra option flag bolted onto one command is not an elegant abstraction (whereas a setting that completely hid the index from sight would be).

      • Well if you used Git but did not use SVN then I can see why you think SVN is better :)

        There is a sweet spot for SVN for which it works quite well: making small changes directly to trunk (which is typical for small-scale OS projects). You update, code, update again, resolve the rare conflict, and commit – simple and easy to understand. If you don’t have commit access (maybe you are not a regular contributor, just ran into some bug and want to contribute a fix) then SVN can be a lot more painful. Not only do you need to mail or upload the patch, but you have no way of “saving” it until it gets accepted. If you want to create two separate patches for the same file, or you are asked to fix something in your patch, things will get messy quickly.

        On the other end of the scale, if you are a major contributor to a project of nontrivial size, which needs versioning and backwards compatibility, or has big rewrite efforts which should not conflict with the continuous maintenance going on (in other words, you need multiple branches), then SVN starts sucking bad: its behavior at merging is erratic at best. Files disappear from the diff (because a merged add is actually not an add but a copy), commits start conflicting with themselves, code is duplicated without any edit conflict, and worse. (Not to mention that the whole thing is excruciatingly slow.) And the deceptively simple conceptual model you have drawn in your post is gone – suddenly you need to know about tree conflicts and mergeinfo and reintegration merges, with the difference that git makes an effort to open up its internal workings, so you can understand what is going on (not easily, but it is possible), while with SVN you usually don’t have a clue.

    • With g2, seems you’re replacing one complicated lexicon with another. Why coin “freeze” when “stage” (meaning “add this file to the staging area”) supports the existing term “staging area”? Why make an inscrutable prompt when there are already a great prompt built in to git-completion.sh ? And you’re not resolving any of the ambiguities between reset, undo, and checkout, or between pull, fetch, merge, and synchronize…

      I do like “g panic” though :-). Think I’ll go make an alias for that.

    • > This project is an attempt to make the git command line a friendly place: it eases the learning process by providing guidance and high level commands.

      But it’s still git underneath, so the same problems will eventually surface.

  47. As someone relatively new to git, the thing I find really messy is submodules. Concept is great but the implementation sucks. Using Git Extensions on Windows takes away some of the pain but you’d think there would be a simple way of updating the commit the submodule points to, to the latest commit on a branch, or any branch for that matter.

    It’s really hard to convince the guys at work that git is the greatest thing since sliced bread when all they see is a mess. You really hit the nail on the head: Users just want something that works, they don’t want to have to study it to figure out how to use it. They’re too busy doing their jobs to waste time on side shows. Tools and apps with intuitive interfaces and workflows have been around for a couple of decades, at least. So expecting something to be straight-forward to operate is not an unrealistic dream.

  48. Okay, I understand that you don’t like the complexity. But why do you want to make people change git for that? The complexity is harder to understand but if you have done so, it gives you much more power over your repository. Some people need complexity -> most of the things you say are actually considered advantages by them. Some people need simplicity -> Git sucks for them. But if you make it simpler, it will automatically destroy the advantages people love it for. So I think the decision for you is to choose another VCS and not to change Git.

    • I think you’re making the common mistake of thinking that complexity and power are inherently linked. The most powerful tools hide complexity, they don’t expose grubby implementation details like “refs” and “tracking branches”. There are many ways that the usability of Git could be improved without decreasing its power at all.

    • Yeah, I sometimes use EasyGit – but it definitely runs a risk of creating even more commands to remember. It should give pointers to the Git developers though. I particularly like the message that “eg status” gives during a merge: a big warning, and a link to a man page explaining all your options.

  49. I like the part where you complain about using a feature branch, despite:

    1) It being a good thing

    2) It being completly irelivant to git vs svn

    • I think the problem with feature branches is not that you can use them, but that you have to.

      Feature branches are great, when you do somewhat larger development. But they are a needless complexity when you just want to do some smaller changes.

      • I think some issues with Git can be summarised as “it forces you to structure the *changes* to your code, in addition to the code itself”. Sometimes (in established, large projects), that forced structure is a good thing. Sometimes (for beginners, and in smaller projects), it’s a hindrance.

      • steveko :
        I think some issues with Git can be summarised as “it forces you to structure the *changes* to your code, in addition to the code itself”. Sometimes (in established, large projects), that forced structure is a good thing. Sometimes (for beginners, and in smaller projects), it’s a hindrance.

        Rather it forces you to give your changes names which you will throw away.

        It does not allow you do to add names to you changes, but enforces that – even for the most trivial changes.

        In projects where many people work simultaneously from a given base (either large or small) and merge only after many smaller changes, that forcing does no harm, because they would want to separate and name their changes anyway. But there, persistent naming would actually be more helpful, so people can later retrieve the information, why a given change was added. But since the branch name is just a pointer to the head of the branch, you don’t even have that after merging. The information is lost.

        So the forcing does not help for large projects and does harm for small projects.
        (don’t confuse forcing with the option to name your branches: having that option is great! Being forced to name them leads to a hundred “tmp” and ”foo“ branches. Whenever you see a “foo” branch, you observe time lost to git)

  50. I wholeheartedly agree. Git makes simple things hard and has a completely unintuitive CLI. Frontends like EGit do not help much. And I’m not comparing Git with Subversion: Mercurial is DVCS done right, from the usability point of view. So the really interesting question is, why is Git so popular, when there is an equivalent but better alternative?

    • “I invested so much into learning git, now I want to use it.” ← do you dare to tell them that they wasted their time?

      Second point: Good strategic option (likely not planned, though): Most times the maintainer chooses the DVCS, so cater to the maintainer to get spread around. Linus scratched his itch. Other maintainers had the same itch. Now the users are itching all over, but they do not get to choose the DVCS (except with hg-git).

  51. In your list of mandatory options, you should add “git add”:

    ‘git add’ does nothing (it warns you “Maybe you wanted to say ‘git add .’?”)

    ‘git add .’ adds all local modifications and additions but misses local deletions

    ‘git add -A’ adds local additions, modifications, and deletions

    The way I like to put it is, Git was written by Martians. They’re very smart, but their brains don’t work like humans’ do.

    I say “I’m sorry” a lot when I’m teaching git. All your points are dead on right.

  52. > But you only need a few basic commands to get by.

    You only need onw git command and a 2nd version control to get by: git clone to download a source code, and a 2nd version control system, like my home grown svc (shell version control) to create a patch to send to the upstream by mail. Thus I’m avoiding the complexity of git completely and drop the burden to the maintainer who did chose git. The drawback is, that you dont find my tag in any git based project.

    And you forgot one more problem:

    11: Git is slow as hell

    Try to download Android Cyanogenmod source. You will likely need a day even with a fast internet line.

  53. I love git, but I agree that some of the commands are difficult to understand, and man pages for commands like rebase are awful. The biggest thing that bugs me is the difference between pull/push. Pull fetches all branches, but only merges or rebases the the currently checked out branch (HEAD), push pushes ALL your branches to any matching remote branches unless you specify which branch you want to push to. Git could definitely use a UI make over. I also agree that Git has a steep learning curve. The first time you make some mistake and need to go back to your reflog to fix it, that’s not as easy as it should be. And despite the fact that I’ve been using git for years, I still have to look at my notes to remember how to checkout a remote tracking branch that does not exist locally.

    I could never go back to SVN, just because it’s so damn slow, and merges/rebases are more difficult. The code base I work on takes 3+ hours to checkout with SVN, while git clone takes <30 seconds. I also like how open source projects use pull requests, which are infinitely better than the SVN equivalent: emailing patches to the the maintainer. I also have trouble without the index when going back to SVN. It doesn't seem like a super useful feature until you go back to a system without it.

  54. I love GIT and it has very many options that are simple one line commands it’s a slight learning curve compared to SVN but it’s way worth it. I also love the branching which I’m not familiar how to do in SVN and merging. GIt has a very fast workflow once you get used to it it’s definitely quicker than SVN for me anyways and I’ve worked with both of them for quite a while.

  55. 1. Using a simple tool for a complex problem isn’t always a good idea. The philosophy behind Git (and most DVCS out there) is that you need that complexity to manage the problem of version control effectively. For instance: you mention the stash, that is something svn intends to add as well.

    2. True. It did get a bit better, but it is still a mess.

    3. Man pages suck, but I reckon Git has about the best docs out there. There is a huge community, a lot of books, etc.

    4. Same as 1.

    5. Not sure what the example is about, is that a regular workflow for you? Seems like an exceptional flow.

    6. Not true. The Git model is clearly appreciated by contributors, as seen by the massive adoption. What helps maintainers is also good for contributors. Also, on my one man Git projects, all the levers really aren’t in the way. The wizards in my IDE and GitHub/Google Code set up the repo, branches, etc. I just press commit and push.

    7. Yes this is scary about Git. There is a back-up to get most changes back. Although sometimes useful, I feel this ease of destroying history is a golden rule Git broke.

    8. Same as 6.

    9. Same as 7. I do think in a DVCS world it makes some sense to clean up a bit. I like the IBM Jazz model a lot.

    10. Same as 5. and as you admit a completely unfair comparison. If you’d use a similar access model, Git would only be one additional command.

    So a 2 out of 10 in my book.

    Git is by no means a perfect tool. But it is a massive improvement over SVN, especially for distributed open source development. Focusing too much on command-line quirks and the nuts-and-bolts way of working, dismissing all the great tools and services out there, I think you miss the point here about Git’s popularity.

    • If you need a complex tool to manage the problem, then why can Mercurial do it as well while staying simple?

      Naturally you can say it can’t. In that case you should just use it for some time – and have a look at hg-git, which provides you a transparent bridge. So everything you can do it git can be done in hg, too. But most things are much easier.

  56. Steve I agree 100% with this article. Solving problems are difficult enough, however solving problems that don’t even exist are even harder and unnecessary.

    I think Einstein’s quote sums GIT’s failure quite aptly:

    “Any intelligent fool can make things bigger and more complex… It takes a touch of genius – and a lot of courage to move in the opposite direction.”

  57. Here’s the thing: you can hate Git all you want. The fact is, there is no substitute for it and the learning curve is a small price to pay for the power and flexibility you get – you wouldn’t expect a granny to get in and drive a race car, would you? Let me know when you find such a system. I’ll switch (and my guess is, so will the rest of the world).

    • There is a substitute. There are several, in fact. A DVCS doesn’t have to be the way git says it should be, because git didn’t invent DVCS, and git isn’t the fastest DVCS. Check out bzr, darcs, or my favourite, Mercurial.

      git is popular because “the guy who made Linux invented it” and because of github. It’s popular due to network effects. Not because it in itself it’s good.

      • The kind that uses the best tool for the job. I stand by my statement that git is the most powerful. You can moan about it all you want, but it works and it works really well.

    • Just learn Mercurial. It takes much less time than learning git.

      But then, it will still take some time. If you don’t want to invest that time, I can understand that stance. But it would completely invalidate any argument you can make about the power of git.

  58. You can blame hacker news for me being here (http://news.ycombinator.com/item?id=4340047) which seems awkward given this post is 6 months old now but I guess still holds relevance.

    steveko :
    I think your assumption that developers want to, or at least can be expected to, spend time learning developer tools is misguided. It was more reasonable 20 years ago. These days, we have so many tools and technologies to deal with, that they all must be made as learnable and intuitive as possible.

    +1. This is precisely the reason I went with hg. While I haven’t bitten the bullet and tried yet, there’s excellent plugin support like hg-git or hgsubversion that turns hg into a subversion client. I plan to get my feet wet with the latter and if it sticks, remove svn from my vernacular forever. When using a DVCS and getting used to even the basics, going backwards is like taking a trip back to the stone age. You mean I have to be connected to the internet to commit? The remote server has to be up? FU!

    I will second that Hg’s usefulness is in the ease of use. Hginit.com explains everything in a very simple manner too. I come from Windows, where Tortoise* is king and I find TortoiseHg to be the best package available among svn, hg, or git. Hg Workbench combines basically every UI dialog into one location which is amazingly useful. If I could choose it would always be Hg but there are things I pine for in Git, well specifically one: gitflow. There is a hgflow plugin but it’s not quite 1:1.

    Others have mentioned mq or patch queues and I think in tortoise they’re incredibly simple. I typically use it to commit anything volatile or in some instances move a block to patch and rearrange the commit order until I’m satisfied. I suppose it’s a lot like rebase but a more manual process.

    I’m not trying to be a poster boy for hg but I’ve drank the koolaid for a long time now apparently and when you find something like that, it becomes hard to want to jump to something user unfriendly like Git, despite it being billed as an “expert tool”. TortoiseGit *has* come a long way I will say and Github for Windows client helps tremendously as well but it has a long way to go still. It’s not that I need it to be awesome because I’m on Windows but you really should be able to get beginners to use a DVCS *early* and Hg will always eat Git’s lunch if it doesn’t take usability seriously.

  59. DIsclaimer: I don’t hate git — I rather like it. But there is one complaint I could add:

    No ability to edit log messages after the fact. Especially once you’ve pushed a commit, that log message is now out there; if it’s wrong, you can never correct it, you can only try to add amendments in later commits.

    In SVN you can (if the repository admin enables it) tweak log messages after the fact, and it turns out to be really handy. Once people get used to doing it, they’ll go back and, for example, edit a log message in the past to refer to revision number that happened later, essentially saying “See also r1729″. It has many other uses as well.

    I think this feature would be very hard to support with decentralized repositories, though.

      • Hey, steveko. Doesn’t that just amend tip, though? If the commit in question is past tip, and you can’t afford to rewrite history (which generally one can’t), then that log message is written in neutronium.

        And there’s a larger issue: if you’ve pushed already, and your commit has been replicated in other peoples’ repositories now, then you *really* can’t amend it. It’s not even clear in theory how one would design a protocol to reliably spread the news of the amended commit.

        IOW, in this case, Subversion’s design limitation — centralization, whereby the One True Repository is a technically rather than a socially enforced fact — becomes a feature. Because of it, editing log messages post facto is a conceptually consistent thing to do.

        This isn’t meant as general defense of centralization. I like git, and like decentralized VC independently of whether it’s done through git / hg / bzr / veracity / etc. But there are times when having a single, everyone-agrees-because-they-have-no-choice answer to “Where is the canonical data stored?” simplifies things greatly, and I’ve found this to be one of them.

  60. Can I use this as my homepage? lol
    Git is overrated bs.
    Don’t bother replying, I won’t bother elaborating. I hate Git.

  61. OK git has a steep learning curve, so we got someone to teach us, we mad some videos and made themn freely available here http://www.ava.co.uk/git .We also adopted / paid for smart git. The combination does a very good job, obviates the need for command line and has returned far more than the learning cost and smart git licences: it works for us

  62. 7. Unsafe version control
    9. Git history is a bunch of lies

    This “problem” is fixed by GPG signing your Git commits. There are built-in tools in git for that. This not only prevents from accidental or intentional history rewriting but also keeps your sources safe if your git server gets hacked.

    • GPG does not solve 9. 9 arises because people code, then rewrite the history, then push. Or worse: pull, rewrite, push – that actually garbles up the history of the contributor once he pulls, so he will have to rewrite his history, too – and all who pulled from him have to do the same. That’s the opposite of scaleability: It just means pushing the cost of scaling onto the contributors.

      • Arne Babenhauserheide :
        GPG does not solve 9. 9 arises because people code, then rewrite the history, then push. Or worse: pull, rewrite, push – that actually garbles up the history of the contributor once he pulls, so he will have to rewrite his history, too – and all who pulled from him have to do the same. That’s the opposite of scaleability: It just means pushing the cost of scaling onto the contributors.

        Huh?

        If you do not use the –rebase option when you pull the contributions, how does the rewrite get into your repository? Or, if you are particularly strict (and you probably should be, if you are pining for svn), you could use –ff-only.

      • rdm :

        If you do not use the –rebase option when you pull the contributions, how does the rewrite get into your repository? Or, if you are particularly strict (and you probably should be, if you are pining for svn), you could use –ff-only.

        If someone else does a rebase of stuff you already pulled, your history gets garbled, because you now have duplicate history.

        If you send a pull request and the other one does a rebase, you have to prune out your copy – and rebase everything you did on top of the changes to the other changes.

        And everyone who pulled from you has to do the same.

  63. Pingback: 10 Things I hate about git | Part-time Life

  64. Honestly, I did not read very single word of your post. To be fare, the learning curve is much deeper than svn. This is not complete because the tool itself, but because it introduce lots idea of versioning control which is seem odd in other svn. The workflow of versioning in git is quite different, and this workflow looks complicated at first, but once we get used to it, we find lots rational. Here a section of script of “Scent of a worman”

    Now I have come to the crossroads in my life.
    I always knew what the right path was.
    Without exception, I knew, but I never took it.
    You know why ?
    It was too damn hard.
    Now here’s Charlie. He’s come to the crossroads.
    He has chosen a path.
    It’s the right path.
    It’s a path made of principle…
    that leads to character.
    Let him continue on his journey.
    You hold this boy’s future in your hands, Committee.
    It’s a valuable future,
    believe me.
    Don’t destroy it. Protect it.
    Embrace it.
    It’s gonna make you proud one day, I promise you.
    http://www.veryabc.cn/movie/uploads/script/ScentOfAWoman.txt

  65. First: I agree that git’s command line does not properly reflect its underlying structure. Personally, I use the guide at http://marklodato.github.com/visual-git-guide/index-en.html so that I can find the command that accomplishes what I want to accomplish.

    Second: I disagree that git does not provide meaningful abstractions. I would agree if you claimed that you do not understand the abstractions it provides, but that’s a very different kind of statement, and was not your claim. The abstractions git provides are very much like the abstractions provided by a file system — and once you understand them, they are simple to work with.

    Third: I dislike some of the defaults that git provides (for example, I always have people I am working with put in their global config: push.default=current). But my distaste for those defaults is a reflection of the admin system provided by github, and git was designed before github.

    Finally, comparing git to svn is sort of like comparing google maps with a tumblr. I can be totally in awe of the aesthetics of the tumblr and I can say all I want about how google maps does not have those design characteristics. And, in doing so, I would be pretty much missing the point of why people would like either one of them

  66. I am familiar with at least 9 source control systems, and I am paid-administrator-proficient with 4 of those, including ClearCase and Perforce.

    Git is such a mighty pain in the rear that I just gave up ever working on any open source project that uses it. Its learning curve is a sucktastic cliff and you really do need to know almost everything about it before you can stop being dangerous.

    And then you’re still dangerous. No thanks. The tool should not be more complicated and inconsistent than the programming language source it protects. It’s anti-developer.

    It’s as if I wrote a book entirely in made-up language because it was easier for me as an author, but then every reader would have to learn the stupid language I invented. It’s a horrible approach.

    • Yes — that is how git push works.

      But two branches in the same repository and you do not want to consider the target branch as the current branch? Why would you even want to do that?

    • It might be, but I don’t see why you’d want to, because to resolve conflicts, data must be dumped to the working directory anyway. And there’s no porcelain commands I see anywhere for this, because it would be notably complicated to perform. If you know git internals pretty well, you could probably find a way to forge a merge commit in memory without checking them out. Just… why?

  67. It’s enough to look what Linux is to understand why Git is such a cr*p. Linus never ever studied properly even having such learning grands like Tannebaum. I hate Git too even from a first look (and I didn’t know who wrote it). Now I’m hundred times sure in my choice – Mercurial.

    • Linus made things work where the grand Tannebaum failed.

      But I fully agree that Mercurial achieves the same as git without introducing the same kind of complex interface. That does not make git a bad tool. It just makes it inferior – but heavily hyped.

  68. Even the first hate-thing is enough to not to read further for each one who really tried git. Other 9 are also a crap of subjective shit, decorated with lovely graphics :)

  69. Try a GUI program called SmartGit. No more command line syntax to remember and it shows you a nice log on all the branches and past commits.

  70. Just read your post for the first time, complete with the August update. This sentence really made me laugh and must be what the developers of Git say to themselves from time to time, “If I’d known it would be so popular, I would have tried harder.” :)

  71. CC :
    “Subversion doesn’t even count, because anybody can write a simple VCS if they don’t have to make it distributed.” You truly have no idea what you’re talking about. it was a wholly different world when Karl Fogel and company wrote SVN. You seem to have no concept of how difficult it is was to create SVN in a world where there were few good tools, very little OSS, and a much more limited concept of VCS. That SVN succeeded so well at the task you dismiss out of hand is corroborated by its wide and enduring popularity.

    The original quote (“anybody can write a simple VCS if they don’t have to make it distributed”) is indeed kind of silly — SVN is certainly not simple, and it remains popular for good, understandable reasons IMHO.

    But the reason SVN isn’t Git isn’t because there were fewer good tools then, or less open source software, or anything like that (I mean, this wasn’t the Late Cretaceous — we’re only talking about 12 years ago or so). It’s because the project was explicitly started as a replacement for an older centralized version control system, CVS. The company that founded the SVN project, CollabNet Inc, envisioned something that fixed a lot of CVS’s problems but worked using basically the same model: check out from an upstream repository, make some modifications, check back in to the repository.

    Had we on the early SVN core team proposed to CollabNet that we do something like Git instead, CollabNet would rightly have rejected the idea, because it would neither have served their customers’ needs nor easily displaced CVS in the open source world. (I hasten to add that we didn’t have a decentralized vision anyway — i.e., it’s not like we considered a Git-like system and rejected it, it’s that we weren’t thinking in that direction at all.)

    But even back then, decentralized version control was not some new field of research. Git grew out of Linus’ experience using BitKeeper, which in turn grew out of the venerable SCCS. Linus was indeed bold to write his own system from scratch, and its success speaks for itself — but part of the reason he was free to do that was that he was the only constituent he had to satisfy. He wasn’t aiming to take over a broad installed enterprise base. (Whether Git ever does take over there is still an open question, I think; it might, but in many ways it’s less well-suited for that environment than SVN is.)

    Decentralization is not a successor to centralization; rather, it’s been a parallel track all along. We weren’t aiming for decentralization with SVN, and I’ll admit that I at least didn’t fully understand it at the time. But even if we had seriously considered it, I think SVN would still be a centralized system today.

    • Git’s decentralised nature does seem to cause problems in environments where you need to end up with a single, definitive, centralised repository. The MediaWiki team has been going through a lot of pain, adopting Gerrit as a code review and Git management tool. The success of GitHub has also shown that Git alone isn’t enough – you need social tools built on top of it.

      I guess my feeling in all this is that Git (or something equally powerful) is necessary, but not sufficient, for effective code management in distributed teams. Although it claims to provide “porcelain”, it really doesn’t – and there are all kinds of features required by humans that it falls short on.

  72. Agree. Besides the basic version control functions, intuitive and secure are the essential features of a version control tool. If the tool cannot even manage the source code safely, then why use it.

  73. A third of the rant is on the money (“git co filename.ext” vs “git reset commitid” etc). The rest is “I am a leg-less, color-blind semi-person who likes to stab frogs with bamboo sticks. This new-fangled world with distributed workflows, and the new ideas that come with it are too much. I don’t need that, therefore it’s useless. And, by the way, I don’t know why and how GitHub is a part of my angst, but let’s make it part of the problem too.”

    In other words, more than half of the rant is a person used to wheelchair complaining about complexity of using wings.

    The rant is only useful to Git maintainers really, just as a reminder that their user base is growing very diverse. You, the stray visitor that comes by and thinks this rant should somehow calculate into your decision not to / to choose Git, don’t pay attention. Just choose Git.

  74. I have a feeling you approached git expecting it to be like svn and got disappointed. They are used for completely different workflows. They are suitable for completely different workflows. Try managing Linux kernel with svn…. If you have a 10 developer project maybe git is overkill, but if your project grows enough then git is the best choice around.

    P.S. Ever tried branching? ;)

  75. Just a note about Github, many people use pull requests (PR) as part of their daily workflow. A pull request should be opened early, very early, before any real changes have been made. The PR serves as a staging ground for discussions about the change, and a place for code review to occur.

    You can PR between two branches in the same repository. When I work on a project we all have push access to the same repository, but we still use PRs to coordinate changes.

  76. Comparing Subversion to git is like comparing a single-speed bicycle to a Jeep Wrangler or notepad to Microsoft Word. Yes, it’s more complicated. Yes, it’s harder to learn initially. But once you learn the basic theory you have a much more powerful tool at your disposal. This article is like hearing a whiny teenager complain about how hard his calculus class is because he thinks algebra should be enough math to get through a Computer Science degree. Every software developer that hasn’t yet learned git (or other respectable DVCS) and wants to stay stuck in svn-land needs to grow up or go home.

  77. Didn’t read all the comments, so sorry if this has already been said, but the problem is you are assuming that GIT was designed to be used by the ‘regular user’. Unfortunately, it was actually created because Linus needed a tool. It was created for Linus by Linus, and then he decided maybe other people would like it too and let everyone use it. That’s why it is written to be used by a computer scientist, and that’s why it is slanted more toward the maintainer than the ‘regular user’: Because Linus is a Computer Scientist and a Maintainer.

  78. 3. git is a tool for computer scientists. Anyone who doesn’t qualify has no business writing code, and no business using git. And if they do, they certainly have no right to complain about it.

    • I was thinking that, right up until I read the actual examples. From the looks of it, the Git documentation is as bad as reading source code – and if source code were good enough, there wouldn’t be any documentation.

  79. I agree with you 100% that the man pages suck and the “porcelain” commands aren’t enough for getting a reasonable project going.

    For the rest of it, it’s an extremely flexible tool that can be misused way too easily. The key, like in probably C++, is not that you should get to master “all Git”. But that someone in your project decides what subset of Git features make most sense to you. It’s just a different job for the maintainer.

  80. Your post has good points. I’m encouraged that we’re at a point where we’re complaining about the UX for a VCS instead of about features. It shows what huge steps we’ve made in version control technology.

    I started with RCS and SCSS and worked my way up to CVS, svn, p4, hg, bitkeeper and finally git. From my perspective, git is awesome and I can live with the complexity of the commands because doing a lot of the things I do now easily with git were painful and dangerous with the previous version control systems.

    Subversion, for example, didn’t have sane branch merging when I was using it all the time. CVS was incredibly limited and I was constantly repairing checkouts by editing files in the .CVS directories.

    I think it’s time to improve the UX for git, and posts like this will encourage people to make those improvements.

    I’d love to see you write mock ups or descriptions of how the commands should work for maximum (or maybe just better) UX in an ideal world.

    Ciao!

    • Hmm, very interesting idea. It will certainly be very tricky to fix, especially because many users now depend on all the commands and options they’ve memorised.

      • Hypothetically, though, you could design a new line of independent git * commands, allowing people to migrate at their leisure.

        That said, my impression is that people working to design new git user interfaces often have a rather limited view of what will want to be doing (or what they should be wanting to do) with git (for example: git flow).

        There’s a dichotomy between utility and workflow and in addition to the “many people are already doing it differently” thing, it can be surprisingly difficult to build a new system that integrates properly with the abstractions people are going to be wanting to use to reflect their own work…

    • Hear! Hear!

      It would be nice to have a tool that is really really simple for the simple things, yet also able to handle the more complex things when required, so it can be used by time-pressed non-programmers (who would really prefer not to use version control at all) and experienced developers with sophisticated needs alike.

      Sensible defaults, easy installation, good documentation etc.. all contribute to this as much as a nice interface.

      • Mercurial is still too complicated.

        On Win32, TortoiseHG is (IMHO) not as easy to use as TortoiseSVN, and even TortoiseSVN was too complicated for some of my erstwhile former colleagues.

        Unfortunately, I suspect that the tool would have to have absolutely no interface whatsoever to stop them being bamboozled. It is tempting to take an arrogant line and give up on these individuals, but I strongly disagree. There are highly intelligent domain specialists with limited time and little interest in software engineering issues, who nevertheless have a huge contribution to make to many projects.

        Bringing their contributions under version control has a huge benefit in terms of communication, automation, organization, and team synchronization.

        Bottom Line: We need to make our tools simpler. Not just a little bit simpler, but dramatically, radically, disappear-from-sight zero-interaction simple.

      • wtpayne :
        Mercurial is still too complicated.
        On Win32, TortoiseHG is (IMHO) not as easy to use as TortoiseSVN, and even TortoiseSVN was too complicated for some of my erstwhile former colleagues.

        Once upon a time, I had a colleague for whom “files and programs” were too complex. I remember spending hours working with him on this issue, before we managed to work out how to get him to “start the word processor before you start typing” though he never did understand the idea of what a program was (this was about 25 years ago).

        Anyways, my point of view on this issue is: ignorance is a solvable problem.

      • Telling people that they are ignorant is not the solution, particularly when they represent valuable specialist expertise to the organization. I would rather take a more conciliatory approach and save up my balance of good-will for situations where it really matters (Like the importance of keeping files neatly organized).

        In any case, they are not ignorant, merely pressed for time, and (entirely correctly) want to focus on providing value within their area of expertise, not on learning how to use (for them) obscure and byzantine “techy” tools that hinder, rather than help them achieve their own objectives.

        This is particularly true when the specialists in question view the software engineering function as something that is subordinate to them, and that should operate in the sole service of their objectives.

        In this situation, any attempt to push back needs to be handled with the greatest of discretion.

        It would really help me if the tools just got out of the way, and I did not have to apologize for them and the inconvenience that they cause.

      • wtpayne :
        Telling people that they are ignorant is not the solution, particularly when they represent valuable specialist expertise to the organization. I would rather take a more conciliatory approach and save up my balance of good-will for situations where it really matters (Like the importance of keeping files neatly organized).

        I do not think anyone has advocated that “telling people that they are ignorant” is a solution for anything.

        However, you replied shortly after my post, where I suggested that I do not accept “ignorance” as an issue.

        If I am using prepackaged software, and I am working with someone that does not want to deal with it, there are a variety of options open, including providing wrappers (click on this icon…) and engaging someone else to support them (if this fails, talk to Sam), and so on…

        That said, when I have been working with software developers, and we are using git, it’s always been simple enough to work through the issues.

      • @rdm – I apologize for my blatant; egregious misrepresentation of your position – I was creating a straw-man to dramatize my argument.

        :-)

        I agree with you that, amongst developers, learning new tools is rarely a significant issue – because we accept that as part of our job. (Whether we *should* or not is another discussion for another day).

        I feel quite strongly that the same tools that we use to communicate, coordinate, synchronize and integrate work within an engineering team can also be used to fulfill the same needs across the entire organizational management structure, and that lack of systematic attention to such issues is the underlying reason for a great deal of inefficiency, waste and grief in a wide range of organizations.

        I am an empiricist, and, as such, I think that empirical evidence is the most important, reliable source of truth in decision making. However, so many of our decision makers are so distant from the results of their decisions, and so removed from empirical truth, so distorted and disfigured by social and political pressures, that the quality of decisions in many organizations is simply execrable.

        Exposure to the coal-face of hands-on development gives the developer tremendous benefit – his actions must (frequently but not universally) be judged by what actually works or fails, not by his social nous, political maneuvering, faculty with weasel words, or ability to pull the wool over people’s eyes.

        I wish for that benefit, that feedback loop, to be extended more widely through the organization. For people to cease hand-waving platitudes and generalizations, to get to grips with the detail of the problems that we face, and to realize that to make real progress, you need to do real work, not busywork.

        That is my motivation.

  81. The trick with git is to realize that it’s called plumbing and porcelain because neither are something you want to live in but something you want to just “work” and live in the corner of the house you build. Occasionally some things feel weird, but if you’ve every been to Europe then the porcelain feels weird over there too, so I write it off as culture more than true usability.

    Moving the bulk of our source code from svn to git was probably the best thing we ever did in our company, but we set up a pretty significant process and automated-merge-to-master intranet page that tied in with our work tracking system. We also left a bunch of third party stuff in svn because it just made more sense to not have every version of every binary on every clone of the git repo.

    I originally got annoyed reading your rant until I realized it was pretty much a laundry list of everything we had to plumb around in getting widespread acceptance of a distributed source-control system in the company. Things like turning off non-fast-forward commits on master, and then making master read-only to anything but the automated merge process were critical to making it all livable, and now there’s measurable improvements in workflow overheads going way down. Obviously we encourage GUIs like SmartGit, TortoiseGit and Git Extensions instead of the command line for everyone but the top end of power users, which paves over most of the usability complaints.

  82. rdm :

    Hypothetically, though, you could design a new line of independent git * commands, allowing people to migrate at their leisure.

    That said, my impression is that people working to design new git user interfaces often have a rather limited view of what will want to be doing (or what they should be wanting to do) with git (for example: git flow).

    Yes, I wonder whether something git flow could be integrated into the core git suite. So then commands like “git branch” get relegated to “power user” status, and the average user only works at the higher, workflow level. Those commands would also be able to give much more verbose output, and be free from the dual requirements of human usability and scriptability.

    • I’m actually not entirely clear why people think git and svn conflict.

      You could easily, for example, use svn to track the history of a branch managed in git, and you could use git to propagate changes introduced in that branch using svn.

      The thing is: they solve different problems: svn keeps track of a history of document instances, while git deals with change management.

      I suppose, though, some people are saying that they do not need both features. People that are using svn but not git do not need to coordinate changes from a group of contributors, and people that use git but not svn do not need another copy of the document history.

      • Do remember that SVN has real branches, though they are implemented via the file system. It’s a different tradeoff than with git, but SVN gives you real diffs and you can coordinate changes from groups of contributors via SVN.

        It’s just not as convenient as with Mercurial (I won’t go as far as calling git convenient…).

  83. 11. Too many states
    This has been mentioned a few times now, detatched head, merge conflicted, in-the-middle-of-that-but-got-stuck state etc. Do we need them all?

    This brings me on to:
    12. Git gives up
    Someone on hacker news summed this up: “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 is my biggest problem with it. Git needs to be more INTERACTIVE. Like if something fucks up, talk me through the issue.
    This is carried through into GUIs for Git. Take github’s Windows application as an example (“The easiest way to use Git on Windows. Period.”), if i get into a merge conflict, it just offers me a button to abort, or launch the command line. Why not bring up a diff tool at that point? why not integrate a diff tool into the application and say “look, here’s the problem i had, tell me what you want to do, then let’s continue!”

    This brings me on to:
    13. GUIs
    Ever try and learn about revision control? Read a blog about it? Get a book? Have a buddy explain it? What’s the thing in common? They ALL use diagrams (at least the good ones do). Diagrams, AKA graphics. Why not use that for git, and combine it with the user interface, we could call it a GUI! And I know about Git GUI and Gihub’s gui, but they all suffer from my previous point – they only work for a subset of git. Why not make a tool that covers the corner cases (infact, not even the corner cases, just the edge cases, or the top-left-quadrant cases, or the non-svn-user case) so you dont end up taking a user, confusing them, then sending them to the commandline.

    For the record, I was not brought up on SVN, I actually started on Rational Team Concert, when I barely new what revision control was. and found it pretty simple to use. I suppose I am spoilt by this. I’ve tried individually and within a group to learn git. I still get stuck and confused, and my head still gets detached, and then you have to guess which reset command to use.

    • Some good points. In my experience, “non-trivial” things tend to happen with Git pretty frequently, and neither Git, Github, GitX nor GitX provide any guidance when they do. EasyGit provides some pointers sometimes, such as the “middle-of-merge” help text.

      Your point 13 is well made, too. Much of the complexity of Git revolves around trying to construct the right representation in your head, then take appropriate steps to resolve it. A decent drag-and-drop GUI would help a lot, with visual representations of “before” and “after”. Perhaps there is one already, but it needs to be free.

      • Yes! I’m not even sure drag and drop would be needed, but it would certainly be awesome if somebody implemented a full nodal tree that you could rearrange and play around with (like the snap-to connectors you get in MS Word drawings)

        I played with tortoiseHG today without really reading the manual. I can commit, merge, rebase, revert and push to SVN entirely from the gui. I got in some messed up states, broke a few things, but even so, after initial set-up I never typed hg again and solved all isues through the GUI. In fact, the only issues I really had were because i was doing operations against an SVN repository, which tortoiseHG has poor support for (self admittedly). The best part was it provided a simple graph so i could see all the changes i was making as i made them. I’m not sure why that should feel like such a massive feature :)
        Now, looking into tortoiseGit, it may be my saviour, as I *think* it’ll talk me through resolving conflicts. I’ll try to remember to report back when I get a chance to do something serious with it.

  84. GIT! FUGGIT! UI is waaayyy too hard. Even using eGit in Eclipse is still complicated. And no, I am not dumb or lazy, I just need to make code and commit it. Back to SVN for me.

    • try mercurial with tortoiseHG first. I could intuitively make it work, even doing reasonably complicated things like rebasing, i managed to get it to work with a bit of playing around.

  85. I will agree with you on exactly 2 points:
    The git command line tools are inconsistent and suck.
    The git man pages need to be improved.
    Your other points either stem from this, or are simply wrong.
    Complex information model? In all the time I’ve used git I’ve never needed to know about trees and blobs and whatever.
    The only reason I know about them is because the man pages mention them for some reason. (see complaint number 2).
    The way branches and tags etc work is exactly how I imagined they would before I was introduced to subversion.
    So your problems there are mostly to do with you familiarity with subversion I guess.

    git commit -a; git push;
    is the same as svn push as far as I can tell. So that’s one extra command, and only because you are pushing to a server.
    If you only use local repository, which I do until I finish and push a bunch of things at once, it’s the same number of commands.

    git stash is useless?
    Until now I have never wanted to stash untracked files, so whether it’s useful or not depends on your workflow.

    I think the fact that you use github adds complexity that you are attributing to git.
    We have our own server where people can pull and push, so that eliminates several of your complaints already.

    tl;dr; I dissagree with you :P
    I couldn’t resist posting.

    • “the built-in commands suck and the built-in documentation sucks”…

      Naturally every other complaint when using the tool stems from these, because they describe the whole default user interface.

      And the only way to avoid them is not using the tool directly, but using some program which uses the tool. You could say that you can improve every interface by not using it…

  86. Why can’t I use git and svn and mercurial and vss at the same time? why let technology define us, don’t we all want more innovations. I hope git is not the final stop in the source control evolution.

      • Arne Babenhauserheide :
        you can, but they have different paradigms so everytime you switch you have to change your way of doing things (except if you use emacs). It’s like programming in 5 languages at the same time. You can do it, but it has much higher friction than being able to use one language for one project.
        Joel described that quite nicely in “human task switches considered harmful”: http://www.joelonsoftware.com/articles/fog0000000022.html

        I would draw a distinction between scope of vocabulary and interruptions.

        Personally, I use a variety of languages, and that seems to me to be a very different experience from someone coming up to me and asking me to drop what I am doing and work on something else.

      • I agree with the programming language part, but since i use git/svn/mercurial/vss with their awesome augmented GUIs I find it extremely easy to use. And since i use them all anyways its automatic for me when i use them. but i must clarify i m slowing using git as my primary repo. svn is still useful for me for non programming related source control since i can check out individual files. Thts y i like using all of them.

      • If you’re using the VCS via a GUI, that’s similar to using them via emacs. I have no problem interacting with git via emacs, because it is exactly the same as interacting with Mercurial or SVN.

        But an augmented GUI which works differently for the different systems is still a context switch which creates friction.

  87. Arne Babenhauserheide :
    rdm :

    If you do not use the –rebase option when you pull the contributions, how does the rewrite get into your repository? Or, if you are particularly strict (and you probably should be, if you are pining for svn), you could use –ff-only.

    If someone else does a rebase of stuff you already pulled, your history gets garbled, because you now have duplicate history.
    If you send a pull request and the other one does a rebase, you have to prune out your copy – and rebase everything you did on top of the changes to the other changes.
    And everyone who pulled from you has to do the same.

    So don’t pull it. Seriously, the whole reason pulls are not automated is so that you can exercise judgement about which pulls to make, and when. Problems should be fixed by the person introducing them. People that won’t fix their problems are not helping.

    • rdm :
      So don’t pull it.

      So you don’t pull the canonical repo. That creates a shism in the project, and from there on it goes downward.

      The problem is brought upon you by someone else, but git makes it easy for mainainers to screw with contributors and hard for contributors to recover. Git makes it easy to rewrite published history (you can even do so remotely!), but it provides no way to detect how history was rewritten and adapt the local DAG automatically.

      • Arne Babenhauserheide :

        rdm :
        So don’t pull it.

        So you don’t pull the canonical repo. That creates a shism in the project, and from there on it goes downward.
        The problem is brought upon you by someone else, but git makes it easy for mainainers to screw with contributors and hard for contributors to recover. Git makes it easy to rewrite published history (you can even do so remotely!), but it provides no way to detect how history was rewritten and adapt the local DAG automatically.

        Ah, I think I understand.

        You are correct: git is not designed to have a shared repository be the canonical repository.

        If I had your problem, I would create another repository which I would designate as “canonical”, which most people could only pull from.

        When you are using git, you need to be a code review process before you accept changes. If you define your policies properly, you might even be able to automate this process (allowing anything that can be fast-forwarded, for example).

      • rdm :
        You are correct: git is not designed to have a shared repository be the canonical repository.

        That is still too short: Code review processes are exactly what creates the problem: Some code is not accepted, but someone already pulled it from another repo, then it is rebased, improved and accepted. Suddenly you have two versions of mostly the same changes floating around, which everyone has to join by hand (and change all the code they based upon that).

        And git offers nothing to recover from that condition.

        A tool which makes it that easy to break lots of code of other people should have better ways to recover. But all you have is rebasing – which multiplies the effort when people share code very vividly.

        Git gives the false impression that you can just fix a bad push after the fact without effort, because the real effort does not hit the one who “fixed” it, but those who already pulled it.

        And yes: I experienced that first hand a few times:

        - “hey folks, I just cleaned up the messy history I pushed”
        - “you did WHAT?”

      • Arne Babenhauserheide :
        That is still too short: Code review processes are exactly what creates the problem: Some code is not accepted, but someone already pulled it from another repo, then it is rebased, improved and accepted. Suddenly you have two versions of mostly the same changes floating around, which everyone has to join by hand (and change all the code they based upon that).
        And git offers nothing to recover from that condition.
        A tool which makes it that easy to break lots of code of other people should have better ways to recover. But all you have is rebasing – which multiplies the effort when people share code very vividly.
        Git gives the false impression that you can just fix a bad push after the fact without effort, because the real effort does not hit the one who “fixed” it, but those who already pulled it.
        And yes: I experienced that first hand a few times:
        - “hey folks, I just cleaned up the messy history I pushed”
        - “you did WHAT?”

        Ok, yes: git also does not solve the “no one is in charge” problem — it was originally designed for a notable case where this had been solved for decades.

  88. Arne Babenhauserheide :
    Rather it forces you to give your changes names which you will throw away.
    It does not allow you do to add names to you changes, but enforces that – even for the most trivial changes.
    In projects where many people work simultaneously from a given base (either large or small) and merge only after many smaller changes, that forcing does no harm, because they would want to separate and name their changes anyway. But there, persistent naming would actually be more helpful, so people can later retrieve the information, why a given change was added. But since the branch name is just a pointer to the head of the branch, you don’t even have that after merging. The information is lost.
    So the forcing does not help for large projects and does harm for small projects.
    (don’t confuse forcing with the option to name your branches: having that option is great! Being forced to name them leads to a hundred “tmp” and ”foo“ branches. Whenever you see a “foo” branch, you observe time lost to git)

    You are not forced to use names which you will throw away. For example, you could use your own name. And you can keep using that same branch name for all of your changes, if that seems to be a good thing for you.

    If you do not know how to make this work, here’s two different approaches:

    1. on your branch: git merge master (to bring yourself up to date on changes in master, before doing further changes)

    2. on master: git branch -D yourname; git checkout -b yourname (this will destroy your branch and recreate it as a fresh copy from master — clearly you need to exercise good judgement about going this route).

    Or you could use initials and the current date. Or you can create a file documenting the changes and you can use the same name for your branch that you used for the file. (And note that you can start with a temporary name — your initials and a date, maybe — and then bring those changes into another branch that’s a permanent name.)

    Or, you know, you could just stay on master and try to do all of your work there. That might not be the best idea, but it can be done.

    Anyways, nothing is forcing you to follow any specific naming policy.

    • arnebab is just foo by another name. It has no information correllation to the repo I work in, so it is just useless effort forced on my by the lack of anonymous branching.

      Staying on master is hard for the same reason: lack of anonymous branching. Though that would be possible to fix by automatically creating a branch with a random name whenever someone commits on master.

      PS: If I need to exercise good judgement for doing simple stuff, something is wrong.

  89. Arne Babenhauserheide :

    rdm :
    Why should you need to change the commands?

    Because if you are not already used to git, the current commands are pretty unintuitive and hard to learn.

    So, if you are seriously talking about modifying git, why not introduce new commands that work the way you want them to work?

    • There are several reasons:

      * They won’t be default, so I would have to bring my adaptions everywhere I go to be able to do basic stuff.
      * If they’d be integrated into git, I would not be able to use the words commit, push, pull, merge, …
      * Why reinvent the wheel (and add my own mistakes)? Mercurial already does all that. And since the Mercurial devs discuss the interface in depth before adding anything, the number of unintuitive options is extremely low.

      • Arne Babenhauserheide :
        There are several reasons:
        * They won’t be default, so I would have to bring my adaptions everywhere I go to be able to do basic stuff.
        * If they’d be integrated into git, I would not be able to use the words commit, push, pull, merge, …
        * Why reinvent the wheel (and add my own mistakes)? Mercurial already does all that. And since the Mercurial devs discuss the interface in depth before adding anything, the number of unintuitive options is extremely low.

        “Won’t be default” is going to be the case for anything new that you write. You’d have this problem even if you could change the commands without breaking any shell scripts.

        So you are not actually trying to solve the problem of how to improve the UI. You are just finding reasons to object to it.

        Meanwhile: it’s fine to admire Mercurial. But you’re missing the boat if you characterize that admiration as contrived criticisms of git. Just say what you like about hg and have fun with it…

      • rdm :
        Meanwhile: it’s fine to admire Mercurial. But you’re missing the boat if you characterize that admiration as contrived criticisms of git.

        I think you’re missing my point. In my opinion git is pretty much unfixable for several reasons:

        * The default commands are unintuitive,
        * The commands are really hard to change constructively because they are intended to be used in scripts,
        * Regardless of that, the commands change in small ways, which don’t hurt small scripts but make full-featured commandline ui replacements hard to maintain and
        * The community around git has quite a nonsignificant proportion of quite vocal people who say and mean stuff like this: http://steveko.wordpress.com/2012/02/24/10-things-i-hate-about-git/#comment-357

        I am forced to use git in some projects (or rather: was forced till I switched to using hg-git), and I got bitten by it quite badly a few times. Due to that I think that promoting git over equally powerful but easier to use solutions is a problem for making free DVCS systems become the de-facto standard – with the goal of replacing all unfree versioning tools (from VSS over Clearcase to TimeMachine).

        For everyone who writes stuff like “finally someone said it” in here, there are likely hundreds of people who silently harbor a hate for git – and project that hate over to all other free software tools (because its shortcomings are so typical of early free software utilities). And those are the people who could really help free software.

        …ok, now I framed git as harming free software. Please read this with a grain of salt: Git is a great tool. I just think that it is not the best, despite its popularity, and that other tools would draw more people towards free software and DVCS – and even more importantly: alienate less people.

      • Drak :

        rdm :
        Meanwhile: it’s fine to admire Mercurial. But you’re missing the boat if you characterize that admiration as contrived criticisms of git.

        I think you’re missing my point. In my opinion git is pretty much unfixable for several reasons:
        * The default commands are unintuitive,
        * The commands are really hard to change constructively because they are intended to be used in scripts,
        * Regardless of that, the commands change in small ways, which don’t hurt small scripts but make full-featured commandline ui replacements hard to maintain and
        * The community around git has quite a nonsignificant proportion of quite vocal people who say and mean stuff like this: http://steveko.wordpress.com/2012/02/24/10-things-i-hate-about-git/#comment-357
        I am forced to use git in some projects (or rather: was forced till I switched to using hg-git), and I got bitten by it quite badly a few times. Due to that I think that promoting git over equally powerful but easier to use solutions is a problem for making free DVCS systems become the de-facto standard – with the goal of replacing all unfree versioning tools (from VSS over Clearcase to TimeMachine).
        For everyone who writes stuff like “finally someone said it” in here, there are likely hundreds of people who silently harbor a hate for git – and project that hate over to all other free software tools (because its shortcomings are so typical of early free software utilities). And those are the people who could really help free software.
        …ok, now I framed git as harming free software. Please read this with a grain of salt: Git is a great tool. I just think that it is not the best, despite its popularity, and that other tools would draw more people towards free software and DVCS – and even more importantly: alienate less people.

        Drak :

        rdm :
        Meanwhile: it’s fine to admire Mercurial. But you’re missing the boat if you characterize that admiration as contrived criticisms of git.

        I think you’re missing my point. In my opinion git is pretty much unfixable for several reasons:
        * The default commands are unintuitive,
        * The commands are really hard to change constructively because they are intended to be used in scripts,
        * Regardless of that, the commands change in small ways, which don’t hurt small scripts but make full-featured commandline ui replacements hard to maintain and
        * The community around git has quite a nonsignificant proportion of quite vocal people who say and mean stuff like this: http://steveko.wordpress.com/2012/02/24/10-things-i-hate-about-git/#comment-357
        I am forced to use git in some projects (or rather: was forced till I switched to using hg-git), and I got bitten by it quite badly a few times. Due to that I think that promoting git over equally powerful but easier to use solutions is a problem for making free DVCS systems become the de-facto standard – with the goal of replacing all unfree versioning tools (from VSS over Clearcase to TimeMachine).
        For everyone who writes stuff like “finally someone said it” in here, there are likely hundreds of people who silently harbor a hate for git – and project that hate over to all other free software tools (because its shortcomings are so typical of early free software utilities). And those are the people who could really help free software.
        …ok, now I framed git as harming free software. Please read this with a grain of salt: Git is a great tool. I just think that it is not the best, despite its popularity, and that other tools would draw more people towards free software and DVCS – and even more importantly: alienate less people.

        Being a newcomer to git, and working with it, and helping others with less experience than I use it, I do not think that “the commands are unintuitive” is a real issue. In my mind the biggest problem is that I need to tell everyone I work with to use:


        git config --global push.default current

        This command means that


        git push (without any file name)

        only pushes the current branch. That’s not the default behavior, and that is tremendously confusing.

        Once that’s out of the way, the recipes for git init and git clone combined with these commands, are pretty much all that I ever use:

        push and pull:

        git push -u
        git pull

        branch switching (and creating a new local copy of a known remote branch):

        git checkout BRANCHNAME
        git checkout -b REMOTEBRANCHNAME remotes/origin/REMOTEBRANCHNAME

        branch creation and deletion:

        git checkout -b NEWBRANCHNAME
        git branch -D DEADBRANCHNAME (or maybe use a small -d if I'm paranoid that I had work on that branch)

        janitorial cleanup:

        git gc
        git fetch --prune origin
        git reset --hard (to throw away changes)
        git reset --soft (to undo a commit that was on the wrong branch)

        and queries

        git status
        git diff (sometimes with arguments)
        git branch

        and, of course

        git add (with file names)
        git commit -m 'message'
        git merge (branchname)

        Now, you can say that this is unintuitive, and I’ll grant that I’ve not spelled out ever detail of why I’d use these commands. But as near as I can tell the big “intuitive” issue is that we have multiple repositories with git — when I commit, I am committing to my local repository, not to some other repository. I own my local repository, and it can only include changes that I bring into it. If I’m being paranoid I might set up another local repository to pull into — this way I can pull changes and discard the entire repository if I don’t like them.

        And no one that I work with uses rebase. Ever.

        And if someone creates a problem for someone else, that person is responsible for fixing it. It sounds like some people posting in this forum don’t work with people that are responsible for fixing the problems they create. But I feel that that’s a social problem and not a git problem.

        That last concept is worth repeating: If you are working with people that will not take responsibility for fixing the problems that they create, your life is going to be unpleasant. You are going to have a lot of frustrating experiences, cleaning up other people’s messes.

        And if you feel that you need better tools, to cope with other people’s messes, so be it. Personally, I think that that problem should not be considered a technical problem, but a social problem.

        I do wish that git could be configured to never allow a local name for a branch to differ from the remote name for a branch. But by restricting myself to the above commands (and note that I never name a branch during push nor pull), I get close enough to that ideal for me to get my job done.

        As for the comment about “computer scientists” — my guess is the person making that comment does not understand the scientific process. (From my point of view, the closest thing to a “computer scientist” is someone that actively practices test first design, and that doesn’t even make sense as a constraint on git use.) I think we should ignore ignorant comments like that.

        As for people that hate git and/or feel the need to blow off steam… *shrug* yes… haters are going to hate, or something like that. But if they want to have a coherent discussion about the problems that they are encountering, and I have the time and interest, I might try seeing if I can talk with them on some sort of reasonable basis.

        This comment was rather long and I wish I could preview it before it goes live — here’s hoping that it doesn’t look too dumb…

      • rdm :
        Being a newcomer to git, and working with it, and helping others with less experience than I use it, I do not think that “the commands are unintuitive” is a real issue. In my mind the biggest problem is that I need to tell everyone I work with to use:

        git push -u
        git pull
        git checkout BRANCHNAME
        git checkout -b REMOTEBRANCHNAME remotes/origin/REMOTEBRANCHNAME
        git checkout -b NEWBRANCHNAME
        git branch -D DEADBRANCHNAME (or maybe use a small -d if I'm paranoid that I had work on that branch)
        git gc
        git fetch --prune origin
        git reset --hard (to throw away changes)
        git reset --soft (to undo a commit that was on the wrong branch)
        git status
        git diff (sometimes with arguments)
        git branch
        git add (with file names)
        git commit -m 'message'
        git merge (branchname)

        Now, you can say that this is unintuitive, and I’ll grant that I’ve not spelled out ever detail of why I’d use these commands. But as near as I can tell the big “intuitive” issue is that we have multiple repositories with git

        If you manage to get people to restrict themselves to those commands, you should have a quite solid setup which people can enter nicely.

        But I think that these are already far too many commands.

        * git branch and git checkout -b NEW should be redundant.
        * There are two calls to reset, which do very different things.
        * why do you need fetch –prune? Is there any reason to not prune?
        * why the need to give the local and the remote branchname on checkout? If it exists in origin and not locally, why should I ever not want the branch from origin?
        * why do you need git gc? (actually you don’t need it anymore, since there’s auto-gc)

        In my opinion an intuitive set of commands would rather be


        git push
        git pull
        git fetch
        git checkout BRANCHNAME
        git branch -d DEADBRANCHNAME
        git reset
        git status
        git diff (sometimes with arguments)
        git add (with file names)
        git commit -m 'message'
        git merge (branchname)

        Those are still too many (11 commands for the core functionality), but since they are for different tasks, you could say “local work: checkout, branch, reset, status, diff, add, commit, merge” and “sharing changes: push, pull, fetch”.

        Checkout/branch and reset could be made redundant, since you can just checkout an earlier commit.

        But restricting checkout to getting branches is the best reason I ever saw for forcing people to use branches. I still don’t like that forcing, but if you make it a workflow, that you never checkout commits themselves, it can help you.

        Could you do `git reset –soft` via `git checkout BRANCH~1; git branch BRANCH`?

        Pull vs. fetch still disturbs the image. You should only need pull, if you work on a remote branch, after all. So cut pull and always merge remote branches explicitely.

        Then the commands would reduce to


        git push
        git fetch
        git checkout BRANCHNAME
        git checkout BRANCHNAME~1
        git branch BRANCHNAME
        git branch -d BRANCHNAME
        git status
        git diff (sometimes with arguments)
        git add (with file names)
        git commit -m 'message'
        git merge BRANCHNAME

        That’s 9 commands now, where 2 commands have 2 different ways of calling them: checkout gets a branch or earlier commits on the branch, while the other sets or deletes the branch.

        7 commands for local work, 2 for sharing work.

        Still too much, but hard to get smaller.

        I’m pretty sure that someone will now say “git does not work like that”. But well: It should.

        This comment was rather long and I wish I could preview it before it goes live — here’s hoping that it doesn’t look too dumb…

        I think it’s quite good.
        Though it would be nice to be able to branch it instead of having to copy your commands. Being able to show a diff between your commands and those I consider mostly sane :)

      • rdm :
        Ok, yes: git also does not solve the “no one is in charge” problem — it was originally designed for a notable case where this had been solved for decades.

        The problem does not only arise when “noone is in charge”, but as soon as the system is not fully hierarchic.

        In Linux kernel development you have clear hierarchies: There is Linus and there are his lieutenants. Some lieutenants release special builds of their domain. And you have groups working on a clearly limited area of the kernel, who rebase once their changes get accepted.

        Now imagine this as a writing group (I am a hobby author, so my VCS has to work for that task, too). Someone rewrote a part of a book (=commit0) and others get his changes. They like some key phrases and use them in their parts (=commits). Now the rewritten part gets accepted, but rebased, so history appears linear.

        All those who used that commit0 have to rebase all their work to the new base of commit0.

        You might have someone in charge of publishing the final book, but if the writers coordinate independently, he can either not rebase at all, or break their work repeatedly. As such git cements a hierarchy: it makes it less likely that the non-leaders build their own versions with changes from different groups, because doing so means that rebasing on part of the leader would create a big burden for all of them.

        Interestingly Linus himself warns against rebasing – possibly for exactly that reason: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html

        Essentially he says “as long as you’re not ready, send patches around, but don’t publish git history”.

        But git itself does not help you with that: It will happily break other peoples history, without even giving a warning. It does not track for you what has been published (and thus should not be committed) and if a given rebase would be safe. You have to keep all that in your mind – where you would normally rather keep more of the structure of your code.

        So git makes it very easy for you to make mistakes, but really hard to fix them (because other people have to fix your mistakes in their repositories).

        And that irritates me. It’s like a road on which someone planted snares on purpose – and then tells you to avoid them.

      • Arne Babenhauserheide :
        The problem does not only arise when “noone is in charge”, but as soon as the system is not fully hierarchic.
        In Linux kernel development you have clear hierarchies: There is Linus and there are his lieutenants. Some lieutenants release special builds of their domain. And you have groups working on a clearly limited area of the kernel, who rebase once their changes get accepted.
        Now imagine this as a writing group (I am a hobby author, so my VCS has to work for that task, too). Someone rewrote a part of a book (=commit0) and others get his changes. They like some key phrases and use them in their parts (=commits). Now the rewritten part gets accepted, but rebased, so history appears linear.

        And that irritates me. It’s like a road on which someone planted snares on purpose – and then tells you to avoid them.

        Right… do not accept rebases. Rebases might be fine for cleaning up your work before presenting it to someone else, but it’s silly to expect someone else to want to accept your rewrite of their history.

        Accepting rebases is like copying and pasting javascript urls — yes, if you completely understand what’s going on, it can be useful. But if you do not understand what you are doing, down to the last relevant detail, you’re just creating a security hole.

        Anyways, if someone sent me a rebase and I wanted the change, I might accept the changed content without accepting the history change. And, quite likely, I’d want to ask them to do the tedious work. If it’s a gift, though, I’d probably just smash their entire set of changes down into a single delta from my current branch head.

  90. Drak :
    If you manage to get people to restrict themselves to those commands, you should have a quite solid setup which people can enter nicely.
    But I think that these are already far too many commands.
    * git branch and git checkout -b NEW should be redundant.
    * There are two calls to reset, which do very different things.
    * why do you need fetch –prune? Is there any reason to not prune?
    * why the need to give the local and the remote branchname on checkout? If it exists in origin and not locally, why should I ever not want the branch from origin?
    * why do you need git gc? (actually you don’t need it anymore, since there’s auto-gc)
    In my opinion an intuitive set of commands would rather be

    git push
    git pull
    git fetch
    git checkout BRANCHNAME
    git branch -d DEADBRANCHNAME
    git reset
    git status
    git diff (sometimes with arguments)
    git add (with file names)
    git commit -m 'message'
    git merge (branchname)

    Those are still too many (11 commands for the core functionality), but since they are for different tasks, you could say “local work: checkout, branch, reset, status, diff, add, commit, merge” and “sharing changes: push, pull, fetch”.
    Checkout/branch and reset could be made redundant, since you can just checkout an earlier commit.
    But restricting checkout to getting branches is the best reason I ever saw for forcing people to use branches. I still don’t like that forcing, but if you make it a workflow, that you never checkout commits themselves, it can help you.
    Could you do `git reset –soft` via `git checkout BRANCH~1; git branch BRANCH`?
    Pull vs. fetch still disturbs the image. You should only need pull, if you work on a remote branch, after all. So cut pull and always merge remote branches explicitely.
    Then the commands would reduce to

    git push
    git fetch
    git checkout BRANCHNAME
    git checkout BRANCHNAME~1
    git branch BRANCHNAME
    git branch -d BRANCHNAME
    git status
    git diff (sometimes with arguments)
    git add (with file names)
    git commit -m 'message'
    git merge BRANCHNAME

    That’s 9 commands now, where 2 commands have 2 different ways of calling them: checkout gets a branch or earlier commits on the branch, while the other sets or deletes the branch.
    7 commands for local work, 2 for sharing work.
    Still too much, but hard to get smaller.
    I’m pretty sure that someone will now say “git does not work like that”. But well: It should.

    This comment was rather long and I wish I could preview it before it goes live — here’s hoping that it doesn’t look too dumb…

    I think it’s quite good.
    Though it would be nice to be able to branch it instead of having to copy your commands. Being able to show a diff between your commands and those I consider mostly sane

    1) I use git branch without any arguments, to tell me the name of my current branch. I advise people not to use git branch with a branch name.

    2) People need to learn that when working with git this way there’s a command prefix which determines what action git will take. That’s only a minor wart, though, if people avoid using commands designed for a different workflow, and limit themselves to a locally meaningful subset of its capabilities.

    3) fetch –prune deletes local branches which were deleted in the remote (along with bringing the local copy up to date with the remote). When your team is productively generating several branches an hour, after a few months things can start slowing down. So someone needs to delete the branches from the remote and fetch –prune copies those deletions locally.

    4) I really wish I could tell git “I want to work in single remote mode, local name should always match remote name”, with a corresponding “create this branch based on the remote instance” command option. It does not have that right now, though, so I have to cope with this issue somehow.

    5) git gc is for windows machines which can cause the auto gc to fail. The workaround is: when you reboot your machine, run git gc in your active repository.

    6) The distinction between “checkout” and “reset” has to do with the distinction between “working copy” and “staged copy” and “history”. git add is adding to your staged copy. git commit is adding your staged content to your current branch of history. git reset –soft is removing the most recent local history entry (and ideally, I’d like it to throw an error if that entry existed in the remote). git reset –hard makes your staged and working copies match history. I can easily imagine a new command set which is more technical, requiring explicit keywords to represent each of these three data structures. Until then, I use http://marklodato.github.com/visual-git-guide/index-en.html

    Anyways: checkout without -b updates working copy. checkout with -b also creates a branch in history. checkout with -b and two arguments pulls that branch from the named remote. (or it can fail if you give it names that don’t work.) All of this is additive only. git reset is subtractive — it’s discarding information (and should only be used to erase minor errors). And I’m not sure that adding a new “subtractive data” syntactic element to save a command is a worthwhile change.

    7) Note also that I use a shell script which looks something like this:

    #!/bin/sh
    set -e
    branch=`git branch|awk ‘/\*/{print $2}’`
    if [ master == "$branch" ]; then onestep=true; else onestep=false; fi
    trap “git checkout $branch” EXIT
    git fetch –prune origin
    git pull
    $onestep || git checkout master
    git pull
    $onestep || git checkout $branch
    $onestep || git merge master
    git merge origin
    trap “:” EXIT

    (I’ve cleaned out some language and environment specific cleanup and requirements stuff). I’ve been considering adding the -ff-only option, but so far I’ve not seen any problems that that would solve for me.

    So this brings down everything from git and possibly chokes if something conflicting has happened. If the conflict is not trivial, I’ll clone another copy of the repository so I can inspect the changes, and decide what to do about them. So far, the one time that that has happened, I went to the developer who caused the problem, talked to him about it, and he cleaned up the problem.

    8) If git could have a “single remote mode” I agree that it should also be able to do –prune locally. But I forgot to mention git branch -a in my list of commands we use and perhaps in single remote mode it should do an implicit git fetch, if it can.

    Perhaps it’s worth noting here that some people use git differently. “single remote mode” implies a team working against the same repository, which is inspired by github. In “multi-remote mode” which I do not use, people apparently use it as more of a test bed, lab and community publish mechanism. Anyways, not everyone uses github, and things that seem necessary when using github can be silly in other contexts.

    So, anyways, my thing has been to discover enough about how git works to use it, as is, sensibly. And I have been trying to wrap my mind around a minimal set of changes, that fit within the “git design” to ease my major pain points. So far those issues all have seemed to resolve around the idea that local branch names can be different from remote branch names. Since I do not need that feature, I have been fantasizing about “single remote mode” and how git could behave if it had that.

    • For fetch without –prune, I think it would be nice to have it prune those branches automatically which are neither checked out nor changed locally nor ancestors of local branches.

      That way you would likely never need the –prune, because all useless remote branches would disappear automatically and the others would stick.

    • note that the branch behavior in your single remote mode is the normal behavior for named branches and bookmarks in Mercurial. Additionally it has diverging-change detection, though: named branches can have multiple heads and diverging bookmarks automatically add a postfix to the remote bookmark.

      Consider that you have a refactor branch and your colleague „mark“ has a refactor branch. When you pull the changes from him with Mercurial, you now get either the refactor branch with 2 heads (for named branches) or the bookmarks refactor and refactor@mark.

      If you use it with a shared repository, the bookmarks would instead be named refactor and refactor@default, since the default remote repository is called default in mercurial.

      And this works with multiple remotes, thanks to the divergence detection.

  91. Arne Babenhauserheide :
    For fetch without –prune, I think it would be nice to have it prune those branches automatically which are neither checked out nor changed locally nor ancestors of local branches.
    That way you would likely never need the –prune, because all useless remote branches would disappear automatically and the others would stick.

    That could be annoying. You checkout a local copy of a remote branch, then study it some, and it’s actively being worked on so you want to see if there’s any changes so you do a git pull and it vanishes (because pull uses fetch). Maybe you clean this up by never pruning the current branch, but I feel like there’s other subtle consequences lurking in there (especially since once a branch is merged it’s an ancestor of the resulting branch).

    But I think I see what you are getting at.

    I think if I were going to try to implement something to satisfy this way of thinking, I’d give git a “cached mode” where the local repository is assumed to be a cached copy of the remote repository whenever possible. In other words, it would assume that upstream was available and any remote branch would be assumed to exist locally — the local repository would be a cache of the remote.

    And, to make this work cleanly, remote would have to be in an “append only” mode — it would be configured to only allow additions with perhaps a “slow deletion” mode where deleted content first is hidden for a long period of time and only is actually removed from the repository after a painfully long wait (weeks, months).

  92. Pingback: git hates

  93. 1. Index may be ignored (use commit -a/-A), tags may be ignored (they are strap-on data).
    4. Tags and reflog may be ignored.
    6. Guess what, Git _was made_ (initially) by and for Linus himself. I wage to say users who don’t want to deal with it should be using tarballs. (Web-)Interfaces like cgit can produce one for an arbitrary hash if you do at one time need one just to eschew the revision
    control system.
    7. People mentioned it: git fsck
    9. Yes, history is the important product, because it can reduce the amount of WTFs. http://commadot.com/wp-content/uploads/2009/02/wtf.png

    • tbxi :
      6. Guess what, Git _was made_ (initially) by and for Linus himself. I wage to say users who don’t want to deal with it should be using tarballs. (Web-)Interfaces like cgit can produce one for an arbitrary hash if you do at one time need one just to eschew the revision
      control system.

      Or a system which works better for them. If enough people would realize that the fraction of developers who maintain a project with over 100 contributors is far below 1%, then it’s likely that more would realize that git isn’t made for the regular developer – and that hey themselves are most likely regular developers.

      9. Yes, history is the important product, because it can reduce the amount of WTFs. http://commadot.com/wp-content/uploads/2009/02/wtf.png

      Good code reduces the amount of WTFs.

      History can help, but good code goes first. And if you worry too much about the history, it can have a bad impact on your code.

  94. You are dead *right* about the “crappy documentation”. But now that I have figured it out, I think Git is awesome and I *hate* having to use Subversion.

    How best to learn Git? Make heavy use of the graphical tools such as “gitk” and “git-gui”. Stackoverflow.com seems to have the answer to any specific “howto” question.

  95. Thanks , I’ve just been searching for info approximately this subject for a long time and yours is the greatest I’ve discovered till now.
    But, what about the conclusion? Are you certain about the supply?

  96. “git checkout .” is what I use when I want to zap all local changes. I *don’t* want to use git reset –hard, because that also resets the branch HEAD, which I almost never want to do. (Usually what happens is that I litter my code with printf to debug something that started breaking a few commits ago, that I didn’t realize at the time.)

    Overall, I understand your frustrations with git. I probably once shared them, but as I get more and more used to git, I find myself bumping into the sharp edges less often. The experience reminds me of how, at first, I *hated* vi[m]: what blatant disregard for an intuitive interface! What capricious use of random letters for commands! But due to my constrained home PC at the time, I was forced to learn it (emacs was simply too big – to install, let alone to run), and over the years we’ve become best buddies.

    • The difference today is that you don’t actually have to go through that hassle, since I’m pretty sure that Mercurial runs on yout platform of choice. And that you have to know to choose checkout . instead of reset –hard to undo uncommitted changes is aproblem in itself… both do it, but one has a side effect while the other does not always work.

      It’s clear that you can get git to work for you, but you very likely(1) don’t get something extra for the additional work you put in.

      (1): You only get something extra, if you happen to be maintaines of a program with more than 100 developers – and then at the expense of the others. That’s my current understanding after using both – though I use Mercurial much more, because I at one point decided to not risk hitting any more pointy edges of git – using the mostly safe subset when I have to. That means, that my perception today is skewed, but for good reasons…

  97. Your top ten is very fair IMHO. I’m looking at moving my development to git, all hosted internally (not using GitHub). I’ve used commercial CM for over 18 years and Git amazes and worries me deeply.

    I love Gits ability to work out what’s changed in your working tree and thus what to commit. When you’re working on multi million LOC tree’s, I like that this is extremely fast.

    Switching branches is also very neat.

    Yep, that’s about it.

    I guess your point #7 is my biggest concern. For a company to keep a central repo of their expensive IP, requires someone to babysit it so no idiot can rebase the history into oblivion. This is a crazy waste of time and money. Hoping that someone has an untarnished clone of it on a PC somewhere that you can recover is not a mitigating strategy!

    Second is that CM should be as close to invisible as possible for the humble developer. A company pays them good money to develop IP. Anything that distracts them from that is a waste of development $$. With Git, your devs will be using useful brain energy on high level of tricky mental gymnastics trying to work out what command to use, which branch to merge with and undoing things that went “wrong”. While they are doing that, your other n-1 developers will be sat there waiting patiently..

    My ideal SCM system would have a lot of the great ideas of GIT, but without the complexity. You always need someone who knows the internals of a SCM system, who can set up the branches and the integration strategy.. but the developers should have a much easier set of commands to use.

    • You could have a look at Mercurial. An example Workflow I wrote just requires the developers to commit and merge – and I can explain it in 3 steps:

      1. you do all the work on default – except for hotfixes.

      2. on stable you only do hotfixes, merges for release and tagging for release. Only maintainers touch stable.

      3. you can use arbitrary feature-branches, as long as you don’t call them default or stable. They always start at default (since you do all the work on default).

      http://draketo.de/light/english/mercurial/complete-branching-strategy (with task diagram :) )

      Your regular developers only need to know three things:

      (a) commit changes: (edit); hg ci -m “message”

      (b) continue development after a release: hg update; (edit); hg ci -m “message”

      (c) Share changes: hg pull; (if new changes: hg merge; (if conflict: hg resolve -l (fix conflicts); hg resolve -m;) hg commit -m “merge work from others”;) hg push

      More advanced developers can use feature branches and a host of other features, but no one has to.

  98. Yep you have to take a solid week out of your life and work sched to learn the monster. Like others have said, guis are the only way to go far as i’m concerned – command line just seems crazy to me.. Get the concepts then use smartgit is my plan.
    Thanks for the post.

  99. The way I like to put it is, Git was written by Martians. They’re very smart, but their brains don’t work like humans’ do.

    While they are smart, they are not brilliant. If they were, they wouldn’t have created such a mess in the first place.

  100. From my time in the field it seems like a lot of people have forewent actually looking at the problem of VCS. Most chose a centralized one and left the developers to fight with it. In my opinion, things like Eclipse cover up the giant gaping hole in centralized versioning systems. If everyone had to use SVN and CVS command line, they would run screaming for the hills. Most people cannot conduct a merge even in SVN WITH a GUI. There’s nothing that can be done to help people that don’t understand VCS. If you don’t know how to use a versioning system, any versioning system is going to be difficult to imagine.

    Then there’s Git. Git to me is a VCS for people who have seen the problems in other VCS products. I think Linus saw the flaws in existing tools and truly tried to create one that would help everyone. It IS complex, but that complexity comes with great flexibility. I am able to use Git to produce just about any imaginable workflow. I’m able to use it behind SVN in my day-to-day work to allow auto-merging where I’d usually have to manually alter files in Eclipse.

    Local branching support and stash are the bar for how much git will be of use to you. If all you want is a centralized backup of your work and you’re willing to sacrifice experimental branching and willing to have your project function linearly, then SVN or CVS are for you. There are people who would rather work surrounded by a local VCS bubble in which they can make their changes without being affected by the unwashed masses. I’m one of those people. I find commits important. I find what I commit on what branch to be important. I want to keep around experimental changes locally in case I need to use them again.

    Git is a replacement for not only a centralized version control system, but also a replacement for Eclipse local history. It functions in both ways and allows you to work independently of what you commit, allowing you to push what you want when you want where you want. I have not seen another VCS even come close when you look at the ideas it abstracts.

    The learning curve of the command line is a little steep, I’ll give you that. But is VI not difficult to learn at first? Was bash a walk in the park? Is CVS or SVN easily digestable from command lines alone? Most people I know wind up needing Tortoise or an IDE to make the type of merges I can make in seconds in git.

    Just because something is complex to learn and powerful does not mean it’s a reason for hatred. I find git better than the alternatives because after I learned the basics of what I was actually trying to do, I can stack overflow a way to get there. When I can’t do something in SVN it’s usually just because it’s simply not possible, not because I don’t (yet) know the correct command syntax.

    I understand git command line is probably not for everyone, but I would argue that it SHOULD be for REAL programmers. People who like to get shit done without the tooling getting in their way. SVN and CVS have always felt they could just pulverize my local files even when I have important changes in them. I cannot tell you how many times you wind up resorting to making a copy of your whole workspace just so you can get SVN or CVS out of some retard state in Eclipse and then had to pull diffs back in. I have never done so with Git…because I never had the need to. Git is trying hard to make it so you don’t lose your work. Let it help you.

    • I readily prefer git to svn, and I would agree with you, if Mercurial did not exist.

      > It [git] IS complex, but that complexity comes with great flexibility.

      If we had no Mercurial, I’d think that this might be true. But I know Mercurial and therefore I know that it’s not the complexity of git which gives the flexibility, but the underlying decentralized model. Mercurial showed me that it is possible to have all that flexibility without the complexity of git.

      The decentralized model gives a lot of flexibility and I would not want to work without that. But git makes it pretty hard for normal developers to harness the power of the model while Mercurial makes it really easy, giving all the safety and convenience without the pain of git.

      So I disagree with your sentence. It implies that the complexity of git is required to get the flexibility of the decentralized model. And that is not true. But creating an interface which makes it easy to use the flexibility of the model is a pretty hard task – and that’s the task at which git failed and Mercurial mostly succeeded. The google folks called that the “sweet spot” of VCS. It’s not yet perfect and there are some points where git actually provides more convenience (remotes are nice!), but those are mostly relevant for maintainers of big projects and not for regular developers.

    • > Is CVS or SVN easily digestable from command lines alone? Most people I know wind up needing Tortoise or an IDE to make the type of merges I can make in seconds in git.

      SVN is, indeed, very simple to understand. I know training guys from my company, most people non-technical are able to work with it just fine after one hour of basic training. And merging is merging, the git heads often pretend to save a lot of time on merging with their great system while in fact most time is spent on resolving the conflicts in actual contents. And a VCS can hardly help you there.

      > “Just because something is complex to learn and powerful does not mean it’s a reason for hatred.”

      Did you read the same article above as I did? hatred doesn’t come from the fact of dealing with something powerful but from the thoroughly braindead user interface of this powerful thing.

  101. Pingback: Git is awful | Smash Company

  102. Git is like a ferrari covered in fresh dog turd. Yes, the fundamentals are awesome. But it’s hard to think of anything with a worse interface. Consider a really, really simple and common action: deleting a non-merged branch. Based on analogy with “git remote” I would expect “git branch rm –force foo”. Git seems happy with that; but instead of deleting, it creates a copy of foo called ‘rm’! My next guess would be
    “git branch –force -d foo”, but that’s wrong too. You need “git branch -D foo”. That’s really apalling. How on earth did they do such an awful job? The whole thing is inexcusable.
    Sure, when you’ve driven the ferrarri for long enough, most days you hardly notice the smell any more. But some days you just wish they’d clean the seats.

  103. Linus Torvalds is actually against GitHubs pull requests. You were supposed to send a patch to the ML and then a maintainer merged the patch.

  104. Indeed, I’m hating Git. It is NOT friendly for Enterprize usage (I’m at Intel). Git was obviously designed by college students who worked in groups of 4-6, and wanted to make big changes entirely disconnected from any repository, and wanted NOBODY else to own the official “known good source for release”. Fine. Use Git. Submit your college class semester project.

    Git is NOT happy at Intel. There MUST be one “holy and blessed” repository for burning released chips. In this environment, Git sucks. All developers want to do is “Update, Commit” (repeat), and truthfully, that’s ALL you want developers to do! Focus on their code, their features. Code analysis tools and Build machines will catch errors and reject submits. In this environment, SVN or Perforce are kings.

  105. Oh, how I wish this post existed when I was forced into the Git world. It would have helped me understand a little bit better how to hold my head when I try to understand anything related to Git.

  106. Steve, thank you so much for this summary. It points out most things I have been feeling for git in the last couple of years.

    Honestly, git is a toy from nerds made for other githeads ticking the same way as they do. It seems to match the taste of many project managers who then quickly switch to git, forcing whole communities to use this user-unfriendly software. And a couple of other guys that want COMMIT; COMMIT, COMMIT every second minute.

    The bad thing about git is that it isn’t actually really bad for most things but is totally embarrassing for other basic features, like not being able to handle empty directories or the crude hacks it uses to track file renaming operations. And the consistency of the user interface somehow reminds me on PHP’s API – inconsistent behavior, dangerous commands are just one CLI switch away from harmless operation, and the vocabulary which has been partially stolen from CVS/SVN and others with the meanings totally mixed up.

    Sorry git guys, that sucks. I just don’t trust a VCS which feels like steering on ice.

  107. Pingback: git vs svn | objetweb

  108. Very good article Steve!

    I thought I was too old, or too stupid, or a little bit of both. I am glad I am not the only one with the same frustrations.
    I have been using VCS for 17 years.

    I used RCS, CVS, SVN, Bazzar (just a tad) and now I am using GIT full time for the past 5 months.
    I spent a lot of time learning each and everyone one of them. Knowing my tool is important.
    They each had their strenght and weaknesses (ok, lots of weakness in RCS and CVS).
    I was able to master SVN and it was not frustrating.

    I found Bazzar more intuitive and easy to use than git. I was confident with Bazzar even though I did not use it for a long time. I had the feeling that I was controlling my project.

    With GIT, I am not confident at all. I am always cautious and nervous and.. it’s slowing me down a lot.
    Trying to master git is very frustrating.

    I WANT to be able to master git like I was able to master SVN. I just don’t see the end of the tunnel yet.

    • Pretty much the same feeling as you. GIT is all fun when you follow a simple forward workflow; I also find the staging area useful when you modify a bunch of files but only a few are ready so you “stage” only those to commit them…. the problems begin once you need to rollback and do more “advanced” stuff (I use the quotes because they shouldn’t feel like advanced things but they do).

      I’ve read the documentation, Scott chacon’s book, articles and everything and yet I don’t feel confident to do things backwards. The reset command is still black magic to me even though I have spent plenty of time reading how it works. You know something is wrong when you need to figure out all the things the commands will do before running them (should I use the –soft flag when reseting to leave the index and tree untouched? If I specify a previous commit using something like HEAD~2 when reseting, how do I ensure the good files are not modified and only the bad files are brought back to the working tree?)

      I know it’s just me not understanding it fully but it’s funny that something that it’s meant to make your development more organized and safe has to be so complicated even for the most basic workflow.

      Steve: the command with the “remote:branch” syntax you may be looking for could be the command used to delete a remote branch–> git push origin :branch_to_delete and yeah, it’s damn weird and inconsistent.

      • My take is that resets and other such reversions should never be pushed off into another repository — they are only for cleaning up messes locally. When dealing with other repositories, I think the right approach is to create a new branch that’s fixed up properly. (And, eventually, pruning the damaged branches.)

        The reasons for this might include technical issues, but mostly it’s people issues that this is solving. I do not get to control what other people do in their own repositories.

      • That tutorial is a nice piece of work, at least the first part, but the bit on rebasing does not convey its destructive potential in [for example] the context of a shared github repository, and the later “multi user” treatment does not fix that, either.

        Rebasing is fine for unshared changes, but it’s an utter mess when you have a shared history with someone else. And, yes, everyone can agree to rebase instead of merge, but that means that you lose the ability to revert to earlier versions of the code!

        If you have a shared history with someone and you really want a re-arranged view of history, you really should put that new view into a new branch. Otherwise, you are not using git as a version control system (which might be fine, but you should never expect that other people want to lose their version control abilities).

  109. rademi :
    And, yes, everyone can agree to rebase instead of merge, but that means that you lose the ability to revert to earlier versions of the code!
    …which might be fine, but you should never expect that other people want to lose their version control abilities

    That’s the best rebuttal of rebasing when you get remote changes I ever heard. Thank you for that!

    How come that this “I hate git”-thread is a much better guide on using git practically than the man-pages?
    (“don’t use it, but if you have to, do it safely)

  110. I am pretty certain that GIT was designed by Google to drive the next-generation of load on their search engines, because GIT is the ultimate driver of “help” queries, as in “help, this software has screwed up my tree and I can’t do what I need!”…

  111. tl;dr
    git is like mercurial with less than 5% extra features and 100% less usability.
    It speaks volumes that git’s adoption is so much bigger in certain circles.

    • it shows the stergth of group effects and strategicla advantages over utility for the majority I think: Git caters to the maintainer, and who chooses the VCS?

      Interestingly most projects which did a clear check of requirements (mozilla, google, python) came out in favor of Mercurial (with the disclaimer: “I remember this and I like Mercurial much better, so I could have a supports-my-position bias here”).

      • yes… and there is also some possibility that you are overgeneralizing here. Consider, for example, consider: https://github.com/google

        On the other hand, Linus Torvalds had some interesting comments on git, and github, visible at https://github.com/torvalds/linux/pull/17 …and after reading his point of view, and thinking about my own experiences, I am wondering how many people are struggling with github, and its workflows, vs. how many are having problems with git in a context which is independent of github?

        That said, everyone has their own needs, and their own ideas of how to address those needs, so personally I do not buy into the idea that one tool can be universally superior to another tool — I am much more interested in the reasons a person uses to pick a tool than I am in the choice they made. (But, sometimes these discussions reveal the kind of view points that I am interested in…)

  112. and regarding
    8. Burden of VCS maintainance pushed to contributors

    Why you would push the burden of VCS maintenance and branching (i.e. for every “clean patch” if you go by some manuals) to everyone instead of having a group of specialized people do it?
    Oh, because the specialized people are divas and don’t care that the summarized effort is a lot more and scales with the number of contributors? Isn’t that cute?

  113. rdm :
    yes… and there is also some possibility that you are overgeneralizing here. Consider, for example, consider: https://github.com/google

    That possibility always exists, especially for complex topics.

    But the google hosting is no real counter-example: It shows a handful of projects which chose to not use googlecode…

    The example I showed is not what google does today (it now also offers git for code hosting, see the group effects), but why they chose to use Mercurial:

    Mercurial offers an excellent “sweet spot” in terms of flexibility, simplicity, and speed. – Alex Martelli, Google Tech Lead

    And for me: I have more usability problems with git itself than with github. I wrote some of my reasons and wishes herein our previous discussion here: http://steveko.wordpress.com/2012/02/24/10-things-i-hate-about-git/#comment-500

  114. Pingback: gitの図 at softelメモ

  115. Pingback: GIT: a Nightmare of Mixed Metaphors – Ventrella Thing

  116. I think you got one of those examples wrong, it should be:

    git push master push push more squeeze wriggle merge pull tickle squeal commit puff puff

  117. Many thanks for this article.
    I thought it was just me, finding GIT so hard to learn and so ridiculously complicated, having previously Clearcase and then SVN.

  118. tldr;

    Not because of you but because of the subject matter. Anything about git automatically makes my brain shutdown. A few weeks ago I ran into a revolving door and broke my nose. It was less painful that git branching.

  119. As an example of git being somewhat batshit insane, this is the method I found necessary to properly and fully garbage collect the repo. There might be some unnecessary steps in there, but yeah… this took quite a while to figure out!

    git remote rm origin || true
    (
    cd .git
    rm -rf refs/remotes/ refs/original/ *_HEAD logs/
    )
    git for-each-ref –format=”%(refname)” refs/original/ | xargs -n1 –no-run-if-empty git update-ref -d
    git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc “$@”

    No git, I do not want you to provide backup services in case I am stupid, I do my own backups before dangerous operations. I want you to do what you’re told, without needing a 10 line script to spell it out!

    I’m not sure if hg is more sensible with garbage collection, I haven’t used it much, but it has a much better reputation for sanity.

    • > I’m not sure if hg is more sensible with garbage collection, I haven’t used it much, but it has a much better reputation for sanity.

      hg doesn’t create garbage to begin with, so there’s no need to collect it either. The closest to garbage that hg has is backup bundles. They’re all stored under .hg/strip-backups and can be deleted at any time, since they’re just backups.

  120. There are thousands of medium size, commercial project for which svn is perfect. And I really like the ‘comparative anatomy’ diagrams. Thanks!

    • Well, I don’t think you can read too much from Linus commenting that after two days, his primitive tool was not *yet* capable of SCM.

  121. I’ve just discovered git init will overwrite a repository without question. Just lost a day’s work, restoring my source from backups.

    • Really? What was the sequence of events exactly? I get the message “Reinitialized existing Git repository in …”, and nothing is lost.

  122. Haha – pshew this post makes me feel much less stupid. Plus I learned more about how git works from this page then half the other git instruction sources including the oreilly book…LOL!

  123. You’ve intentionally removed complexity from the SVN examples and added useless complexity into git examples. Git already has some shortcomings, you should stick to those.

    * For example, how do you avoid pull-requests on subversion? Oh, right, you give write access to everyone? That’s smart and so realistic.
    * Rebase? Never used it, never needed it. If someone wants to put some make-up over their repo history, that’s their problem, it’s not required at all.
    * You can add/commit in one command: commit -a
    * And no, you don’t need to push to a remote unless you’re working with a remote… In which case, you tell me how is subversion better, when you push directly (usually a bunch of changes that don’t fit logically in a unit) without enough testing, since all you want to do is “make it safe” as soon as possible? Half the times you either collide with another dev or you simple screw the main repo for him and for yourself.

    And I could go on, your post is just a bunch of these, with little truth lost among it.

    • >For example, how do you avoid pull-requests on subversion? Oh, right, you give write access to everyone? That’s smart and so realistic.

      You’re right, the Subversion open-access model is not equivalent to the Git pull request model.

      > Rebase? Never used it, never needed it. If someone wants to put some make-up over their repo history, that’s their problem, it’s not required at all.

      That’s not the case for everyone. Many projects require contributors to rebase patches.

      > You can add/commit in one command: commit -a

      True – although new files are missed.

      > And no, you don’t need to push to a remote unless you’re working with a remote…

      If you’re not working with a remote, you’re in a completely different category of use: solo developer.

  124. Pingback: kirjoittaessani » Blog Archive » Revisionismus

  125. Pingback: Git מהשוחות, אמנות אסקי יהודית בגטו ועוד. קריאה קוד פתוח ושיטוט ברשת « טכנולוגיה בשביל אנשים

  126. While I agree to a greater or lesser extent to all the points made in this article, the advantages of git are so compelling I would never select Subversion in preference – and I never expect to have a use for Subversion again. For me, SmartGit/Hg tamed git and made it very simple to drive effectively.

    The key defect of git from my perspective is that is cannot handle files > 2GB in size. I work in GIS and that’s not a particularly large file; files up to 10GB are commonplace. Although I don’t especially want to version control such large data files, I do want to manage them and base my development platform on a single repository with a single API. It seems surprising weakness to me.

    Mercurial and Bazaar also seem like fine tools, with slightly different strengths and weaknesses. I have not spent much time on them, other than to verify that they also suffer from the same irritating defect and hence I have no compelling reason to switch.

  127. Pingback: Free GIT repository hosting | Think Digital, Talk #Interactive

  128. Pingback: River Recycled » From Twitter: Continuing my anti #git ranting. this suits my moo… » The Same River. Twice.

  129. Pingback: Blackmoor Vituperative » I dislike Git

  130. I guess GIT screams for someone for someone for someone to make a decent interface for it (probably paid for). Most of the issues would then either be bypassed or simplified and probably something like a cutback form for users.

  131. I’ve been thinking recently about this very issue. It seems noncontroversial to say that git has the best adoption and the strongest architecture. It’s true that there are some great git clients out there which help get you access to that strong architecture. I’ve tried Tower and Gitbox and others. They help, but the complexity of the system, even for not-very-advanced tasks, comes out if you need to do anything besides clone, commit, pull, push, and merge without conflicts.

    I think there’s definitely room out there for a git command line abstraction that thinks about every common case that a contributing developer would come up against, and basically maps those use cases into git commands. GUIs could be built on top of that command line abstraction, but without the abstraction first, the temptation with a GUI is just to give buttons for each command. With git, I don’t think that’s good enough.

    Would someone else want to work on this? Does this sound like a promising idea? I’ve seen some other tools try this but I don’t think they go far enough. Simplification for this would be really, really difficult and require a deep as sea trenches understanding of everything that can happen when you want to, say, undo a commit.

    In a way this could be like “Javascript the good parts” for git. List out all the common end-user workflows, build aliases/scripts/walkthroughs for them that cover all the bare metal decisions your average contributor doesn’t want to have to make (undo commit that has/hasn’t been pushed to remote, push before pulling intentionally(?), rebasing vs merging).

    I’d view such a project a success if it could work for a team of 1-20 developers managing a repository that does basic staging, production, and version tagging contribution behavior and they could learn the whole thing in less time that it takes them to figure out why their git 3-way merge thinks the wrong side is more up to date.

    • Very insightful comments. Working on a project like this, although very valuable, could be unrewarding. As you point out, you’d need a very deep knowledge – but once you get to that level, you may not be so motivated (because, after all, Git is so simple now!) I doubt you’d get much support (if not downright hostility) from the main Git developers, so you could be working in isolation for years, constantly frustrated by small changes in Git’s internals.

      • Why not just map the command line with intelligent logic- do not delve into the internals of git- sure they might change the commands but that can be patched over. If need be merely hide the command line and simulate keystrokes.

  132. Pingback: Don’t be a git, use subversion | ebeab

  133. Another issue for me is the impossibility of checking out just one folder of my repository, not the repository as whole.

    I understand the concept of Git managing “projects” in the meaning of “you have to check out everything or nothing” but this is often not the way I need a version control to work.

    Example: I provide several useful files for my company: a LaTeX tree, OpenOffice templates, Office templates etc. A user interested in the LaTeX tree only does “svn checkout …/trunk/latex” and is done. In git she has to clone the whole repository including all branches tags etc. and then has to use the one folder she is interested in.

    Thus I still use svn for this project only to avoid this special issue.

    • svn is great if you want to prevent shared ownership – if what you want to prevent is group effort. (cvs is another possibility for that.) There’s nothing wrong with hating git – if what you need is a bottleneck – if git is the wrong tool for you.

      • It is possible to dislike git without preferring svn. I wonder whether you tried the DVCS alternatives. Compared to git, the Mercurial UI is wonderful…

      • It’s possible to hate part of something without hating the whole thing. (Hating your government without hating your country.)
        It’s possible to hate one thing without preferring a certain other thing. (You think Git is a 3/10 but SVN is a 2/10.)

    • Or, to put it another way, the mismatch between git’s functionality and version control functionality that leads to confusion and disdain.

    • >Lol, so many git haters and all i see is complaining about things that they don’t understand.

      That’s kind of the point, actually.
      I doubt that the people posting here are stupid. Still it requires more time and work to understand git good enough than they may be willing (or paid for) to spend on understanding their version control system.

      The version control system should not be harder to understand than the code itself.

  134. I’ve used a variety of VCSs over the years and finally stumbled (got lumbered) on Git. A long-long time ago I used CVS (I cant remember much except it was a bit crap). Then we got VSS (absolute crap and dangerous), then SVN (yeaa! happiness at last). Then in one company I worked in an abomination called “AccuRev” was intoduced, an interesting attempt to create a visual UI, some good ideas but so horrible that we needed a support team to look after it. Then I discovered DVCS and Mercurial (enlightenment and bliss). Used it for two years in my last job (still using it for my own stuff on BitBucket). For the last year I’m working in a company that is migrating from a mix of VSS (aargh) and SVN (I know, mad in 2013). My boss has decided that Git is the way to go even though I am the only one in the company with DVCS experience and would much rather use HG. I set up a server in-house with a demo repo, wrote a three page guide for everyone (and pointed them to Joel Spolsky’s excellent hginit tutorial) but no, my boss is insisting on Git. I’ve spent the past few days cursing and gnashing as I’ve tried to set up the Git server on Windows and port a few projects into it (the pain!, thanks to Tim Davis ‘http://www.timdavis.com.au/git/setting-up-a-msysgit-server-with-copssh-on-windows/’ for really trying to explain it all). It’s got to the stage where I’m about to tell my boss it’s HG or I’m outa here…

    • Try to look at some of the 3rd party suppliers, I have never ever installed a pure git server my self, but Stash (from Atlassian) was virtually pain free…

      Overall it seems there are more momentum on git these days, e.g. Atlassian adopting it in Stash, Microsoft delivers git integration in Visual Studio and many others… So it might not be such a un-informed choice to adopt it over e.g HG…

      I can second you on that It’s a damn risky decision if you don’t have any in-house that has the knowledge though… But top bosses often tend to think in terms of “That is what they all talk about, so we should go there to…”, and while it’s a decent philosophy on some cases, you need to be ready to pay the price.

      Anyways, 3rd party integration’s can help you… And one thing is initial installation, another is ongoing maintenance and administration, tools like Github Enterprise and Stash can IMO really help here… Even for my personal SVN i found it far easier to just install CollabNet’s subversion edge over a standard subversion server…

  135. Pingback: Some notes and links on DVCS (dynamic version control systems) « The Wiert Corner – irregular stream of stuff

  136. I actually had to turn down a client because they use git. I got fed up doing 1 hour billable work and 4 (unpaid) hours trying to figure out what git did. Too bad it wasn’t designed better. Oh well, lots of other choices.

    • GIT is state of art software and if you have problem with it, then it is more likely that you should debug relation between chair and keyboard, rather than trying to figure out “what git did”

      • The only thing about GIT that’s ‘state of the art’ is the concept. There is no doubt that DVCS is the way to go. Making DVCS hard is not ‘state of the art’. Mercurial (which is what I use at the moment) is at least consistent and pretty quick to learn and easy to use every day. It’s not because I learned it first that I prefer HG (SVN was the third ‘traditional’ VCS system I learned and easily the best). When I learned HG I had a number of tasks to accomplish, learn the DVCS concepts, learn HG itself and learn to set up and use remote HG servers. I came to Git with an open mind (I was genuinely interested in adding another VCS to my repertoire) but the pain was too much especially in setting up a server for the team. From nothing to a server supporting a few HG repos was an hour or two. With Git I gave up after two days. I’m not smart enough, obviously.

      • Well, in my personal experience, I had a problem “to get the mindset”, but then I started to work with it and beside few occasional issues mostly produced by me or someone from my team, it is a lifesaver… I really can’t imagine to work without it… I do have some little experience with Mercurial, but that long time ago. I would like to try it again, but there is really no need (for my team, I’m not saying someone doesn’t like anything else better)
        Once we started to practice http://nvie.com/posts/a-successful-git-branching-model/ our git troubles are mostly based on “someone didn’t follow the rules”, but even in that case we always managed.
        I am kind of sad when I see many people in this thread are spiting all over git, but for very wrong reasons, especially if they like SVN…that is just wrong :(

    • Yeah, SourceTree is pretty good. It does a great job of helping you understand exactly what mess you’ve gotten into this time.

    • I don’t think that logic holds. There are hundreds of technologies that have done very well due to making a complex problem very simple. Git has succeeded in spite of its complexity, not because of it. If there was a simpler version, I think that’d do pretty well.

  137. I’ve been using git for over a year and it has only provided frustration and suffering, though I can appreciate it’s power. I’ve nevertheless managed to trash my repository several times trying to fix what should be trivial issues. You are right on that git is made for power users not the end user.

    One extreme annoyance for me is that I need to distribute my code over several machines from which I do not intend to do any development. In fact for most use cases, when I want to pull code out of the git repository I want to replace whatever rotten old code I have in the current directory, ie I just need an update to the latest. To do this I must use the extremely hard to remember commands,
    git fetch origin master
    git reset –hard FETCH_HEAD

    The git developers apparently never thought that some people might just want to use git to fetch code. I have found that it is much safer to only develop code for my repository from one golden directory. Otherwise you can get unwanted merges that are a pain in the arse to unwind. In fact it is not that unusual to alter compile flags that are specific to the architecture of a given machine, or to set data directories in source configuration scripts that are also specific to a given machine. I don’t want to pollute the repository with that sort of thing. Yes there are commands that enable this such as the -s ours flags etc., but it is very hard to remember the exact syntax, since, as described it is not consistent.

    Someone really needs to develop a consistent easy user interface overlay for git for common simplified workflows. I also find it annoying that the gui’s that are provided don’t have some of the most important commands. git gui is very poor with regards to fetching and merging but pretty good with regards to adding committing and pushing.

    • Did you try switching to Mercurial? Your usecase would be resolved with `hg pull -u`.
      hg-git allows you to easily access git repositories with Mercurial.

  138. First of all thanks for your post. At work we use subversion; while I start to get used to git, I do not think it would be a good idea to introduce it at work exactly because of its complexity; so yes I fully understand why you “hate” git.

    Still I think some of your points are not very valid:
    1. Complex information model
    Hmmm. The way most tutorials are written you are correct. The main reason why I still disagree is, because once you look at the “advanced” stuff it actually gets simpler. Once you understand that git stores three main types of objects (blob, tree, commit) + each object is referenced by a SHA-1 checksum over its content, the information model starts to look a lot simpler.
    After that reading https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html clears up lots of questions.

    2. Crazy command line syntax
    I agree. It really could be better; but then again it would be really easy to make it less crazy if people cared enough.
    What about the project “Easy Git” ?

    3. Crappy documentation
    I agree that the man pages do not make sense to a new user. But that is because you first should understand about git objects, then understand of local / remote repositories, then read “gitglossary” and then at last read the man pages of the commands (at least this was the order which made most sense to me).
    I once gave an introduction to subversion. If you talk to people, which are completely new to version control in general, then even this is hard, even if the concepts in subversion are much simpler and easier to understand. I think that learning something completely new usually means that the terminology will sound like gibberish.

    4. Information model sprawl
    Once you understood about “blob”, “tree”, “commit” it does not seem so complicated anymore…
    The biggest problem seems to decide how to organize branches for a given project. With subversion this seems to be even harder; at least from my experience.

    5. Leaky abstraction
    The example you give here seems to be something which you could not even do in subversion ?
    So the complaint seems to be, that you do something quite complicated and it turns out that doing it requires a set of complicated commands. This seems not very surprising. Maybe what you were trying to do was not complicated ? But then it might help to explain first what you were trying to do, before complaining.

    The “no abstraction” means that you are able to do these complicated things, because these complicated things do not allow for an easy abstraction…

    6. Power for the maintainer, at the expense of the contributor
    In all your examples you seem to assume a model in which everybody has write access to a central repository. At least that would be the “easy” case in subversion.
    How would you setup a maintainer kind of workflow with subversion ?
    I am really interested, because I really have no clue how that would work:
    - Checkout
    - Modify
    Now:
    - Commit ? Hardly; I do not think everybody gets write access to the central repository
    - Commit to some other repository, which was cloned somehow ? Who then integrates my changes into the “master” repository ? A maintainer ??? this poor guy! How do I get updates from the “master” repository ?

    So what would be the easy workflow without expense for the contributer ?

    7. Unsafe version control
    That was an interesting topic, because I am still quite new to git and understood the concern. After googling: What about
    git config receive.denyNonFastForwards true
    on the “master” repository. This seems to avoid most of what you are worried about or am I wrong here ?
    In general all of this assumes that you have write access to the master repository.
    As I said I do not understand how you would have a maintainer like workflow, if everybody has write access.

    8. Burden of VCS maintainance pushed to contributors
    How do you “update/commit/update/commit” without write access ?
    How do you have a maintainer if everybody has write access ?
    I do not seem to understand how you would implement your supposedly simple workflow.
    What happens in the case of “update/commit” … oh crap I broke the build ?
    “undo commit” (not really possible in subversion) ?
    revert change then commit ? What happens with the user users who already “updated” the broken commit ?
    Maybe they fixed it on their local working copy and now get conflicts when they update my “undo commit”…

    The model you describe seems to put a lot of responsibilty on the contributors; they really should not make any mistakes, because it hurts everybody else.

    9. Git history is a bunch of lies
    “Surely the correct solution is a better log output that can filter out these unwanted merges.”
    That sounds like you want a sophisticated AI as a filter. When I look at the logs of our subversion repository at work it is quite hard to tell which log entries might be merged; so no clue how a computer might do that.
    Git history on the central repository (or master repository) is only a lie if you allow it, by allowing non-fast-forward updates.

    10. Simple tasks need so many commands
    This is mostly unfair. If you want to do the same as subversion you would do

    1. modify
    2. git commit -a
    3. git push
    So exactly one more step than in subversion. The git way allows you to do “git status” (ok I did not forget anything), compile … broke the build; oh good I can still fix it, before anyone notices it and gets angry.

    The thing about github only applies if you use github. You compare oranges with apples; a central subversion repository with github…

    Note that after using git for a while, I never use “git commit -a”. It simply happens far too often that I modify several files, but only want to commit few of them. It is much easier to first use “git add”, then “git diff –cached” to see if you really got everything and then use “git commit” to commit exactly that (yes I agree: The syntax could be more obvious). With the subversion command line there simply is no way to do that; you need “svn commit ” and sometimes you might commit too much or not enough.

    Another example: “git stash”. The way I do that with subversion is, to first use “svn diff” to create a patch file, then undo all my changes with “svn revert” and then to reapply the changes later when I am done with whatever I wanted to do. Note that re-applying the patches requires “patch” a non-subersion command as far as I know. So the “simple tasks need so many commands” applies to subversion in this case.

    “As an added bonus, here’s a diagram illustrating the commands a typical developer on a traditional Subversion project needed to know about to get their work done.”

    And where is the maintainer in this picture ?
    That is where the complexity from the github example comes from. So again you compare apples and oranges.

    Summary: I still completely agree that git is a lot more complex than subversion. Yes it really lets you shoot into your food. Still I am not convinced that subversion is so much easier (I just have to remember the svn-property and “how to merge” discussions we had at work).

    • >The main reason why I still disagree is, because once you look at the “advanced” stuff it actually gets simpler. Once you understand that git stores three main types of objects (blob, tree, commit) +…

      This is kind of true, which is very weird. You really, really shouldn’t need to know this stuff.

      >2. Crazy command line syntax I agree. It really could be better; but then again it would be really easy to make it less crazy if people cared enough. What about the project “Easy Git” ?

      I don’t think it’s about “caring”, it’s that the syntax is too hard to change now. The attempt to separate “porcelain” and “plumbing” has failed. EasyGit doesn’t go far enough.

      >That was an interesting topic, because I am still quite new to git and understood the concern. After googling: What about git config receive.denyNonFastForwards true on the “master” repository. This seems to avoid most of what you are worried about or am I wrong here ?

      I think if new users need to set some hidden flag on their repositories in order to protect against data loss, my point is confirmed, no?

      >The model you describe seems to put a lot of responsibilty on the contributors; they really should not make any mistakes, because it hurts everybody else.

      I’m not really advocating for “everyone has write access” workflows. I’m just pointing out how complicated the default workflow is for Github. GitFlow probably improves things a lot.

      >Git history on the central repository (or master repository) is only a lie if you allow it, by allowing non-fast-forward updates.

      Interesting idea, thanks.

      >Still I am not convinced that subversion is so much easier (I just have to remember the svn-property and “how to merge” discussions we had at work).

      Yep, Subversion is too limited for modern development.

  139. Pingback: Learning to Code | Quartet

  140. I hate git right now. It is the source of great frustration. :/ Suck it, git!
    These things should be much much easier to do, instead it’s harder than actual programming and such.

  141. Pingback: Learning to Code | Decluttr

  142. Someone probably said that already, but the Information Model is not that complex, given the decentralized nature of Git. Repositories are repositories, whether they are remote or local. Tags are actually tags, much closer to the real life thing than in SVN, and there is no trunk, which was some kind of a fuzzy notion in SVN. Commits are still commits, on SVN same as on Git. I don’t know what treeishes would be. Stash is just like a commit, and you don’t have to use it if you don’t like/understand/feel comfortable with it.

    But I guess all this is just a matter of perspective.

    Apparently, you have been spending a lot of time on Github, and it is the real target of several of your criticisms. The thing is, a/ I don’t know any code hosting system that allow anyone to do something similar with SVN (I’m only talking about the pull request part, of course), making the comparison quite pointless, b/ github is not git. It is one way of using it. Most usage of git I have seen are very similar to what SVN was like before the switch, only more powerful (not going to be to long on that, but the merge tracking alone justifies the switch)

    Last point, regarding rebase, it is not a “lie”. The commits you push to the remote are not modified once they are pushed. No pull is ever made of a different tree, history is not rewritten, you simply apply your work on top of the latest remote version. (If you use rebase after a pull has been made on your repo, that’s a different story, but the SVN admin could do just the same).

    • >Repositories are repositories, whether they are remote or local.

      Remote repositories, local repositories, and local copies of remote repositories (ie, origin/master) all behave differently on the command line.

      > there is no trunk, which was some kind of a fuzzy notion in SVN

      “master” is a pretty fuzzy notion in Git.

      > I don’t know what treeishes would be

      That’s what Google is for.

      > Stash is just like a commit, and you don’t have to use it if you don’t like/understand/feel comfortable with it.

      Except the syntax is all different and a few other peculiarities.

      > Last point, regarding rebase, it is not a “lie”.

      If the sequence of development goes A-B-C-D-E, yet the version history after a rebase goes A-C-E-B-D, I think “lie” is an apt description.

      • > > > Last point, regarding rebase, it is not a “lie”. > > If the sequence of development goes A-B-C-D-E, yet the version history after a rebase goes A-C-E-B-D, I think “lie” is an apt description. >

        Agree.

        I think an important default behavior would be for rebase to be the default merge behavior when history lines up correctly; automatically use merge instead if/when history isn’t congruent. In other words, new commits should normally go on top of pulled changes regardless of the timestamps without requiring a different set of commands or prior knowledge if what has changed in the remote repo.

        Another related behavior that would help me understand our current repos would be for git to show history in merge order instead of commit timestamp order by default, or at least provide an easy tool to display history in merge order.

        >

      • > new commits should normally go on top of pulled changes regardless of the timestamps without requiring a different set of commands or prior knowledge if what has changed in the remote repo.

        New commits go to the top by definition. Of course, by the time you pull, they are old commits. You might be thinking of unpublished vs. published commits – but the software cannot reliably determine which is which. You can set the pull behavior per-branch via the branch..rebase config option.

        > Another related behavior that would help me understand our current repos would be for git to show history in merge order instead of commit timestamp order by default, or at least provide an easy tool to display history in merge order.

        What do you mean by “merge order”? Commits which happened on different branches do not have any obvious ordering. If you want to keep together consecutive commits as much as possible, you might be looking for the –topo-order flag.

  143. At first I was going to hate, but then after getting through your post I think it’s pretty well written. I’m not expert so I can’t debate. My only confusion is when you compare SVN process to GIT why you also talk about github. I don’t use github professionally so it clouds the point a bit. I do use github for my public/personal code.

    • I wrote the article about my own personal experiences with Git which all involved (and still do) Github. I almost never come across projects that use Git but don’t use Github in either my work or sideprojects.

      • fair enough. I mean I use github for my public projects but I also don’t do much collab on there. I use just git on the commandline for my private projects and for work we use gitlab which is just an alternative to github. But without me knowing better I wouldn’t think you’d need any gui (gitui, github, gitlab etc) to manage repositories. So I’m just saying if you take that out of the equation I wonder how its diagram compares to svn in complexity. I figured github was just for managing repo’s and users in a GUI friendly way, and to merge forks and stuff like that, but not necessary.

  144. Perfect article which reminded me of my 9-month experience with Git after 5 years of experience with SVN. I definitely agree that user interface of Git totally sucks comparing to one of SVN. Git beats SVN in lots of things just because it is DISTRIBUTED version control system (VCS), while SVN is centralized one (ironically 90% of Git supporters doesn’t know the difference :)).

    So, I’ll add to superb comparison of “Granny on the freeway”:
    Git is like Formula-1 sports car – it accellerates very fast, it brakes very good. In hands of a professional it’s really awesome tool. But for beginner to intermediate user it’s total overkill and out there there are 95% of such users.

    SVN is like normal city car – it has normal engine, normal brakes and normal suspension and hence fits 95% of use cases. Any professional on this car will easily beat beginner on Formula-1 simply because he/she knows that in most cases power is not what matters.

    So, 90% of arguments for Git over SVN looked like advocating Formula-1 car in small city over normal city car just because it’s so damn fast :)

  145. Pingback: My Journey Towards Learning Git | Robert Cina Online

  146. Great article. I must say it has been quite “challenging” being forced to switch to Git from SVN. It is a completely different mindset which I have had trouble switching to after 12 years of Clearcase, then SVN. I got very use to using SVN through Eclipse and using Git through Eclipse seems to be much more difficult, at least at the very beginning.

  147. The bottom line for me is simply that Git is in my way. It consumes more time $@#&ing with it than it’s worth. Source control should be a tool to enable my coworkers and I to collaborate effectively while focusing on the core work of programming. As such, I need them to have a tool that’s simple and bulletproof. Git is anything but.

    • Glenn, I totally approve of your approach. However, I must also admit it is not for me.

      See… from my point of view what you are telling me is that you (a) do not understand Git, and (b) are happy with the alternative you are using. So you are not motivated to change. That might change in the future, but that future has not arrived, yet.

      That said, if we were working together? I would bet that I could have you up and productive with Git within an hour (probably half an hour, but let’s allow some time for unanticipated problems…).

      Something similar could probably be said of other tools (like Hg). Proficient technical people learn to take advantage of their tools, whatever they are, and to focus on delivering what some people ask them to deliver. [Management, of course, has a slightly different job.]

      • That is then an hour you spend, getting someone else up to speed. And if stuff I read on the internet is of any value, he will keep stumbling regularly and ask you again.

        With hg you could say that I have that position in the team I work in. We have 3 people not really familiar with version tracking. And in 2 years, I got about 6 questions after the initial setup. Not per month and not per year, but overall. How’s your mileage with git?

      • Maybe, yes. But often enough that hour spent saves me a good 10-30 hours over the course of a year. Also, most of the younger programmers I have worked with already know how to use git. So it’s really not that big of an issue for me.

        Also, a lot of problems with git are really github issues, and most of those can be resolved by cloning a fresh repository and working with it. Most of the remainder can be resolved by making sure that they are using a relatively recent version of git.

  148. Hi again,

    I still would really like to know how to setup Subversion in such a way, that you get a maintainer workflow. You write:
    ——- snip ————
    8. Burden of VCS maintainance pushed to contributors
    In the traditional open source project, only one person had to deal with the complexities of branches and merges: the maintainer

    —— snip ———-
    I work with Subversion each day, but I still have no clue how you would setup a maintainer if you have a central Subversion repository.
    How would you do that ?
    I am really interested, because I certainly do not know.

  149. Hmm. lundril, if you seriously need to know how to do maintainer branching patterns with Subversion, ping me at my consulting address http://opentechstrategies.com/. (This is not meant as a statement one way or the other in the git-vs-subversion debate, by the way. Git has great branching and merging, and I use it all the time. But I couldn’t tell if your question was just part of the conversation, or was an actual attempt to find help for your workplace. If the latter, I’m happy to take a look, though it sounds like you understand Subversion pretty well and basically are just missing what you’d get from Git.)

  150. Pingback: Version control Part 1: Local repository | Tom Wallis

  151. Pingback: The Git Reference | Tamasdan.com

  152. Pingback: Git: what they didn’t tell you | Steve Bennett blogs

  153. Yikes. Interesting post. From my experience it’s like someone trying to re-invent the wheel. First time I used Git, I had conflicts on my second commit. It’s not as much about the tool you use, but more about how you use the tool at hand. In repository’s case, for the projects that I’ve worked on, SVN is just fine. No need to complicate things.

  154. You’ve summed up my feelings with more educated examples. I gave up on subversion in favor of git, and I think it has the features that I want. But, man, it is so difficult figuring out the way to use that functionality.

    It was extremely easy getting the repository and first import setup, but after that, the developers decided to let the users suck it after that.

  155. > To reset one file in your working directory to its committed state:
    > git checkout file.txt

    It seems that the correct command is

    git checkout HEAD file.txt
    or
    git checkout HEAD — file.txt

    I was bitten by this. When you pass paths or –patch, git checkout defaults to the index (staging area), so if you want to revert to its committed state you must pass HEAD explicitely as a parameter.

    Of course this only proves that git does things very differently when file names are present on the command line…

    However, after learning git for about one or two months, it does not look as horrendous as people say. It’s certainly possible to use it despite the little annoyances, and it usually prints useful messages on the screen while it operates.

    Currently I’m a little annoyed with git add -A, git commit -a, git stash -u…
    If only we had git add -A, git commit -A, and git stash -A plus an easier to use git reset… I think it should be separated in two commands: one to undo git add and other to move HEAD.

  156. Just wanted to vent:
    Git again fucked up my local changes when I did a pull.
    Git is so stupid compared to TFS wheneven I try to pull changes from teh server it can’t just download the unchanged files and leave the changed ones alone. I had to stash my local changes, then pull server changes, then un-stash my local changes and retarded git couldn’t unstash my local changes (dunno why, it didn’t say, but I guess it’s because git is the most retarded source control out there).
    .
    To the morons who wrote it – you should learn from Microsoft and TFS – TFS is the best!

    • In my experience whenever you have problem with git, it is at chairkeyboard relation. I am absolutely sure that you don’t know what are you talking about, so unless you have any argument to confirm that you did everything right and git “fucked it”, please go use something more close to your intelectual capacity. Thank you very much!

      • If a product is hard to use, is that a “chairkeyboard relation”, or a problem with the product?

      • You have missed the point of this article, which is about the poor “UI” design of git that leads to these muddles. You may well wear your underpants over your spangly tights but if that’s really what it takes to use git reliably then most of us would say it’s not fit for purpose – because most of us don’t believe version control is that difficult. Simply insulting people doesn’t make git a better tool and, given that James seems to be happy with TFS, should give pause for thought.

      • While technically correct, it seems like there ought to be a better way of addressing people with this kind of problem. Everyone starts out ignorant of the technical details.

        In my experience, usually the best way to approach this involves asking for:
        (a) What specifically did you do (exact steps)
        (b) What did you expect to happen
        (c) What did you see instead (exact error messages).

        People will usually range from too impatient to deal to those that are interested and capable. Many times when a person follows these steps they will figure out how to make it work. Sometimes they will have trouble finding relevant documentation – that can be a good opportunity to point them at the documentation you find relevant (and hopefully they see it the same way). Sometimes they will have found an actual bug (like if the code crashes or whatever), and if that’s the case they need to be treated with respect.

        Unfortunately, it’s all too easy to think you’ve found a flaw when you have not. But by asking for a small amount of effort from people you can weed out most of those who aren’t worth your time.

      • There might be a set of 9+ commands to make git reliable; but, there’s a single click in SVN. It might be an egit problem and it might be a stash app problem; but its not a chairkeyboard problem. For sure, what works every time with one click in SVN (and CVS before it etc) had a high probability of failing with git. – off to manually resolve even more files git failed to commit.

    • I use both git and TFS every working day and I have managed to get myself in bad muddles with both. However, in normal working practice I find git enormously more comfortable and secure feeling. The ability to stay under version control when I am working offline is essential, similarly private branches, and the freedom to manage my branches without managing a horrendous pile of nested folders. If you have to use git, may I suggest getting holding of SmartGitHg (or Atlassian Sourcetree), which are excellent tools and make git safer and more manageable.

    • James, I suggest you always `git commit`, not `git stash`, before pulling, merging, rebasing, or whatever. That (a) forces git to merge the changes in as part of `git pull`, which makes `git rebase –abort` available; (b) gives you an exact commit to return to if you find things get horribly borked, so you know your changes are safe.

      Your specific feature suggestion, downloading unchanged files and leaving the changed ones alone, is not workable, as it would silently drop upstream code on the floor. That could well lead to the project being uncompilable! It would also be a nightmare when you came to git push again, as you’d be reverting parts of other people’s work.

  157. Pingback: The Guy Who Made Your Android Phone Possible Responds To Nasty Tweets About Him | Construction

  158. Pingback: The Guy Who Made Your Android Phone Possible Responds To Nasty Tweets About Him | Digital Wealth

  159. Great post. Most use git in a source control pattern where changes are branches and must be approved. This is great for two scenarios: 1. mature code base with high risk aversion. 2. Junior programming teams where most do not comprehend the whole product. The main problem with this approach is the merge conflicts. Way, way, way, way, way worse than source control usage patterns common with CVS/SVN. In those, you merge at least daily so must keep the entire product in sync. Another problem with the way git is used is many (all of both medium-sized projects I’ve worked) projects allow specific persons an advantaged seat where they can merge as is convenient to them, but everyone else has to manually resolve the junk they did. Maybe its human nature; but in the typical SVN pattern, the first merge wins; so, good developers constantly keep their code in sync with the product. In git, it quickly goes to …

    • BTW, ever notice how git takes like 5 commands to do something which is two right-clicks in svn. No matter what you think of how people use git/svn, the fact of usability is there. What is even more strange is its perfectly possible to make lots of branches and do code reviews on those with svn – looks more like the primary goal for git users was to be able to stash/local commit. That is the only differentiating feature as far as capabilities which I have observed. Outside of that, everything you can do with svn you can do with git, and vice versa. Svn is just 10x easier and less error prone.

      • Do have to give credit to egit, Eclipse plugin for git. I used it before enduring lots of gaps; but, on this project its quite decent. I almost never have to shell out. (had to for merge to do a “git commit -a” to make git take the changes.) Its a great plugin and makes using git/stash tolerable.

      • The local commits are one of the major reasons why I prefer Mercurial over SVN. Also branching has lower overhead. And you can commit before you merge, so you first secure the work you did, then you integrate it.

  160. OK, read through some of the posts. FYI, svn merge intra-file is very good. Git sucked. Perforce sucks. MKS probably sucks worse. ClearCase – been years since I used it but it sucked in several places. Used several others. So far, SVN is the cleanest. Of course, have someone with a brain deciding the branch and release strategy is far more important. I actually think git merge might have improved some since 6 months ago when I used it alot. Not sure but latest project I’m seeing less mess to manually clean up after git.

    If you want a maintainer then just have all commits reviewed before being accepted into the head/trunk. No matter what source control, you can branch to your heart’s content. Just like people do with git.

  161. Some things you should NOT do with GIT which are common with SVN.
    #1. commit+pull on a whole tree. While this works sometimes, when we are on this project with different timezones then silently many files do not get picked up. Sure, you might should notice it in the list; but with SVN this just always works. In contrast, with GIT you had better commit -m “” exact-path-to-file for every file. Don’t just “commit” at top of node with egit nor even try git -am.
    #2. Don’t do lots of pulls. If you come from a distributed team development background, then you are used to very, very often pulling the latest. This is BAD with GIT. Apparently the git tools are like MKS and determine diff based on timestamp. laughable if not so true. I never had this problem with SVN and think they might do binary compare. You’ll end up needing BeyondCompare or another binary folder tree comparison tool if you use GIT.
    Long story short, in GIT you checkout/pull ONCE, make all your changes. Then try to commit+push everything at which time you do lots of merge conflicts resolution. With GIT you cannot sync frequently or things stop working. (assuming you are branched and have a fairly complex branching relationship and have lots of people changing lots of files).

    • If anyone is reading this, please don’t follow this advice. Heuristic: follow the practices of people who have good experiences, not those who have bad experiences. Frequently pulling the latest is only correct in one particular workflow, where there is a single, central master copy. Also note that in git you should be fetching not pulling.

      • In Mercurial you normally *merge* frequently and explicitly. It works pretty well. A canonical upstream is not needed for that, just sane people who do not rewrite history.

        I agree on fetching: git pull is essentially a fetch+merge and as such quite dangerous if you do not commit beforehand.

      • In summary, with GIT you do LOTS of manual merges for any normal-sized project where you have lots of people working on the same files. So, to use GIT like is done in Linux, you need a MAINTAINER. Only he or she really changes the files he or she owns. Changes are suggestions to him or her. That’s GIT in a nutshell. Worth noting that the two projects where I used it quickly devolved into one or more “Leads” who would delay reviewing the changes from the rest of the team while he/she refactored the underlying code base, and then expect the rest of the team to sort it all out manually. That is common and repeatedly occurs on GIT projects. It never occurs on SVN projects because, with SVN, if you want to refactor the hell out of the source base then you do it all one late night after clearing that with everyone else or you do it piecemeal after clearing it all with everyone else. Not saying GIT couldn’t be used equanimously; but, definitely tends towards creating constant merge messes which must be manually cleaned up. Bottom line: GIT is a REAL TIME WASTER. You can add at least 20% additional time to the development effort if you choose GIT instead of SVN. At least. Honestly, I think its more like 40% because with GIT you need tons of meetings to figure out what in the heck is going on whereas with SVN the small changes are palatable and, therefore, somewhat self documenting. With SVN, if you make a change affecting others then they see it soon and can understand it better. With GIT, you wait around until a Code Review event, and, by the time that occurs, then the entire code has moved on and manual merge is almost guaranteed. (well, 20% of the time at least).

      • Ok, let’s blame the tools for our own failures. Because if we were responsible for getting something useful done we’d be doing that instead.

        Seriously, if you like SVN that’s great. if you like Mercurial, that’s great. If you like Git, that’s great. But maybe also take a look at what you are accomplishing and how you deal with other people, also.

        Put differently: in a few cases changing the tool will actually help. But if you are frustrated with wasted time then you need to seriously think about doing more arguing about what tool other people should use.

      • @Raul Miller: Keep in mind that having to do more than changing the tool does not mean that the tool is not partially responsible for bad habits which evolved.

        A good tool makes it easier to do the right thing than to do the wrong thing. And while the the obligatory branch-naming of git is pretty good at making people use branches, it is pretty bad at keeping a code-base in a consistent shape (I‘ve seen quite a few year-old branches slowly rotting away because no one merges them)..

  162. Pingback: Git | Rauhe Sitten

    • That was what I found too. “Git is cool”. Just use it. “Its cool”. Pretty much sums it up. Two features make it a choice for special cases; but, those are really edge conditions these days where everyone has Internet every time and where setting up a branch in your favorite SCS is easy everywhere now.

      • In contrast, as chronicled in this page, GIT will add 10% to 40% project cost versus using SVN. But, I’m sure most GIT fans don’t want to talk about reality.

  163. Just did a git merge on two branches. Stash (git) said each was in conflict. In one, in a class a _different_ constant had been defined by each. Git could not auto-merge that! In another, the imports changed. Git could not automerge that! Would be nice if git know something about Java; but at least it should be able to automerge non-conflicting changes. IDK what tool git uses for merge. I know I worked at one huge co that used Perforce and its merge was bad. SVN has been good IME. Why use a tool if you git to do it all manually!!! “Git it”

    • Why even write code if you do it all manually? All that finger motion – it’s just so… exhausting? All that thinking! How horrible. Maybe someone else should do it?

      • Exactly! Last thing you need is a manual SCS! One more flaw of GIT while we are talking about GIT warts…. its “local repos” are just copies of stuff in your working folder. I know, many SCS have this problem. Heck, the project.pj files from MKS break Android compiles; but, since GIT is THE LATEST AND GREATEST, couldn’t they do this right?

        BTW, GIT’s salient feature is support for code reviews. Each change is a branch. This allows one to hire unskilled high school, offshore, and other unskilled people and give them one single task. Experience will teach you that the time to code review and teach them to program is greater than the time to just hire good people. But GIT would be great for a college, and that’s effectively what most large corps are when it comes to trying to use unskilled labor to do skilled work.

    • A few more things which don’t work in git merge and cause manual work:
      1. comments. (really, not kidding, you’ll have to manually merge if someone adds a comment (// stuff) to a file in another branch
      2. net adds. Yep, when you follow the steps below as listed by stash (git site) then you’ll find the net added file is not pulled. Ridiculous bug in git (or else stash’s directions. And if a git dedicated site can’t even figure out how to make git work…).
      3. multiple other problems. Its tedious to list because clearly the author of git did NOT bother to learn from the others who have written SCS in the past. Git is absolutely a way to waste another 10 to 30 minutes for each bug/feature point. Sometimes can be even more time.
      (The reason I’m chronicling here is this pattern of people with 0-5 years experience jumping on fad frameworks is a waste of human productivity. For us to take the next great leap forward as a species, we must learn to “Build on the Work of Others”. Not continually doom ourselves to make the same mistakes. At the very least, decisions need to be made with a list of Pros and Cons; not based on what someone hears at Google IO or whatever latest conference.)
      Stash steps (works sometimes :-) (mostly from memory)
      git fetch origin ORIGIN_BRANCH_LABEL
      git checkout FP_BRANCH
      git merge FETCH_HEAD
      (stash omits but here you make changes and must do “git add fpath” for each file. woohoo, so user freindly, NOT!)
      git commit
      git push origin HEAD
      (now, sometimes you’ll have various problems since this won’t work. MOST git users end up deleting everything, doing a new clone, and redoing there changes. Watch them. This is the type of sgit people are doing with git. But, you can get things working with some git fetch and/or git pull – at least in the case found.)

      • Huh. This thread has always been a rich source of bullshit, but recently it has crossed straight into tinfoil-hat-land. I look forward to the first report of how someone got rashes from using git.

      • @tisza: You can’t expect the positive sides of git adoption to show up in a thread which is the first google hit for “I hate git”.

        On the other hand, git adoption is strong enough that the dark sides of having a mostly implementation motivated user interface with quite a few awkward workflows show up more and more. And these are very likely to show up here.

        So you should not be so fast to insult those who made negative experiences with git. I also contribute to a project where git costs quite some time again and again because the necessary actions for what we need are needlessly complicated and require googling everytime. This wastes quite a few resources (several hours per year for a team of ~6 people).

        Was git an overall win over SVN? I think yes. We are no longer dependent on a single server. Due to having a transparent bridge to Mercurial we can also reintegrate anonymous development into our main repositories with ease. That’s a big conceptual win. That we do most things over github is a big conceptual drawback, though: We always have to ensure that we regularly pull all history from all clones, so we don’t lose development when a user decides to delete the github account.

      • I don’t think @tisza was ‘so quick to insult’. He was responding to an incoherent post that lowered the tone of discussion of what has been, by and large, a well-considered discussion. I am genuinely interested in the problems people have with git, as I am introducing it in my workplace. So I am very grateful when people take the time to explain the issues that they have had with git.

        However in your post you allude to “the necessary actions for what we need are needlessly complicated and require googling everytime”. That doesn’t help me understand the issues that you’ve encountered or how they might apply to my own workplace.

        You continue tantalisingly: “We always have to ensure that we regularly pull all history from all clones, so we don’t lose development when a user decides to delete the github account.” This is about github rather than git, I suppose, but how is it possible for users to delete github accounts?! That sounds like your project is set up wrongly but I would be interested to know more.

      • @sfkleach, GitHub’s authorization control is extremely poor. While users are not able to delete repositories if the configuration is sane, there is no way to limit force push access; if someone has it for some branches (which is usually needed when people work together, e.g. to rebase a feature branch shared between two coworkers), they have it for everything, and if they accidentally rebase master, it is not even logged, nor is there any way to restore the lost commits, unless someone has them locally. It is quite easy to lose work that way.

        Not really a problem with git, of course, and supposedly GitHub Enterprise has more granular access control, so leaving this out of GitHub was probably some sort of business decision.

      • It’s a fair comment that git doesn’t build in authorisation and arguably a weakness. But I would be inclined to say this an issue with GitHub rather than git (and the reasonably well-know workaround for GitHub is to use forks). I haven’t personally configured gitolite but it seems to include branch permissions as a key feature.

        Your point about rebase being a good way to screw up is valid regardless of whether it’s one person or several people. And there are some very good ways to get lost in git. I recently got in a muddle doing a demo by doing a ‘revert’ rather than ‘reset’ – which was a classic terminology blunder. I used the word ‘revert’ while speaking and the rest was … unimpressive. It took me a while to untangle myself.

      • @arnebab, this thread started with some reasonable (if overplayed) usability concerns, then turned into “I did this stupid thing and git didn’t stop me!” (it is of course a valid philosophical stance to prefer tools which have a dumbed-down instruction set and do not allow anything nonstandard because there is no way to tell whether it is stupid, but if you nevertheless choose a tool with a completely opposite philosophy, no sense in blaming anything but yourself), and finally descended into conspiracy theory realm. Git not being able to commit files which have been edited from a different time zone, or merge back a branch if a comment was added to the same file on master, SVN being better at merging renames, etc… Had Max not been the only one commenting here lately, I would have probably assumed that he is mocking the blog author by making ridiculously over the top claims.

      • @sfkleach: whether to include the kitchen sink or concentrate on version control and let you deal with other tasks using tools specialized for those is again a philosophical issue (personally I would prefer the latter). gitosis, gitolite, gitorious etc are easy to set up if you need access control.

        Rebase in git is quite safe: you can use the reflog to restore the old state if you mess up. The problem with GitHub is that it doesn’t expose the reflog but makes it easy to mess up (and hard to even just verify whether you messed up). But that’s a business/legal decision, as I said, not a technical one.

        (git reset, on the other hand, is a major usability blunder.)

  164. One more. If you move a file to another package then it will show in git history but egit compare shows them as two totally separate files. Not sure if you blame the poor, out-dated compare support on egit or on git itself.

  165. Yet another! egit says “failed to push due to funny remote ref”.
    Well, that’s odd since the remote ref listed as an OLD branch and NOT the one just checkout’ed.
    Well, its not even an egit bug, its git itself (using the stuff downloaded from github.com for Windows)
    Here’s the command line example. Git, “Not only user-hostile, but also buggy”.
    136 git checkout EPIC_BLAHBLAH
    137 git pull
    138 clear
    139 git status
    140 git push
    141 git status
    142 git push origin EPIC_BLAHBLAH
    Ok, so, someone will say “you should have have done a “git pull”. Why not? Details:

    $ git status
    On branch EPIC_BLAHBLAH
    Your branch is ahead of ‘origin/EPIC_BLAHBLAH’ by 1 commit.
    (use “git push” to publish your local commits)

    $ git push
    ! [rejected] HEAD -> TAG-bugnumber (non-fast-forward)
    error: failed to push some refs to ‘https://accutname@stash.r.company.com/scm/stuffer-android.git’

    $ git status
    On branch EPIC_BLAHBLAH
    Your branch is ahead of ‘origin/EPIC_BLAHBLAH’ by 1 commit.
    (use “git push” to publish your local commits)

    EPIC_BLAHBLAH

    So, YES, you can MAKE Git work. But, WHY? Why not just use svn and save yourself headache after headache after headache?

    • Sorry, comment was filtered due to gt/lt.
      $ git push
      ! [rejected] HEAD -> TAG-bugnumber (non-fast-forward)
      error: failed to push some refs to ‘https://accutname@stash.r.company.com/scm/stuffer-android.git’

      – comment: why is Git pushing to another branch? I checked out from the one I want. It even told me “(use “git push” to publish your local commits)”? Someone will say “You should not ‘git pull’.” Why not?

      • TAG-bugnumber is an old branch. The same steps used worked for a month or so until last week. The only thing I know changed is a bunch of remote branches are being deleted as part of cleanup (more make-work you get to do if you use Git).

    • You haven’t really given enough information here to isolate the problem. But, at a guess, you are thinking that “push” pushes a single branch (the current one) but have not configured push.default=simple and are using a version of git earlier than 2.0.

      By default, git push tries to push everything in all branches up to the remote repository. But rather than trying to explain how many developers use git, I’d recommend just setting push.default (globally). This is especially important for “corporate use” where a number of people are pushing to some repository which is being maintained by an ops person or some external company, instead of a developer.

      Note that this also means being willing to have someone spend 10 minutes with each developer if they are using a version of git older than 2.0, to make sure they have a reasonable push.default (and/or have read the relevant git.config documentation).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s