What I Hate About Git
steveko.wordpress.com
steveko.wordpress.com
> The information model is complicated – and you need to know all of it. As a point of reference, consider Subversion: you have files, a working directory, a repository, versions, branches, and tags. That’s pretty much everything you need to know.
SVN's model is both simpler than stated here, but also much more complex to reason about. First of all, svn doesn't have branches or tags, it just has directories with cheap copy—tags and branches are just directories. The repository itself is also watered down pretty severely because the actual project directory is just nested in there somewhere with no formal locus. This idea of "everything is a directory" sounds simple, but in practice it's a architectural dead-end. The most obvious implication is that merging in svn will always be fraught with peril because a branch isn't a first-class citizen.
I used svn (and cvs before it) for much longer than git, and yet I never felt I had any clue what svn was doing under the hood, and the experiences I had over time instilled a fear of attempting to stray off the well-worn path of the most basic commands.
Although the learning curve was steep, and the CLI quite confusing, the git information model is actually much easier to grok because the primitives make more sense. After 6 months using git, I had a firmer grasp of the internals than I did after 10 years of cvs and svn. The idiosyncrasies of the UI don't really bother me because they are just superficial flaws that are easily memorized or looked up. The fact that I have the confidence to slice and dice commits to any history I can envision, with or without a network connection and remote repo, and do so with the reasonable confidence that I will never lose anything (reflog) make git the best VCS I can imagine.
Well, sure, but if I understand his intent it's to demonstrate that Git's not hugely superior in clarity to freaking SVN.
I don't think he's defending SVN, though I'd only be completely sure of that if he mentioned hg at some point.
Most of his list could easily be changed to be about svn instead. svn has a bad data model, svn has incomplete and poorly written man pages, in svn you need to run many commands to do simple things, svn has illogical command line parameters, ...
I remember trying to rename a file after 'svn add' but before 'svn commit', and it simply didn't work. Maybe that's fixed now, don't know. Or merging stuff when a file was renamed in one branch and changed in the other.
During my several years of SVN usage I have regularly driven SVN checkouts against a wall, where I didn't manage to recover them into a usable state, not any combinations of revert, update or other commands. This has never happened to me with git.
* "Unsafe version control", and then gives examples using -f or +<refspec>, both of which advertise their destructive nature. Yes, you can also go in with SVN and obliterate history too, using svnadmin dump and svnadmin load. Git's reflog will have your back when you make mistakes, as long as the mistakes don't get too old.
* "Power for the maintainer, at the expense of the contributor" Yes, most people write code on one branch for a long period of time. Git does this just fine.
* "Burden of VCS maintainance pushed to contributors" First of all, nobody says that contributors have to merge. That is a decision that each project makes. Plenty of projects have the lead developers merging in everyone else's work. Second, the reason this is even an issue is because merging is such a pain in SVN that most people don't want to do it.
* "Git history is a bunch of lies" Again, this is up to the individual project. Some developers like to work on six different things at the same time, and then they go back and rewrite history so that their six changes end up as six commits. The difference with SVN, is that these same developers would simply avoid committing until they're done with all six changes. Some projects expect rebased patches, some prefer proper merges. Worse, the author says that "filtering" should solve this problem, but doesn't propose how such a filter would work.
* Complexity of simple tasks: Let's try not to artificially inflate the complexity of the Git tasks. For example, the Git examples assume no commit access, whereas the SVN examples assume direct commit access. If you don't have commit access to an SVN project, how do you do it? You either use git-svn and mail them a patch, or you use svn and mail them a patch.
A recurring complaint seems to be that "git add" is not the same as "svn add". I don't see why it would be. It's not the same as "ssh-add" or "useradd" either.
Personally I know what all these things are, and again I'm quite comfortable with them at this point, but there was absolutely a learning curve, and I'm reminded of it every time I start explaining something to a more novice coworker.
Also, for the record I like git a lot. But it's not immune from criticism.
Git has a lot of wonderful properties, but it has horrible usability. Things like rebasing, remote branch tracking and push/pull, merge conflict resolution, stash management, and reverts are straightforward concepts! Once you grasp the concept of distributed VCS, those things should be a joy to use. But the standard Git CLI and most interfaces to it basically just drop everything on the floor and tell you to sort out the mess yourself as soon as something non-trivial happens.
This learning curve has no reason to be so steep. There need to be clearer explanations, better discoverability, and better interactive modes for all of the things I listed, and more. Telling people to RTFM just misses the point.
This is not to say that the OP makes a particularly coherent point. Just that the overall sentiment has merit.
> Telling people to RTFM just misses the point.
To be fair, most of these "git sucks" posts in the past have been people moving from svn and complaining that git doesn't do it the Right Way(tm) "like svn does." In most of these cases, it has boiled down to:1. I tried to use git like svn without attempting to do much learning at all and it bit me in the ass.
2. svn does things The Right And Only True Way(tm) and git doesn't, therefore git sucks.
3. svn has a command named 'svn <action>' and git has a command named 'git <action>' but they do different things. Therefore git sucks because (obviously) svn has the One And Only Correct Definition of <action> that 'makes sense.'
The other arguments amount stuff like:
1. I use mercurial all of the time and I don't understand how anyone can use git because of <filter-branch | commit --amend | rebase --interactive | etc> that allows you to rewrite commits. If people are allowed to rewrite commits, then obviously all developers using git do things like rewrite the X year-old commit that introduced the bug rather than creating a new commit to fix the bug. <Here is where I continue to rant about how scary the ability to rewrite commits is while demonstrating that I have little to no actual experience with git, or a single bad experience that I'm extrapolating from>.
In general, I find that I can empathize with people that get worked up over "git sucks" rants, because for the most part they either make no compelling arguments, or they bury a couple of compelling arguments under a ton of unstructured ranting about strawmen.
http://www.joelonsoftware.com/items/2010/03/17.html
He also happened to write a tutorial for mercurial that explains the same concepts. The tutorial is linked to at the very end of the article.
It's a pretty good tutorial. But to me the mere fact that there are so many posts on How-to use a tool that is basic in a programmers arsenal, tells me that DVCS are a solution that lacks usability.
Edit: appear to have annoyed someone with that comment! But do go on - prove to me how high intelligence means that you don't need to do hard work, which is the proposition of the OP.
I don't think anyone's said that, or tried to say it (least of all me), at any point.
As for it not being a proposition on the human condition - I mistook what he was saying, but then after it was clarified I understand what was meant. It was unclear to me what was being said - interestingly enough, that is the entire argument being expressed for the reason why git is "hard work".
I put in effort where it's worth it. Version control doesn't even come close to hitting the top of that list.
On the other hand, I can tell you we have almost 10x more downloads than we have svn commits ;-)
To commit any changes, you type in:
git commit -a -m "thing that I changed"
To branch, it's: git checkout -b newbranch
To switch back to the master branch, you just type in: git commit -a -m "changes made on branch"
git checkout master
To merge in that branch, should you so wish to do so, then you type in: git merge newbranch
What is exactly so hard about that?I tried Git but failed miserably with it. It could probably be attributed to the lack of quality tutorials at that time. I then thought, "Fuck it, let's try Mercurial" and stumbled upon hginit. That is one awesomely written tutorial. I use mercurial for my programming needs and find it totally intuitive to use.
I definitely found it easier than git, but that could be possibly chalked up to my bad introduction to git.
When I tried to learn Git (before Hg), I looked for tutorials but everything was all over the place and maybe they introduced too much too soon. Anyway, at the end of the day I find Hg good enough for my usage - init, commit, push, pull so far.
git does not work like that. It's like each command was cut in half and recombined differently, like interlaced video or something. It's all there, it's just harder to recognize.
The thing that people need to get through their head is that distributed version control is a whole different concept. There are some things it is great at. There are some things it sucks at. Centralized version control is great at some other things, and lousy at some other things too.
I am thinking for example that if you are going for a PA-DSS-certified application, git, particularly with the ability to rewrite history, is going to be a problem, but dvs generally will provide more problems in assuring the auditor that you can locate, trace, and take corrective action if someone introduces a security issue (perhaps intentionally) into your application. I don't see git really working in that environment.
On the other hand, if you have a lively project that everyone is experimenting with and you need to merge patches occasionally to create a stable release, yeah, it's much better.
For any given project, no matter how distributed the development, you will have a "blessed" repository, from which the official releases are made. The history of this "blessed" repository is made not rewritable, even if anyone can push new stuff to it. The config files and hooks can be made writable by only admins.
Or you use a maintainer model, where the "blessed" repository is not even pushable. A maintainer (or a group of them) chooses what he merges in.
I have concerns about git and used distributed version control years before git existed.
- Colleague #1 has become sort of comfortable with git but only after heavily customizing gitconfig and setting up a dozen or so aliases for the most common commands.
- Colleague #2 is a devops, lives and breathes inside the command line, and still uses a GUI instead of the cli for git.
I've read mixed reviews... I'm OK with git but am deeply displeased with how difficult the learning curve is for a casual user. I'd much rather that Mercurial won.
In essence, the more I learn, the less I like it, and the more convinced I am that it isn't what I need right now. Building accounting software there are certain things I need in a revision control system. These are:
1) revision control as audit trail. I need to know who committed a change and I need an audit trail on that. SVN isn't perfect here. I'd like to be able to audit changes to commit logs too, but that's pretty minor stuff.
2) collaboration among a smallish number of committers (right now maybe 4 active at any given point in time).
Folks have pushed git because it makes it easier for users to share modifications with eachother. That's fine, and it's a good point, but it isn't worth getting rid of a clear and reliable audit trail in order to achieve. To this end I suspect we are more likely to pursue a hybrid solution with all the complexity that provides (and indeed it is already partly implemented) than a pure git solution.
Allowing rewrite of commits is a problem not because developers might do it but rather because you can't show that developers didn't do it. If there is a question about whether a security issue was intentionally added to the code or not you need to have a clear audit trail. A basic principle of any audit trail is that your audit trails may not be overwritten.
An alternative (or additional) solution is to setup a server like Shawn suggests in this e-mail: http://git.661346.n2.nabble.com/Implementing-commit-signing-...
You can optionally GPG sign a commit/tag which, again, will be invalid if any part of the history is changed.
Disclosure: I occasionally committed something to Fossil.
Of course there was a typo in my previous post. I am "now" learning git, not "not" learning git.
I'm someone who is neither unwilling to learn, nor attached to how Subversion did things. And I dislike git.
Superficially, I dislike it because it seems very little thought has been put into giving it a coherent interface. TFA points out instances of this, and it's true: whether something is implemented as its own command or as a flag to another command sometimes seems to have been decided via dartboard rather than any sort of intelligent process.
I also do intensely dislike git's own man pages, which are the first thing I'd ordinarily turn to. Unfortunately, the concept of an acyclic graph has not yet arrived in that part of git.
I dislike the way git overloads "branch" with multiple meanings or, rather, forces end users to do so. Mercurial does a better job of this currently, and has built-in support for the most important case (bookmarks vs. branches, in hg's terminology).
I dislike the fact that every repository and every branch is on equal footing except for all the commands that work differently with a remote branch or require you to do extra setup before they do work.
I dislike the fact that side-by-side inspection of different branches requires me to jump through hoops, since git only wants me to see one branch at a time. SVN, for all its faults, at least got that one right -- I can actually see two different branches, at the same time, using tools that require no knowledge of anything beyond my filesystem.
I dislike the fact that even people who use git day in and day out still can't seem to agree on a workflow. And I'm not just talking about things like whether rebasing is fashionable this week, but very basic things like when and how to branch.
I also agree with the article's point about contributor workflow; git and GitHub are more complex for contributors. There's also very little that's "decentralized", since GitHub is full of canonical central repositories, which makes me wonder what we gain from pretending we're using the "D" in "DVCS".
And that's really just the tip of the iceberg.
The examples given weren't illogical. The author's examples were git pull, which he complains is a git fetch followed by a git merge... which is quite logical, given that to pull from a repository you must first fetch the files, and then merge the files into your repository.
The second example that he complains about git commit not commiting a file if it's not specified on the command line. This makes sense, as you need to explicitly add the files via git add - something the documentation makes clear. As one of the complaints is that the documentation isn't clear, I think it worthwhile mentioning that the git-commit man page specifically says:
The content to be added can be specified in several ways:
1. by using git add to incrementally "add" changes to the index before using
the commit command (Note: even modified files must be "added");
.
.
3. by listing files as arguments to the commit command, in which case the
commit will ignore changes staged in the index, and instead record the
current content of the listed files (which must already be known to git);
4. by using the -a switch with the commit command to automatically "add"
changes from all known files (i.e. all files that are already listed in
the index) and to automatically "rm" files in the index that have been
removed from the working tree, and then perform the actual commit;
The third example he used was that the shortcut for git branch and git checkout is git checkout -b. However, this makes sense because a branch doesn't populate automatically with any files and needs a checkout. Thus git checkout -b makes perfect sense.Perhaps there needs to be a git branch -c?
I also do intensely dislike git's own man pages, which are the first thing I'd ordinarily turn to. Unfortunately, the concept of an acyclic graph has not yet arrived in that part of git.
I think some of the opening descriptions are a little terse, but not entirely sure what you mean by the acyclic graph comment... I haven't been able to find anything obvious in the man pages that references a man page that then references the original man page... of course, I might have missed something!
I dislike the way git overloads "branch" with multiple meanings or, rather, forces end users to do so.
Could you clarify what you mean? Branches have only one meaning in git!
I dislike the fact that every repository and every branch is on equal footing except for all the commands that work differently with a remote branch or require you to do extra setup before they do work.
Could you clarify what you mean?
I dislike the fact that side-by-side inspection of different branches requires me to jump through hoops, since git only wants me to see one branch at a time. SVN, for all its faults, at least got that one right -- I can actually see two different branches, at the same time, using tools that require no knowledge of anything beyond my filesystem.
Can't gitk do this? Genuinely interested...
I dislike the fact that even people who use git day in and day out still can't seem to agree on a workflow. And I'm not just talking about things like whether rebasing is fashionable this week, but very basic things like when and how to branch.
I really can't see that's a valid argument. Some folks need to branch differently than others. This isn't just a git thing, the same can occur in SVN. As has been pointed out, branching tends to be discouraged because merging can be a regular pain.
I also agree with the article's point about contributor workflow; git and GitHub are more complex for contributors. There's also very little that's "decentralized", since GitHub is full of canonical central repositories, which makes me wonder what we gain from pretending we're using the "D" in "DVCS".
I disagree. The github workflow might be a little tricky, but as has been pointed out there are other workflows possible in git. git != github!
Does it? Pull and then merge is a common operation; it gets a top-level command. Create a new branch from the one I'm working on and check it out is a common operation; it gets a flag on an existing command. What logical, coherent process decides that in each case?
Branches have only one meaning in git!
Hence the "forces end users to do so". There are two very common ways people use branches: one is as a temporary place to do a quick bugfix, the other is as a long-lived place to do a major rewrite or refactoring. With respect to the history of the codebase, these have very different implications, but semantically are the same type of thing in git.
To pick on Subversion: when you had a long-lived branch in SVN, sooner or later you'd merge it back into the mainline... and then what happens? You want someone to be able to look at the repository and see that something major happened here and easily watch the progress, but you also want a way to say "this is done and merged". This required inventing a convention to indicate that -- in SVN, typically the finished branches would go in an "attic" directory.
In git you face the same problem: making a temporary branch, doing the work, merging and then deleting the branch is what you're supposed to do in git. But for those long-lived major branches, you need to invent a convention (commonly, tagging the merge point) to indicate that they're done.
I mentioned Mercurial because it has two different concepts for these things: the ephemeral deleted-once-it's-done line is a bookmark (which is pretty much exactly equivalent to a git branch, in that it's a named head that moves as you commit), and the long-lived major branch is... a branch. Which has additional semantics to indicate things like being finished.
This means that in Mercurial you don't have to invent and re-invent ad-hoc conventions to handle common development patterns, while in git you do.
Can't gitk do this?
Every time I say I want to see two branches side-by-side without invoking the VCS, someone says "well, here's a tool that invokes the VCS to do that!" Which shows a lack of reading comprehension.
Some folks need to branch differently than others.
Sure, but why isn't there a clearly-documented "most projects will get along fine with this" workflow? Or, rather, why are there dozens of them? We've had VCS tools for long enough that the best practices for common cases are out there.
The github workflow might be a little tricky, but as has been pointed out there are other workflows possible in git.
Oh, there are. But git + GitHub has been relentlessly hyped as an Oatmeal-ish fantasy of unicorns farting rainbows onto a field of lollipops, so that's how people actually end up using it, and so it's valid to mention that it's a more complex workflow for contributors since it is a very common case and becoming more common.
I'm guessing you check out a branch to a particular directory, and another branch to a different directory, then do a compare?
You could create a directory, stash you uncommitted files, then checkout the branch ad do a recursive copy to the directory you want to do the compare in. Then rinse and repeat for the next branch. After this checkout the original branch you were working in and retrieve the stash.
You could easily script this.
svn co remote_repo_path/branches/bugfix bugfix git clone -b bugfix ./local_repo_path bugfix
It could be simpler if you removed the trailing target folder name (but git would name the checkout according to the repo name, instead of the branch name).
here’s a diagram illustrating the commands a typical developer on a traditional Subversion project needed to know about to get their work done. This is the bread and butter of VCS: checking out a repository, committing changes, and getting updates.
make clear that when this author says they're listing ten things git does wrong as a version control system, but what they're listing is ten ways git isn't Subversion, and I'm sorry, but maybe if instead of writing blog posts about how a tool's user interface wasn't like what you unfairly expected of it, you actually learned how to use the tool, you'd be using it right now to make something awesome.
What I'm saying is, I think I'd rephrase
Number 1-5 are mostly "I don't want to learn new things"
to
Number 1-5 are mostly "I'm going to blame my tool for me refusing to do the bare minimum to learn how to use it"
The OP already pointed out that the official Git documentation is bad, bad bad. So, already it's not just "RTFM" but "Google around for a decent Git tutorial and hope you pick the right one." Great.
Add to this the fact that the Git commands are simply poorly designed. Yes, it is possible to understand what they do after expending a significant amount of time simply learning to think like Linus, but why should we have to do that? I refer you to the gitref.org entry for 'git reset':
git reset is probably the most confusing command written by humans. I've been using Git for years, even wrote a book on it and I still get confused by what it is going to do at times. [0]
This is not a problem of people not wanting to learn DVCS concepts. This is simply people who don't want to jump through a set of arbitrary, confusing, and completely unnecessary mental hoops in order to get to the DVCS concepts they wanted to use.
[0] http://gitref.org/basic/#reset (gitref.org is maintained by GitHub)
I have a hard time believing that there are scores of software developers out there who have learned their craft enough to want source control but are somehow overwhelmed by the basic task of finding a good Git tutorial.
The real impediment that I've observed is developers that certainly could learn Git but don't because they don't see it as a good investment. That's where they're so, so wrong. Git is like power tools for your code. If you embrace and learn it, you'll be much better off for it. Yes, SVN is easier. It's also a lot less powerful.
And there's always Mercurial, which is very similar to Git and addresses some of the confusing-API criticism.
Distributed version control is not as complicated as this.
The whole time I was thinking if I'm stupid or talentless.
The discussion here showed me that git is indeed far from perfect.
Ummm.... when you don't know the tool, you're not in a good place to judge what a 'good' tutorial is. This is the same reason we've got generations of bad PHP developers out there - they can't tell what's good or not.
"scores of software developers out there who have learned their craft enough to want source control"
How many people 'want' to learn source control, and how many people are told 'this is what we use here, go learn it'? I suspect far more of the latter, especially with git. People would not flock to git purely based on the documentation quality. Further, I suspect that had git just been written by some random dude off the street with no major project behind it, it would have never taken off. Using it for Linux kernel work has ensured a sizeable number of people are going to have to use it, whether they like it or not.
But like leaning Git, earning your education will pay off. Does that mean Git is without flaws? Of course not. And if you want to work to improve it, and release a better version, go for it. But anybody that sticks with SVN and refuses to learn modern DVCS is not somebody I'd hire.
Maybe this is a problem on IT-department, line-of-business teams (where most software developers work) but if Bay Area tech companies are a leading indicator, a big majority of Engineers I work with use and love DVCS's like Git and HG and there's not this groundswell of resistance.
And while this isn't related to my previous comments:
To anybody who has tried Git and ended up "losing work" because of a misunderstanding of the commands, let me assure you: It's actually a lot harder to lose work than you think.
Anything you add to the Index (eg git add foo.py) or commit is stored in the Reflog (which is just a DAG). The reflog is garbage collected periodically -- see below for details. Within that window, you can recover any lost state from the reflog.
So how long does Git keep things around by default?
Intermediate products of conflicted merges - 15 Days
Unreachable commits (do a git reset --hard HEAD~1?) - 30 Days
Intermediate products of a resolved merge conflict? - 60 Days
Everything Else? - At least 90 days.
It deleted 95% of branches locally and on origin without leaving much of a trace, or any way to undo (well, none that i know of).
Good thing I had a clone on a machine at home, so I drove home, made local branches for each remote branch and then pushed each.
So yeah, there might be a way to get that stuff back, and I don't even have experience with non-DVCS, but the lesson I learned a long time ago with darcs is that you better have up-to-date off-site backups of your repositories, never trust yourself or your DVCS too much.
The upside is that keeping backups is easy, and good practice anyway, so if you're not doing it yet, don't wait.
Running jekyll without parameters compiles the source in the current directory, putting the output either in $PWD/_site, or wherever the config file for the project says.
I was in the parent directory, and thought I'd try to run jekyll projectname rather than having to cd in and out of the project.
The end result? It tries to compile the project in the current directory, writing output to the directory specified. As an added bonus, it completely nukes the target directory, including the .git subdir. And to add insult to injury, $PWD didn't even contain a valid project, so it error'd out immediately after wiping out the entire source.
The morale of the story: Always keep offsite backups.
You wouldn't hire me. I'm OK with that.
I use git (required for an assortment of OSS projects), but for my own work, at at work, I use SVN. I'd never willingly choose git.
It's complex, involved, powerful, and incredibly distracting from the actual thing I want to do, which is write software.
The minute someone says something like this, my eyes glaze over: "Anything you add to the Index (eg git add foo.py) or commit is stored in the Reflog (which is just a DAG)."
Not because I don't understand git's fundamental model, or I'm unfamiliar with a DAG, but simply because I SHOULD NOT HAVE TO CARE.
My job is to write software, not operate heavy revision control machinery to some arbitrary level of dvcs revision control fetish perfectionism.
I don't want to hide my work from my coworkers, I don't wind to hide my work history from my coworkers, and I don't want to maintain wildly diverging branches (the cost of branches is primarily found in code divergence, not SCM headaches). Git isn't for me.
That's fine and all, but I want to work with craftsmen. People who give a shit about their trade, love their tools and relish in the oportunity to learn something that will help them do their job better. I wouldn't hire you.
And craftsmen are picky about their tools.
Git has a terrible, terrible, command line UI. It's entirely possible to do distributed source control with an easy command line interface: Mercurial. I've never had trouble teaching people how to use it, and I've almost never had to sit around scratching my head, wondering what arbitrary set of command line arguments I need to pass to it.
Maybe git is the most powerful chainsaw ever devised, but the fact that so many of its users are either covered in bandages or fastidiously studying man pages and googling proper usage so they don't end up covered in bandages is not a good sign.
I also think its worth pointing out that many of the people here complaining about Git (including the OP), use it very frequently. These are the people who have bothered to invest the time in learning the tool and hate it anyway.
The job of a SCM, in my opinion, is to be as invisible as possible. Record my commits, and then stay out of the way of what I'm really here to do: write code, architect systems, engineer products.
Futzing around with an overly complex revision control system doesn't help me do a better job.
This is also why I switched from Linux & BSD desktops to Max OS X. I can still write an XFree86 config file by hand, and the fact that I spent time and effort learning this is mind bogglingly awful.
I tried hg for a time, which was much better, but in the end I went back to bzr (hg confused me in merging, with it thinking that "what is this three-way vimdiff window with all the colors? I'll just leave this and examine the files one by one" meant "okay, everything is correct now"). It interoperates with everything, and it's the sanest of the three, so why wouldn't I use something that just works, rather than fight my tools?
git has well-documented and simple commands to perform these operations (except if you're talking about reverting some files in a commit, that's not a thing git does afaik? though it might, but I doubt it would be straightforward).
If you're confused by hg & git and just wound up back where you were it sounds like you just didn't have the patience to learn a new tool. Either that or you failed to evaluate what each tool did before you tried switching.
I don't think git's CLI design is that bad, but the commands for quotidian usage are hidden among a large and confusing array of commands for which serve to make git more powerful for the experts. This is also where the manuals are confusing: all the commands are listed, and beginners don't know where to start. It's like a woodwork hobbyist walking into the workshop of an expert carpenter and wondering where in the hell the hammers are.
As for subversion, try using it for branching and merging many parallel versions of code for very long and you'll welcome the arrival of git like that of Jesus into a leper colony.
Also, due to inconsistencies in how commands take branches, I sometimes realise I have a branch called 'origin/stuff', when I meant to do something with stuff on origin. It's also hard to find which branches are tracking what. Of course, you can find the options to do all these things. But there are just so many little things to learnt.
The fundamental question is, does the complexity of git come from the power it offers over svn, or does it come from the most terrible UI I think I have ever seen on a command line tool? I think it is the second.
I still use git every day, but I think it is putting usability by less computer-savvy users back years.
It's the opposite, "git push" pushes all branches and "git pull" only pulls the current branch. I think it's because push will only do fast-forward merges while pull will do any merge, and that could require a working directory to exist (but why not make push just push the current branch?)
The problem this causes (for me) is that if I have commits in other branches, 'git push' will fail (as other branches can't be fast-forwarded), but 'git pull' won't fix it. Of course, I can get around it, but it's annoying.
`git config --global push.default upstream`
The relevant docs (droplr'd, since you can't anchor-link into the online manpages): http://d.pr/Rlqn
What version of git are you using? "git pull" definitely just pulls the current branch. It will fetch all the other remotes, but will only pull the current branch.
See the new destined-to-become-the-default "simple" mode for "git push" in these release notes: https://raw.github.com/git/git/master/Documentation/RelNotes... .
This is exactly my feeling. Sure, I can, but why should I? I just want to get work done, not become a git fanboy.
The place I work at compared DVCSs and chose mercurial, and I'm very happy, I've never looked back, and heres the point... I really have no understanding of HOW mercurial works. It just works.
Then I take it you'll agree C++ is better than C?
The whole post is about a system that is badly designed or implemented, making it unnecessarily complicated to learn and use. Not wanting to have to deal with unnecessary complications is not the same as not wanting to deal with necessary complications. People unfamiliar with good UX design can't tell the former from the latter.
For example, last month I was at a meetup, and had to help someone who was contributing to an open-source project. She had been following the project's instructions on using git, but was stuck. It turned out that she had hit a snag in the middle of a multi-commit patch that was applied with "git am" and as a result, her repository was in an intermediate state and the usual commit, add, reset etc. commands weren't working. I helped her back out to a clean state, but it took me several minutes of scouring documentation to do it, and I consider myself proficient with git. If I hadn't been there, I expect she would have given up on the whole thing, and all because git has some bizarre interactive processes that leave your repository unusable while in progress.
I think it's undeniable that git is unfriendly and obtuse at times, and the people who think otherwise are just examining it too close. They have mastered it, they see all of the justifications for each quirk, and because of that they can't see the big picture, which is that it is extraordinarily difficult for a new programmer to pick it up and be proficient.
I don't understand this attitude. Why can't our tools be so easy to use that you don't need to read the instruction manual?
Conceptually, there's nothing that difficult about using git. I have some files that I want to be versioned. Yet, the commands are inconsistent and any non trivial operation requires consultation of a variety of tutorials.
Why do we have to settle for this? Why can't the tool be internally consistent?
1. Temporarily forget everything you know about every other system, and imagine they didn't exist, and that you have to solve this problem yourself. How might you do it?
2. Read Tom Preston-Werner's "The Git Parable" (http://tom.preston-werner.com/2009/05/19/the-git-parable.htm...).
Read it very carefully - the minute you start skimming, you'll start filling in gaps using your Subversion knowledge and be lost again. If you really want to understand, read this aloud.
Ignore them at your own peril.
"Not wanting to learn new things" is very different from "Not wanting to learn needlessly complicated mess of new concepts because nobody bothered to clean up the conceptual spaghetti".
Which is the case here.
My pet peeve with Git is that it stopped once it supported Linux kernel-type projects. If you are working on anything other than that it is likely that you are going to run into all manner of non-text resource files and Git sucks at helping you maintain these. Case in point: Graphically intensive iOS apps.
More like overcomplicated things. Git can be made simpler.
* "Git history is a bunch of lies"
These come up time to time. If you need safe Git history, you're supposed to sign your commits with GPG. Git has built-in tools for that. Linux kernel and many other major projects use signed commits. In addition to keeping the repository safe from changes in the history, it will also protect you when your git server gets hacked (where Subversion will fail).
If I read one more blog post that brings this up, I will cry.
What comes to the squash/rebase/rewrite history part, it's a good idea to not commit any revisions that do not build and run to your master branch. If you push a revision that doesn't build, you'll have a harder time doing "git bisect" (you can skip broken builds, though). It's a good idea to squash and rebase before commit to master. Use git merge --no-ff if you want a merge commit in.
i.e. just take a smart undergrad CS major and record their screen (& audio) while they try to figure out how to use it. I think this would definitely turn up some tasks within it that are way harder than they need to be. Do people really feel confident that learning git is a smooth process, not involving a lot of swearing?
The answer you mostly hear when complaining about programming tools is that you need to toughen up - yet startups are founded on the idea of not doing this to their clients. Making processes super easy for clients is a good thing, and we should gather information, find the common problem spots, and fix them for our own tools! We shouldn't just keep insisting that the customer (programmers) needs to toughen up and learn (as the default answer, anyway; some things really are hard)
Why isn't there user feedback tool for man pages, where it asks "Was this information helpful to you?" every time you use a man page? I bet the success rate would be pretty low.
In general why isn't there any information about which man pages are good and which are terrible? They just seem frozen in time. Compared to the analytics startups get about their customers, info about man pages is nonexistent. Yet there are probably ones out there which would be rated "useless" 99% of the time, and have been for 10+ years with no change.
Maybe we should invent a new model that combines open source with paid incentives for user desired changes. Let's say User A uses Gimp, sees something that could be simplified or added. He can't program it himself but what he can do is describing the feature he wants, possibly with screenshots or even an interface prototype. He then auctions this on a marketplace website. Other users can upvote or even chip in to A's auction such that the probability of a good developer implementing it rises. Developers have their profile with reputation, possibly linked with their stackoverflow reputation. The change gets implemented within a branch of gimp, installable by anyone using a modified package manager. If the maintainers of gimp like the change, they can merge it in such that everyone profits - the number of user downloads being a good indicator that the change is desired.
I will caveat everything by saying I have drank the Hg kool-aid and will be drunk for some considerable time. It wasn't that it was SVN-like, but as I explore more complex features on my own, my hand isn't slapped in the process. I've hosed repositories in Hg and SVN. I've fixed Hg repositories from codeplex that seem eternally broken given that is the "authoritative master". It didn't take any research at the time but I couldn't recall if the knowledge was entirely latent (i.e. discovered previously) or I had researched it at some point in the past to bring it up in the future.
I'm of the notion that if you can jump to any DVCS for the most part you're doing an excellent job. It doesn't hurt that there's hgsubversion or hg-git to make transitions easy but even the more obscure DVCS' are a leg up. I don't bash Git on some crusade, as I look at OSS projects and realize if they use it I probably should too at some point but the barrier to entry is inherently steep. I look to articles like this posted to hopefully stir interest in fixing the usability problem and it's extremely comforting to know that so many people share that it most definitely has a usability problem. I'm not the only derpy one here apparently :>. I really want to learn Git but I definitely do not want to be tasked as the Git-guru of my small developer team. We use a paid hosting firm that only has svn or git to choose from and I can get away with pushing people towards Hg with hgsubversion much easier than playing tech support.
Ignoring the unnecessary parts about GitHub, he hits the nail right on the head with:
> Git doesn’t so much have a leaky abstraction as no abstraction. There is essentially no distinction between implementation detail and user interface. ...Its weakness is the complexity of simple tasks.
I swear, someone needs to invent a Git-wizard program. Interactive with a wizard-like interface, it will walk you through all the common kinds of tasks, even if they're fairly advanced, explaining all the ramifications along the way.
I haven't seen any programs like this -- all the GUI interfaces to git basically just translate to command-line commands, instead of trying to help you intelligently manage your workflow.
I don't think it would be easy to write a wizard interface like this -- it's a UI designer's worst nightmare -- but it would certainly help.
It's a workflow level abstraction over git operations.
Sounds like a great idea for making one type of workflow easy. The great part about Git not having an abstraction is that it supports almost any workflow. You can choose what flow is right for your project.
Which is, by the way, why the documentation is not task-oriented, it's data-model oriented. The same command might be used for two completely different tasks in two different processes.
Other tools that aim to make the basics for committing easy do so at the expense of implicitly supporting only certain workflows. Think of something like Perforce. You don't enforce your process with Perforce, you choose your process so that it will work with Perforce.
Because there are a lot of different kinds of workflows, and I don't even know how you'd begin to organize them. I mean, maybe it's not even possible.
It would just be nice if it were more possible to "ease into" Git, rather than feel like you have to go through the equivalent of a college semester learning it.
This is the point where I think it's appropriate to link another front page article: http://news.ycombinator.com/item?id=4338845
I've learned Git about the same way I've learned *nix systems and programming languages in general: piecemeal, a step at a time, on a largely need-to-know basis. It's been 4 years now and I feel like a complete novice, but I rarely need to do anything other than (1) synching local with remote repo, (2) committing a change, and (3) using a feature branch.
But the mere fact that there are so many How-to's on Git is an indication that is not an easy to learn system. But it should be since is one of the basic tools of a programmer. Or for a car mechanic how many manuals are there on how to use a wrench? For a doctor how many books are there on how to use a stethoscope?
So I don't think that you can discount the cultural factors for our familiarity with hand tools. Certainly even in India, even in 1906, you wouldn't have had to teach a repair man how to use a wrench. But you would have to teach the engineering student. That's a bit of a humbling thought.
Things like detailing the github process and blaming git just does not work for example.
Blaming additional git features that svn simply does not have.. is also nonsense to me.
Finally, you CAN rewrite history in svn, its just extremely painful. In git it's not and.. its a good thing. I prefer USEABLE history than trashy commits. And don't tell me its about having proper devs making commits. As pointed out, you get external commits in git. You can't control them without refusing them and then what? In svn you don't even have the possibility to refuse them.
Don't get me started on how svn is way more about the maintainer due to this...
Pretty much all of the points here are things I love about git.
I'd personally hate working in this author's ideal repository: too many people with direct commit access, no tracking of feature branches, messy merges, noisy history.
I regularly use the history as a view of what others on the team have been up to and to find when bugs were introduced. If many people are developing on the same branch, rebasing makes the history so much easier to read than having to parse merge commits and trying to mentally reconstruct the state of the individual developer's code base before the merge.
Yeah the other day I got into an extended debate about rebasing with another dev who just didn't get this. He maintained that it should not be possible to modify history because it all may be relevant later. I rebutted with a question: do you want a commit every time you type a character in your text editor? Version control is just another tool for code craftsmanship. You should strive to make your commits as atomic and well-described as humanly possible. git-add -i and git-rebase -i are tools that allow you to approach a more perfect history.
Having a single atomic commit to "add feature x" is a lots cleaner when you're git blame'ing then git show'ing the commit, as you get to see the whole picture, instead of a log message like "fixing typo" and a 1 character diff.
That said, this should definitely be done off on a branch, and there's no reason not to have multiple useful commits on a branch merged in as such, but trashy typo/forgot to add X style commits are completely worthless to someone looking back at history
Meaning you could expand a the merge, see the branches that were merged into the branch, and the individual commits made on that branch.
I don't get it. I want a commit every time I say I want a commit, not upon arbitrary criteria the software decides for me. And I want that commit to be irrevocably and permanently immutable, because I said I wanted it and because it might be relevant later. What am I missing?
If I want to work on some code locally, I might want to experiment and break things, and in the process of doing so I want the ability to commit and have the safety net of version control. That said, a lot of those experiments might be garbage, and I don't want to send garbage to my co-workers when I make a pull request.
So instead, I splash about in my local repo and make tons of commits and screw around with my experiments until they're fully baked, and have tests, and comments and docs and so on. Then I can use rebase to clean up that mess and present them with something atomic and contained that makes clear what I really wanted to publish. The garbage can be tossed from the history or it can be kept around locally, but at least I'm not asking my colleague to trudge through my own thought and work-process.
Does that not sound like a worthwhile feature? If it doesn't that's pretty cool too, you don't have to use rebase at all. Feel free not to, Git works fine without it.
When you don't want to revoke or mutate a commit ("irrevocably and permanently immutable"), you don't tell git to revoke or mutate the commit and it won't revoke or mutate the commit.
When you fucked up history and you want to change it, there are some simple git commands to do this and some very, very tedious svnadmin commands to do this.
Some of us fuck up history and want to change it. Some of us don't. Git serves both of us well. Subversion only serves one of us well. A lot of the time we have to use the same version control system, because we want to collaborate.
In that sense Git has stronger support for immutable commits, since rewriting published history will actually cause everyone downstream to stand up and notice.
If someone depends on your "mutated" commit, they will notice that it's gone, and you can deal with the issue.
The most common use for rebasing and commit editing is to make commits actually sensible.
Huge end-of-the-day commit-all-my-work chunks do not benefit anyone. The index and rebasing allow you to create commits that make sense, regardless of the state of the working tree. In subversion, this is a painful, dangerous and error-prone operation that involves manually using diff and patch. Git frees the developer from having to worry about when to commit.
In practice this is what happens when you share your commits with the world (through push or someone pulling from you). As long as some commits are only in one computer git lets you happily nuke them, but why should it be otherwise? No one can force you to publish your commits anyway, you can always make a new clone and rewrite history there...
(the tag can still be deleted, but just to show the convenience added)
> In svn you don't even have the possibility to refuse them.
Too true. One thing we did to try to fix the trashy commit issue was to mail out patches of each commit to a team mailing list. That allowed 2 things to happen:
First, just seeing your trashy commit next to a commit to which someone has payed attention motivated you to be a little more careful next time. If you're just sending your commits into the void you behave differently than if you know what you commit will have a bunch of eyes on it.
Secondly, anyone on the team could just reply to the email and suggest that it be split in 2 commits next time.
Our whole department (>100 people) switched as part of a move towards decoupled development/continuous integration, we used perforce before. Luckily there were three people with excellent git knowledge who could answer all questions so this helped a lot.
However, I find myself relying on stackoverflow/google for some not-so-common small use cases where a glance at the manual just doesn't help (find all changes in local branch not in upstream branch x?). Also, the git commands and their options are sometimes not very logical as the article mentions (i.e. git show vs. git blame, the first needs the syntax "branch:file", the second "branch file", why? Small things like that take away from the beauty)
git is powerful and I prefer it to perforce for it's possibilities, but I think tools like mercurial are a better DVCS which just didn't have enough hype at the right time.
And there are very high costs to heterogeneity in this world. Using a weird SCM means that every new contributor needs to learn a new tool and new workflow, and that hurts. Using the one that "everyone" knows is a big advantage to projects.
And git is good. Not "the best" perhaps; and undeniably ugly in places. But it's more than good enough. And the existence of a community like github make it, frankly, better for new users than other options.
Windows support was a big deciding factor.
Difficult to take what you say seriously when you make comments like this.
That having been said, while I wish git were easier, I can cope with it. I can't cope with both git and mercurial. I haven't got the brain capacity to remember how to use both of them without them blurring together. I want to standardize on one or the other. And once I ask which to standardize on, git wins by simple market share. That's why I ended up choosing it over mercurial.
The power of Git is its distributed nature and the fact that you can maintain local commits. When you have a single remote repository that everyone commits to, then sure, it's really easy to do things (have fun maintaining the ACL and merging any changes contributed by anyone outside the committer list via patch). If you think "it's really easy to branch" is the primary reason to use Git, you're using it wrong.
that's actually the power of any DVCS.
It's unfortunate that git re-uses some verbs from cvs/svn with different meanings, but is that really such a big hurdle?
And I'm always surprised to hear complaints about git's user interface. I find the command-line interface far friendlier than others: auto-paging, colorized output, text hints of what I should do next, and fantastic tools (like bisect) in the same package.
And looking through my bash history, most of my commands don't use any options (the biggest exception is git commit). Possibly this is because I do most of my git interaction through vim-fugitive (and I have aliases for commonly-used complex commands). But I think it makes more sense to have a smaller set of commands that are logically organized (rebase mangles your history, reset re-aligns based on your history, ...) than a single command for every function.
That said, if you're calling yourself an engineer, you've worked at a Git shop for over a month, and you're still complaining about how "hard" it is? I have absolutely zero sympathy. You're being paid twice the national average to do a job that's supposed to be mentally difficult. You use version control every day. Stop whining, learn to use your tools correctly, and stop subjecting the rest of us to your crappy, disorganized commits.
Git makes you believe it's lots of small little utilities that work together.
Far from it. Git relies on Perl or another scripting language, not to mention it's reliance on curl.
You cannot run Git without these other sizeable programs.
I can make static binaries of RCS, CVS and SVN no problem. CVS uses SSH. No silly SSL and the certificate mess. I value the simplicity.
Mercurial (which seems to be a favourite among connoisseurs of versioning systems) relies on a Python intepreter, but it's reasonably contained to a single Python script; no installation required. You point Python at hg and it works.
Of course, it's been said that most of the time people who ramble on and on about these systems and their esoteric features do not need the advanced features. They rarely use them, except as points in a debate over which versioning system is "the best".
Still, tools like Tower, Smartgit and Github for Windows, especially Tower, make interface to Git less painful.
With time, the interfaces to Git workflows can only improve, whereas what can you do with SVN?
That said, he may have a point about (branch &) merge message management in Git. Perhaps this can be improved closer to git with git extensions, e.g. implementing some sort of ranking and filtration system. Related to that is users should not really have to change the structure of the VCS itself just to filter messages.
hg revert bla.txt
git ???
... and I would still have to google for it (it's something with HEAD iirc). Its usability is atrociously bad and I don't want to spend time learning some badly designed cli interface when I can focus on more important things and use tools that make my life easier, not harder.git stash is hg shelve. Don't know about cherry picking (I've never needed it).
Anyways, the argument I'm making is not "which tool is more powerful" but "which one is easier to use while being powerful enough". For me that is Mercurial, hands down.
Rebase: Oops I committed something I shouldn't have. Must be done BEFORE you push. My favorite is git rebase -i HEAD~<n>, where n is usually something small like 5. You'll get a vim-like view where it lists each of the last n commits by hash and message. Delete the line for each commit you want to remove, save/quit, and git merges out those commits. Of course be cautious here because you can lose work completely.
One more I like in the same vein, git commit --amend. For when you did a commit, and forgot to include something. This commit will just be added to the last.
Or hg qnew -f, which I personally prefer.
But generally you want the opposite defaults for small projects/number of users. For example you do want tags pushed by default so every sees them. This places a large learning curve on the small scale projects and users. Remember that most users will be perpetual intermediates.
My analogy is that git is like a sharp knife. In the hands of an expert it can produce art, but in the hands of others we get blood. Some of the responses here are marvelling at the sharpness and what can be done with it, but are missing the point that others end up bloody!
On the other hand, one of the things I hated most about svn is that it doesn't abstract away the remote repository details at all. To do something as simple as check out a branch you have to type in the full absolute url to your repository, since a branch is basically a different folder higher up in the hierarchy. Talk about a leaky abstraction.
The abstraction between version control tools and the remote server(s) you back everything up on and the power of git's underlying model are both such big wins that I really can't get too worked up about the syntax.
The idea that there are "git faithful" is a sign of how immature (in every sense) the software development field is. Masochism and complexity-worship seem to blight our field(not necessarily referring to git, which I'm not qualified to comment on)
And the benefits are compelling. Enjoy the amazing power of committing early, and committing often. Being able to revert to "10 minutes ago" is so freeing when trying out a refactoring idea. And being able to "uncommit" the last X commits to recommit them in a different order and with cleaned up messages and structure before sharing with colleagues... amazing.
All the quibbles about syntax really miss the point and the power of Git.
In practice however, I've found a force push can be useful. For example, we once had a dev push code to our deployment branch which wasn't in fact ready for production. We could have just reverted all the commits which were added, but this would be messy and make merging again later painful. Instead, just `git reset --hard` to before the merge and force push.
If you understand the implications of rebase and force push, you shouldn't have to worry about losing data.
Git maintains what's called a "reflog" to help with this. It's a record of every place that every ref has ever pointed in your repository. Try it: `git reflog master`. You can even see when you did pulls, and what they merged in.
The only truly destructive thing you can do to your git database is `git gc`.
And of course we should expect garbage collection to be destructive of information that is not garbage?
Didn't know that? Just read the man page. Whoops, it doesn't actually mention that, but it does mention that it may happen automatically at times.
So only clever people like you know archaic undocumented side effects of git's inscrutable design, except nobody ever really knows the full story because there is so much unnecessary crud to learn in addition. Clearly more can be destructive than gc if gc can be executed by other commands and triggers by repository state.
I do not think one can do this accidentally:
git gc --prune=2012-08-05
11. Completely different concepts for the same commands as other SCM systems.
Case in point: Checkout. In every other system prior to git, going as far back as CVS in 1986, checkout meant grab a remote repo and copy it locally.
In git, it suddenly means to switch branches in a repo you already have. The real "checkout" was renamed to "clone".
Why not use something like "switch" instead?
That's nearly 20 years of muscle memory everyone needed to relearn because.. why?
Git add and SVN add do completely different things as well.
Was it simply not thought of that people who use git would be switching from another system at the time, very likely to be either svn or hg?
Essentially, a checkout in git is to checkout files from a particular branch into the current working directory. And that branch is actually in the index, which I would really call the repository - so actually you are indeed "checking out" files from the repository. Once you make your changes, you commit them right back into the index.
If you're still using git from time to time and get frustrated please feel free to ping @gitdoctor on twitter. It's an account I run to try and help people use git right when they need that help.
Thanks and good luck!
http://www.kernel.org/pub/software/scm/git/docs/git-request-...
3 things I hate about (the culture surrounding) git(hub):
1,3,4,5 - I'm expected to understand the information model.
2 - The CLI is inconsistent.
6,7,8,9,10 - I'm expected to work harder so that life is easier for the maintainer.
If you want svn-like commands, you can borrow someone's scripts or use a shiny GUI. I don't want svn-like commands because centralized version control is obnoxious.
Don't complain because it's hard. Programming is hard, math is hard, and if you know how languages, data structures, and algorithms work, git is actually pretty easy in comparison.
I say to you, don't complain that people are complaining. People are complaining for a reason.
Have you tried some of the other DVCSes? Mercurial, or Darcs, or bazaar? Gits problem is not the problem domain, nor the backend. It's the user interface. That's the hard bit.
I'm working on a collaborative project with several inexperienced developers using various editors and operating systems, and dealing with line endings has been a serious time sink. The first step was "* text=auto" in a .gitattributes file to override everyone's local settings, as some had used custom settings when they installed Git.
Apparently the developers of Git decided to not support \r as a line ending, which ended up causing headaches for us because some legacy programs still use it. Several times, someone committed changes to a file where \r\n line endings had been replaced with just \r, for whatever reason. To Git, they had just deleted the entire file and replaced it with one long line. This frequently resulted in edit conflicts where it was very difficult to tell what had actually been changed.
The solution ended up being a filter:
clean = LC_CTYPE=C awk '{printf(\"%s\\n\", $0)}' | LC_CTYPE=C tr '\\r' '\\n'
...which everyone now has to duplicate in each of their local .git/config on every copy of the repository they use. Coming up with that little bit of command-line wizardry, and getting everyone to install it (and making sure it worked on Windows/OS X) ended up wasting the better part of a day to accomplish what seems like a relatively simple task.So, in the end it was possible, but the process could've been much friendlier.
I will say, though, that git bash is absolutely amazing and blows Cygwin out of the water for ease of use.
You can use git in your .git. Add those hooks to the repository. Every dev will get them automatically on checkout. No one should have to install anything. (Well, aside from Awk.)
But this all misses the point. Git is many many times more powerful than SVN. And that complexity is really useful, even for relatively small projects. You can learn Git's complexity, removing many of SVN's advantages. But you can never get Git's power into SVN.
Right there. I don't know who made this promise, but it's not what Git is supposed to preserve. Git is distributable is it not?
If contributors have write access, then Git is almost as easy. There's just one more command ("git push") compared to SVN.
If contributors don't have write access, then there's no easy way to do this with SVN. Most places that I've seen will either have users submit .patch files via email, or put their changes in SVN branches (ugh). Or, they convince themselves that they'd rather just give contributors write access. Either way, Git has many handy ways to solve this problem (Github pull requests are just one of those ways), and it definitely wins on this front.
Git is built by people smarter than you for people smarter than you. Deal with it.
Now, seriously, Git is a) immensely flexible and b) born out of the needs of Linux kernel developers (or, more specifically, Linus' needs). I would expect it to be optimized for that case.
Not unlike the "Are You There God? It's Me, Jesus" episode of South Park.
If you want to use the more complicated stuff, then there is no way to avoid learning the more complicated ideas.
There is a lot I don't understand about Git, but, as far as my usage patterns have gone, I'm very satisfied.
That's hg. With git, you got the index / staging area, which is unique to git (no idea if bitkeeper has it). In other tools such as svn or hg, there is no need for flags such as "commit -a", "diff --cached", and "add -N".
> If you want to use the more complicated stuff, then there is no way to avoid learning the more complicated ideas.
And this is what we hate about git. Version control shouldn't be complicated for 99.9% of projects. I have used svn for 3 years and hg for 2, they get the job done just fine without cryptic commands and flags.
Git questions on SO with more than 300 upvotes should be considered bugs.
It's been the same experience with git. It definitely has a steeper learning curve, especially coming from a centralized source control system like TFS and Perforce (for me at least), but having worked through that curve, I feel git has been much more useful to my workflows than what TFS or Perforce (or insert any central source control system) has ever been.
Interestingly, SVN and Perforce are about power for the maintainer, with no benefit at all for the contributor. You can't even version control your own work with those tools.
alias commit='git add && git commit && git push'That said, the parent post showed what looked like a bash alias, not a git alias.
I'll also say that tech folks don't like not being able to understand something, and enjoy understanding arcane things others don't (and once understood, no matter how hard it was to learn, it is suddenly "trivial"), further strengthening git's hold. I'm happy to see the author seems to understand git well enough to say, yes, I get it, and I still don't like it. I just wish he had talked about mercurial as the plausible user friendly alternative instead of svn, since svn is not distributed and therefor unsuitable for the use cases where git thrives.
Then I discovered Mercurial. The speed was acceptable. The UI was intelligible. And I didn't hit any sharp corners. Life has been way way better ever since.
if you want to have a really simple way of working with git get the github for mac client. at the same time insanely inflexible.
but hey you know what in theory vss5 is quite "simple" as well. i mean how complex can a program be where distributed work is essentially happening by locking files.
I had hoped op would've said something interesting that might've led into 3rd generation DVCS, but this is definitely far from.
- "Yuck, why such different terminology from DOS?" - "Commands are inconsistent and there are too many, where's my One Command or (better yet) One GUI that does everything they way I think about it?" - "Yuck, scripts that make things easier for my particular workflow, why didn't they just build it right the first time?"
Fundamentally it comes down to people who believe version control is a simple problem, and git confuses that for no good reason, or those who believe version control is an inherently complicated problem, and tends to require some study to understand the concepts. Git doesn't hand-hold, it exposes the core concepts at the data level, thus supporting any workflow for any size of team or work style. If you prefer a dictated workflow and task structure, there are plenty of wrappers that will help you - just don't be surprised if not every team agrees with your preferred workflow.
But it exposes them poorly, from a user interface standpoint. The beauty of UNIX, actually, is that it provided a few simplifying abstractions (block files, character devices, pipes), and everything used that. Imagine if catting the contents of something from /dev was different than piping the contents of a tarball. That's the sort of UI/UX frustrations that TFA (and others) rant about.
This is not a "DVCS vs. SVN/CVS" issue. This is about git's usability.
In general, there are too many of these articles on HN about "I don't know how to use it, so it's terrible."
What OP fails to grasp is the purposeful difference between Git and other revision/version control systems. Git attempts to cover anything you would ever want to do. Git is the Photoshop to SVN's Instagram.
You can use Git as if it were SVN, no problem. You can do Git commit-push-pull all day long as if you were SVN commit-update, and be none the wiser.
The one thing Photoshop has (as a similarly complex piece of software) that Git doesn't have is a single user interface. I don't see this as a problem. There are a bagillion Git GUI clients if you don't like the command line. Some are good, some aren't.
As far as having a good strategy for using Git on a real project. I think OP needs to spend some more time on Google. Here's a good article describing the most common workflow:
Just as a parallel compiler developer must worry about recurrences and data dependencies breaking parallel programs, distributed version control adds a huge level of complexity which you cannot safely hide. However, I agree with the poster that the next major version of Git should clear up several inconsistencies.
(As a side note, some binaries labeled as ASCII in our Subversion repository back then caused massive corruption and shut down all development for days. Having too many assumptions made by your VCS and too few options specified by developers is bad simplicity!)
http://rustyklophaus.com/articles/20100124-SubmodulesAndSubr...
Just use Mercurial for random private commits, send the Git people your changesets every so often:
$ git init && git add . && git commit -m "Initial commit" && git remote add origin git@github.com:acct/repo.git && git push -u origin master
$ subgit setup
$ hg init
hginit.com <-- great resourcehttp://code.google.com/p/support/wiki/DVCSAnalysis
In Google's own words: "In terms of implementation effort, Mercurial has a clear advantage due to its efficient HTTP transport protocol.
In terms of features, Git is more powerful, but this tends to be offset by it being more complicated to use."
And no, that's not too much to ask for a tool that you will be using nearly every day. Once you understand git's data model and "patch-oriented" behaviour, you won't have to wonder about namespaces, the index, rebasing, cherry picking or fast-forward merges.
Point 5, or the fact that Git doesn't even try to hide its internal workings is actually why I prefer it over everything else. The UI can be weird at times since it evolved from just a collection of tools to operate on an on-disk, persistent and immutable data structure, but as far as being good at what it does, it's hard to beat Git.
Haha!
My question is how does mercurial compare to git on all of the author's points?
I've had enough of Git lately, and after reading first couple hundred pages of Git Pro, I decided that Mercurial has a better design. Shame that bitbucket is not as good as GitHub, but BitBucket gives you unlimited private repositories...
IMO it's easier to embrace git after mercurial, because the part where you understand how a DVCS works is already behind you, and you jump into the syntax and specific differences.
There are issues, and flaming the author saying he needs to read more is disrespectful (and ignorant of the issues), but git is a community, open source project. Not happy with the existing docs? Rewrite them, call it git for humans and off you go. I've seen projects doing work to 'nice' the command structure, so there's other people attempting it.
But we can all agree git reset is weird.
I don't hate Git but I do agree with many of your points. There's ccomplexity that should be hidden (or more hidden) and there's inconsistencies that still catch me occasionally. I've never actually lost code on Git though it's taken me a while to find my code.
It's also not fair to confuse Github's "Pull request", "Fork" and "Merge" with Git. These are still just branches and merges.
2. The command line syntax:
But the shortcut for “git branch” combined with “git checkout”? “git checkout -b”
Indeed. You can branch your code, but not check out the files from the index into the working tree.
Perhaps the confusion here is because the author is coming from an SVN background, where checkout means something different.
As for git am being obscure - sure, seems a little, but then there are two things: 1. don't use it if you don't need it, and 2. for kernel development, this is remarkably useful!
3. Documentation: completely invalid. The man pages might seem a little terse, but then if you are looking up a command and you don't understand the terminology, then you should probably consider typing in
man gittutorial
Which, incidentally, can be found here: http://www.kernel.org/pub/software/scm/git/docs/gittutorial....Alternatively, if you are trying to understand how to use git (and it might be worthwhile for the author to follow this advise) then try reading the git user's manual, which can be found here:
http://www.kernel.org/pub/software/scm/git/docs/user-manual....
Hint:
git rebase is explained here: http://www.kernel.org/pub/software/scm/git/docs/user-manual....
To understand how git checkout works, read here: http://www.kernel.org/pub/software/scm/git/docs/user-manual....
4. Information sprawl: actually, I consider myself to be a git newbie (mainly use github!) and frankly I've not needed to learn that much about git so far. However, whenever I've come up against something new, I've checked the documentation and after about 5-10 minutes I've understood the concept needed to get me going. I don't consider myself to be an expert in git in any way. However, as someone who has to program, I tend to find that for any system with enough power, I have to learn new things regularly. git is one of those things. Learn to love it :-)
5. Leaky abstraction: first, don't make the title "leaky abstraction" if you don't believe that there is any abstraction in the first place.
Secondly, it looks to me like they are trying to take your branch and insert it into another repository? Can't quite tell what is required here... certainly I'd love to see the way that this would be done in SVN!
6. Power for the maintainer, not the user...
??? I'm sorry, but the author is complaining that git is powerful, and works really well in highly distributed systems where you have a lot of parallel commits? Well, uh... duh?
The complaint here is that it's not usable for "ordinary" repository users. I would consider myself a fairly ordinary user, and I can honestly say that I don't consider that git is that hard to use.
7. Unsafe version control
DON'T DO THOSE THINGS!
8. In the traditional open source project, only one person had to deal with the complexities of branches and merges: the maintainer. Everyone else only had to update, commit, update, commit, update, commit…
Which meant a massive bottleneck when doing branching and merging. That's the whole point of git - it's version control done large. Or otherwise known as "distributed version control". I'd recommend the author read up on some of the advantages here: http://git-scm.com/about
9. I don't really have much of an opinion on this.
10. Github != git. For the record, I love github and I really don't find it that hard to use, or anything so complex that I can't do it fairly quickly.
I think a cardinal virtue of documentation is to but info where people expect to find it. Saying "Oh, you read the MANUAL. When I said RTFM, I mean the MANUAL for the TUTORIAL" isn't much of a help. If the documentation isn't where novices expect to find it, it doesn't exist.
Unsafe version control
DON'T DO THOSE THINGS!
How many can be done by accident? Are you using revision control at least in part for the ability to recover from a stupid accident? The fact that it isn't safe means you can't count on it being safe. You can't use it as essentially a way to have real point in time recovery for your repo, and it also means you can't count on it being an audit trail because at a minimum it could bet wiped out. That's fine, but it's worth stating up front that this is something Git doesn't do very well. Fine. Understand it is a tradeoff.
forcefully pushing things to remote repositories can be denied with hooks, so if you really do not trust the people with push access you can use that. For anything else, it's pretty much always possible to undo any damage by using the reflog.
In my experience, git is the least unsafe VCS I've used. if I commit a file, I know it's safe from accidental removals (as long as I don't touch .git). If I push the commit to a remote (private or public. Could even be on the same machine), it's safe from anything I do locally. So if I am going to do a complicated merge or a rebase, I first make a temporary commit to save the state of the repository and ensure that I can always undo any mistakes. You can't always do that in svn, since commits are immediately public.
Or more likely not knowing what you are doing, getting disoriented and combining the wrong options.
I haven't been using git for that long but I could totally see myself getting confused and typing something like that in by accident.
What I find amusing is the paucity of information you find in man svn. Try it, you might be a little surprised! Though I have to admit, svn's inbuilt help is quite good.
With regards to not doing the things that can destroy data, in actual fact (as has been pointed out below) there is only really one thing that can't be backed out of is git gc, everything else can be recovered from the git reflog.
As for git having an "audit trail", it has never claimed this.
3. Documentation: completely invalid. The man pages might seem a little terse, but then if you are looking up a command and you don't understand the terminology, then you should probably consider typing in
man gittutorial
Which, incidentally, can be found here: http://www.kernel.org/pub/software/scm/git/docs/gittutorial....
I disagree. Just look at the man page of 'git push', a very common command: http://www.kernel.org/pub/software/scm/git/docs/git-push.htm...It says it does "Update remote refs along with associated objects". What is a remote ref? It's not mentioned in the man page nor in git tutorial.
So maybe I can deduce it from how it used? I see in the syntax that I specify a 'refspec'. What is a refspec? It is explained in terms of 'ref's. Hence, I still cannot make sense of ref, refspec or that man page. Things like these pop up all over the place.
I love git. But it took very long until I even understood some basic stuff. And according to the OP, I am not alone.
Unfortunately, this tends to invalidate many of the points he is making. The author is assuming that git should work exactly the same way as subversion, except that it has a fundamentally different way of viewing version control and uses it's own terminology which can sometimes get in the way of those who know subversion.
but when you oversimplify things for any advanced user it becomes hell. git was made from power users for power users. more precisely to merge hundreds or thousands of patches a day. now you're telling people make it simpler, they're just going to laugh in your face and fully justified at that.
git has wonderful language support. it even has complete implementations in several languages. you want it simpler? hell just take one of those implementations and build it on top of that.
For example, he complains that git pull is actually git fetch and git merge... well, that's pretty obvious. First you have to fetch the changes, then you have to merge in those changes. What is particularly illogical about that?
Another example: he complains that git branch combined with git checkout is git checkout -b (he forgets to note that you specify a branch name...). What's so non-obvious or "insane" about that? First you create a branch with git branch newbranch, then you checkout files from a branch with git checkout <branch>. The obvious shortcut is git checkout -b newbranch <branch>: when you want to create a new branch, then you have to checkout the files from a branch, and the -b creates a new branch for you before you do that.
The only real thing that is a little tricky to understand is the concept of refs, but even that's not really that hard to understand. Every commit has a SHA-1 reference to it, and a branch is merely a reference to a particular commit that is the head of a line of work.
Remote refs are about the only other type of ref that you need to know about - all they are is a reference that points to a remote repository that you can push to or fetch from.
Once you know what a ref is, most of the man pages make sense. Thus when the man page for git-push says:
git-push – Update remote refs along with associated objects
... you can see that it means that it will update the remote refs (remote repositories you are pointing to). Which is what he says in his article, but all he has to really do is understand what a ref is and he wouldn't be so confused.When you think about refs, they make logical sense - all they are is like a "remote branch" of your repository.
As for complexity in the concepts, let's look at what he's complaining about:
...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
1. Files - obvious
2. A working tree - you do your work in the working tree
3. An index - once you have made your changes in the working tree, you commit your changes to the index
4. A local repository/a remote repository - this isn't a particularly hard concept to understand. You do you work in your own local repository. You might get that repository from someone else. You make your changes in your own repository, then you push those changes to a remote repository.
Not entirely sure what is so difficult about that concept...
5. Remotes - again, not a particularly hard concept really, as he says these are just references to remote repositories
6. Commits - You work away on your code in the working repository (whatever directory structure you so desire). Then you commit it to the index. Which is not really any different to SVN, where you checkout a file from the SVN repository, then you make your changes, then you commit your change back to the repository.
Explain to me again what is so hard about this concept?
7. Tree-ish - This is an extremely advanced part of git that most users may never encounter. You most certainly don't need do know about this, though of course it is always good to do so.
8. Branches - we are talking about source control? If so, what is the issue here? Branches are not really any different in git than any other source control system.
9. Stashes - an extremely useful feature. If you are in the middle of working on something and you want to switch branches, you normally don't want to commit those changes. So what you do is "stash" the changes onto a stack. You can reapply them later. Some excellent info can be found here: http://git-scm.com/book/en/Git-Tools-Stashing
There... none of that was so hard, was it?
No, it isn't since the words fetch and pull mean pretty much the same thing to most people.
>> What part, exactly, is so hard to understand?
Looking at the length of your comment...apparently a lot, for most people.
I've tried to like git, I want to like git, I don't get git. So ... in Eclipse at least I use EGit to help me make git usable. Even with that tool to make git easier to understand I still find it confusing (or confounding).
All I can say is that there are valid design decisions for seperating the two. That's why they created the shortcut - to make it easier to do what folks intend to do. When people do a pull, then they get what they want. That is the common nomenclature of git, pretty much everywhere.
And to be clear, the man page for git-merge can't be any clearer:
git-pull - Fetch from and merge with another repository or a local branch
Looking at the length of your comment...apparently a lot, for most people.Which I would argue is because they are coming from SVN, and apply their experience with SVN to git. That's not really a problem for git, IMO, but more an issue for those who believe that SVN is the only way to go about doing source control.
How can this article complain about syntax and documentation, but leave out a discussion of submodules. As much as I like git, that's really the worst part.
If git syntax is that hard, then programming might not be the correct vocation.
I consider git to be almost like a programming language.
The information model is not complex, it's actually quite simple if you really understand it.
* blob: roughly a file (without a name)
* tree: roughly a dir (maps names to blobs and trees)
* commit: tree + parent commit(s) + meta data (author, commit msg, etc).
If you grok this core data model, a lot of things will make much more sense.
http://git-scm.com/book/en/Git-Internals-Git-Objects
I don't know if anyone shares my experience, but I actually found svn rather mysterious and difficult to understand. I never actually saw the point to it at all, so I never bothered using it (unless it was mandated by some authority).
It's only when I understood git that I really understood what version control is supposed to be about.
So, I think people who try to "dumb it down" by giving tutorials that ignore the data model and focus only on the usage are not doing anyone a favor.
Git should be treated like a new programming language or a new operating system. Spend a few days reading (or watching youtube videos) about how it works and why it was designed this way.
Yes, you really have to understand how it works. But it's precisely the fact that you can do so, that make git the best version control system out there in my opinion.
There is no point to Subversion or Perforce, unless it's mandated by some authority. The purpose is for that authority, not for you the programmer. That's the essential difference--in P4 or SVN, the authority has version control and you the programmer do not. In Git, everyone has version control.
People just want some version control, they don't want to learn a whole programming language to have to do it.
Imagine if I had to spend a week learning how to configure my screensaver, set up hard drive backups, or install Dropbox? Forget about it.
Now if git were only popular among super-power-hard-core programmers, then I don't think there would be any criticism. But it's the fact that it seems like pretty much everyone has switched to git now, because its advantages are fantastic, but it takes 100x longer to learn than any other tool I've ever used.
Also, the return on investment is huge.
I think that time spent learning git is time well spent.
Your language, your editor, and your source control. Three things worth knowing backwards and forwards if you're going to call yourself a developer. Three things easily worth spending a week grokking, if necessary.
And editors don't take a week to learn because you don't have to learn everything to use them. Even vi works quite well with just a few commands, and you will never NEED anything other than those, only optimize your usage.
And there is always dispute about the best way to do something as simple as back out a commit or clean large old files from a repository (very difficult with a large team). The series of incantations to do such things is always ridiculously obtuse, with non-intuitive flags and symbols.
Sure the basics are learnable, and google can often reveal solutions (though rarely definitively), but I know no one with a comprehensive understanding of the majority of git fundamentals.
- dd - bash - find
Most of those require quite a bit of time to master.
Now, moving past that, git isn't merely a computer utility, its a foundational element in programming. It's actually more primitive than a programming language itself! The thing that separates the high school students from the "professional" programmers is SCM, and mastery of it. Having seen hardcore dev done on 10m loc code bases in perforce, you need some perspective on how hard git is and isnt.
One of the biggest problems I find is that people attempt to understand git via the lens of SVN. Once you free yourself from the past and understand the basic fundamentals of git, and cast aside your svn-isms you will be zen.
I for one wouldn't hire a developer who isnt intimately familiar with at least one SCM system. Zip files named v1, v2, v3 anyone?
My path at learning SVN was that way too. Heck I didn't even learn the merge command for a couple years until I really needed to, and then I realized how much I had been missing.
I think the big issue that some of us have with git is it can't do all the same things that svn can do. Of course a big problem with svn is it can't do all the things git can do. I wouldn't set nails with a ball peen hammer either.
1. Create the git repository:
git init
2. To commit any changes, you type in: git commit -a -m "thing that I changed"
3. To branch, you type in: git checkout -b newbranch
4. To switch back to a branch, you just type in: git commit -a -m "changes made on branch"
git checkout <branch>
5. To merge in a branch to the current branch, you type in: git merge <branch>
6. To push to a remote repository, you first add a remote repository by typing in the following: git remote add origin git@example.com:my_project.git
(origin can be anything, but a good convention to use for the main repo that you are pushing to).Now to push your changes, you just use:
git push origin <branch>
Most often you will use: git push origin masterWhat do I do if a merge fails? How do I abandon the merge (git certainly doesn't help you, it just keep complaning that there is an unresolved merge).
Why do I get 'git push' telling me there is nothing to push, but 'git pull' telling me I have branches with resolved merges (because git push pushes only one branch, and git pull pull everything).
Those are just two things I've seen beginners hit recently.
From the man page of git-merge:
Before applying outside changes, you should get your own work in good shape and committed
locally, so it will not be clobbered if there are conflicts. See also git-stash(1).
git pull and git merge will stop without doing anything when local uncommitted changes overlap
with files that git pull/git merge may need to update.
How do I abandon the merge?From the man page of git-merge:
--abort
Abort the current conflict resolution process, and try to reconstruct the pre-merge state.
If there were uncommitted worktree changes present when the merge started, git merge --abort
will in some cases be unable to reconstruct these changes. It is therefore recommended
to always commit or stash your changes before running git merge.
git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.for ref the equivs are:
1. hg init
2. hg commit -m "message"
3. hg branch newbranch
4. hg update branchname
5. hg merge branchname
6. hg push
hg outgoing
What I'm interested in is how to switch to a different branch.hg update branchname
If you have uncommited changes it will refuse. You can 'shelve' the changes or force the update to the branch (with a flag on the command line).
But I'm not really sure that pushing is that much of a difficult concept, because you just have to add a remote and then use this to do your push. Not really that much of a difference...
Edit: I've just realized... I probably need to clarify the command:
git remote add origin git@example.com:my_project.git
The only git keywords here are "remote add". Origin could be named anything you want (call it "external"), and the git@example.com:my_project.git is actually what points to the git remote repository. You can also use the same style URI if you want to use SSH, or even HTTP(S).eg.
hg push ssh://hg@bitbucket.org/myusermame/project
or
hg push https://username:password@code.google.com/p/project/
But now I use git, and I don't even consider myself an engineer. I do front-end. Structurally speaking, git makes 10x more sense to me than SVN ever did.
I teach git at work. It takes me a grand total of 10 minutes to explain git's core concept to any dev. It takes me the better part of one hour to teach them how to use git. It takes them the rest of a work day for them to train basically without any intervention on my part, only man pages and a bunch of questions. After that they're basically without training wheels and hardly reach to me, except for the trickiest cases. That's assuming no one is stepping on the brakes, then one who does not want to learn, won't learn.