12 ms·
Still hatin' on git: now with added Actual Reasons
- kgrin 16y ago1) "pull --rebase" might help with one of the particular problems mentioned (though obv. not appropriate for all occasions) 2) More broadly: yeah, if you expect it to work Just Like Things You Already Know, it just won't work out for you. It really is a totally different workflow, and it either works for you, or it doesn't. Empirically, it works great for many people/organizations (though, absolutely, not without some trade-offs). But truthfully, yeah, if you're a single developer, disinclined to use some of the niceties and very interested in maximizing simplicity/reducing keystrokes... svn really may be a better fit.
- kscaldef 16y ago> So I edit the file, fix the trivial conflict, and git commit filename. This is a bit vague, but I'm guessing you mean you open up the file in your text editor of choice and edit it directly. What I do these days, probably originally prompted by exactly the sort of frustration you describe, is to run "git mergetool", which I happen to have configured to fire up emerge, but you can use any of a number of tools. Once I'm done, git is happy and I can just push. Initially I was a little grumpy about learning how to use emerge when before I just edited the file with all its <<<< and ==== and >>>> directly, but after learning the tool, I wish I'd been doing conflict resolution this way back when I used CVS and SVN. It's really much nicer and less error prone. So, I hope that's a helpful hint. You're absolutely right about a lot of the unhelpful & unintuitive messages and commands.
- jrockway 16y agoIsn't the message intuitive? Git usually says, "merge conflict, fix the conflict, stage the fix, and run git rebase --continue". If you follow the instructions exactly, everything works. Now, I know he wasn't doing a rebase (but should have been), but still; when you edit things in git, you stage them, and then commit them. After a merge, the index is mostly ready to be committed, except for the conflicts. So you are supposed to manually stage the fixed conflicts, and then plain "git commit". Simple. It works exactly like anyone who understands git would expect it to. Now, if you don't like the index, then git simply isn't for you. It's a core concept, you just can't avoid it. (Personally, when I was using non-git version control systems, I often had a separate working copy I used exactly like git's index. So having that built in is a joy for me.)
- kscaldef 16y agoNo, “! [rejected] master -> master (non-fast forward)” is not intuitive. The example you give is one of the pleasantly surprising examples of a good error message from git. But, by and large, git's error messages are pretty awful.
- jrockway 16y agoWhat else should a one-line summary of syncing master -> master say? "Hello dear user. The remote server refuses to accept your branch, because it would delete information. As a result, your request has been rejected. Please rebase and try again. If you need help, hang up, and then dial your operator." Personally, I am fine with [rejected]. I figured it out, after all...
- stevelosh 16y agoMercurial says this in the same situation: abort: push creates new remote heads on branch 'default'! (you should pull and merge or use push -f to force) Yes, it's two lines. I think we all have large enough monitors now that an extra line of output to be a bit friendlier is a good thing.
- jrockway 16y agoWhere does it end? Should a compiler say "unknown identifier 'foo': perhaps you need to import a header file that defines foo, or spell it better, or write code that works instead of this garbage" instead of a simple "unknown identifier: foo"? No. You just look up the error in the manual, and never think about it again.
- ryanpetrich 16y agoLLVM will attempt to guess the proper name of a misspelled identifier for you: http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html#spell_checker http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-re...
- amanfredi 16y ago'git commit -a' is not the answer to your merge problem. You should 'git add <file-you-merged>', then commit.
- greendestiny 16y agoYou'd still need to commit the files you pulled (that have changes) though right? Which is sort of fundamental to the whole distributed VCS, it doesn't matter that they were committed in the pulled repository, you have to commit them in the new one.
- MikeTaylor 16y agoThat doesn't work. The "git add README.md" completes with no output, but thereafter, "git commit README.md" still fails with "fatal: cannot do a partial commit during a merge."
- llimllib 16y agojust "git commit" after that, not "git commit README.md" edit: it's infuriating that yc won't let me reply to you, so I have to reply in this edit. Anyway. "git commit" says to git: "move anything in the index (i.e. things which I have 'git add'ed, or which have been merged) into the local repository". "git add FILE && git commit" says "put FILE in the index and then commit the whole index to the local repository" "git commit FILE" says "assume the index is clear, and only commit FILE" to which git says the logical response, "sorry, dude, the index isn't clear, I can't do that" perhaps this will help: http://osteele.com/archives/2008/05/commit-policies http://osteele.com/archives/2008/05/commit-policies
- MikeTaylor 16y agoOh! Well, thank you. Yes, I see that that works. But: (A) I see that it still commits everything, just like "commit -a", including all the files that I didn't change but that my colleague did in the branch that I'm pulling; and (B) Why would "git add FILE; git commit" but "git commit FILE" not work? I bet it's something to do with the index.
- deleted 16y ago[deleted]
- timdorr 16y agoSomeone needs to introduce this guy to the concept of rebase and then maybe he'll get on board with branching. And then maybe some of his problems with be solved. I used to have these issues until I started branching and rebasing off a core "develop" and "master" branch.
- sqrt17 16y agoDuh. I've never got the hang of git either, but I figure git is for those people who don't get enough mileage out of Mercurial because they have 42 megatons of source code, or need git rebase, or just want to shock and awe their friends. But no need to hate git for that. No one's forcing you to use it. You don't like vim? Go ahead and use emacs/gedit/eclipse/perl. You don't like git? Use mercurial. Or subversion, if it makes you happier. Merging is always a pain with VCS, more so with DVCSs because they let you conveniently forget a bunch of patches in that repository copy on the USB stick in your back pocket . And these long mumblish version numbers are also going to stay - but they're not so bad when you use a graphical repository browser (hg view/hg_web/git-web/tortoise). And if you just need versioning for a couple .doc files: use Apache's mod_dav_svn and be done with it (i.e., you can mount it as a directory in Nautilus or the Mac finder and it just works). Even though I like all the fancy stuff in Hg, I started using it and never looked back because it's always been painless. (Oh, and you can work directly* on the repository, version history is mostly useless because it reflects weird program behaviour including temporary files, but you'll never get any conflicts unless you mess up really badly).
- MikeTaylor 16y ago"But no need to hate git for that. No one's forcing you to use it. You don't like vim? Go ahead and use emacs/gedit/eclipse/perl. You don't like git? Use mercurial" If only this were true. But it's not: if I work on a project where my colleagues keep the source in git, then I have to use git (whereas if they use vi, I am still at liberty to use emacs). That's the problem with CVSs -- they have a lot more inertia than most other tools because they are, by nature, shared by groups.
- ionfish 16y agoI presume you haven't come across Hg-Git, then. http://hg-git.github.com/ http://hg-git.github.com/
- MikeTaylor 16y agoI've seen things like this. I would be very wary about trusting them with my precious source code, wouldn't you? However good they are, they're an additional layer in which (A) things can go wrong, and (B) you're insulated from the reality that you need to access to fix problems. I fear that Hg-Git would be one of those things that is an absolute delight for as long as it Just Works, then abruptly transitions into an absolute horror the moment something goes wrong.
- andreyf 16y agoI think the move back to CVS/Subversion might be the way to go From your complaints, it sounds like you'd really like Mercurial. Give it a shot.
- sshumaker 16y agoNo, mercurial has exactly the same problem he mentioned: You want to push 'some' of your local uncommitted changes, but if the remote head has also changed you often can't. (hg shelve is a poor substitute). This happened to my team enough in practice that they rebelled and forced a switch back to SVN.
- lars512 16y agoLooks to me like he had two problems. The first was that git gave very poor error messages and needed a confusing series of command-line options. In mercurial, this is much better; the pull creates a new head, and tells you what to do if you want to merge them. Commit is one-step, instead of via the staging area. It just gives more feedback, more usefully, and requires less knowledge about the underlying representation. His second problem is common to both systems, namely that during a merge-with-conflicts you have to essentially re-commit both changes. This is actually a kind of safety feature, since the conflicted change might have screwed up something and it's up to you to make sure the code is in a good state after the merge. If the merge isn't conflicted, then Mercurial (and probably git) does it cleanly without forcing you to read over your teammate's change, which he hates doing.
- sshumaker 16y agoThere's two problems with this approach: 1. If you have other uncomitted changes, you're simply hosed. You can't continue with the merge process with local changes at all. 2. It pollutes your change list with unrelated, unconflicted changes belonging to your teammate (the whole changeset).
- tednaleid 16y ago
- Qz 16y agoAll the people suggesting various git commands he should be using are completely missing the point.
- IsaacSchlueter 16y agoThe point being that the author isn't looking for solutions, but rather just wants to bitch?
- Qz 16y agoThe point being that the solutions are problematic.
- itistoday 16y agoAnd the problems shouldn't exist in the first place.
- MikeTaylor 16y agoBut, yes, I do also like to bitch about them :-)
- ableal 16y agoWatch out for the flying door-knobs. ( http://news.ycombinator.com/item?id=1272779 http://news.ycombinator.com/item?id=1272779 ) Seems that the peasants who have binaries should use rsync manually, instead of expecting tools to do the job.
- donaq 16y agoLinus didn't write git for you. He wrote it for himself. Git works exactly the way Linus (and his merry band of kernel hackers (and others, who thought DVCS was a cool idea when they heard about it and were prepared to relearn SCM to use it)) wants it to work. If you want to learn to use it, cool, welcome to the party. If you aren't prepared to invest the time, that's cool too. But don't try it for like a day expecting it to be svn++ and then complain that it isn't. That's like a Windows user declaring that Linux sucks because it isn't Windows. It wasn't meant to be. Although, complaining about Ubuntu not doing things the way they "should" is more valid, since Ubuntu is targeted at everyone. :)
- moe 16y agoDon't give up faith my friend. Git and mercurial are not the end of the story. I'm optimistic that, within another few years (give or take a decade), someone will come up with a VCS that's both powerful and usable. :-) Other than that: I enjoyed your article. Very nice walk through some of the problems and hair-pulling that I'm going through regularly, too. Pro-Tip: My life with git got a bit easier since I keep this big bucket of paste-ready shell-snippets near my terminal window. You know, those handy little 14-liners that look like line-noise at a glance, but get you out of "situations" when chanted.
- DTrejo 16y agolink to your 14-liners?
- moe 16y agoSadly I guess they most of them don't make much sense without context or the discussion/thinking that led to them. But for example, this is my snippet for merging my current branch into master and pushing that to origin (hopefully merging/cleaning up in between as appropiate): # on local branch git fetch origin master git rebase origin/master # tidy up git rebase -i origin/master # merge to master git checkout master git merge $my_branch # push to master git push origin master # go back to local branch git checkout $my_branch I didn't originally come up with all that, mind you. It's pulled from a workflow tutorial and you'll find basically the same procedure recommended in every tutorial (keywords: feature branches and "don't work directly on master"). And yes, I paste that multiple times per day and still throw up a little bit inside my mouth every time.
- dlsspy 16y agoYour first two commands can be replaced with (one time): git config --global branch.autosetuprebase always Then "git pull" Without doing the config change, you can just do a "git pull --rebase" Your "git push origin master" is typically what I spell "git push" (recommend "git config --global push.default tracking" just to make sure you're pushing the same stuff that's tracked automatically). So, my every day workflow (rebasing upstream and building on top of stuff) looks like this: git pull [edit a bunch of files] git add -p git commit git push My mouth is minty fresh.
- ynniv 16y agoI have read a fair amount of documentation on git. I still don't even know what most git commands do. When people recommend a rebase, I pretty much just pretend that my repository isn't going to die. I wince every time I have to revert a file, as "git checkout" is friendly but "git checkout <filename>" is destructive without warning. I once destroyed a number of local files (I don't remember how) that were thankfully still open in emacs. git is awesome, and git is terrible, often for the same reasons. git is a Sharp Knife, which is fantastic if you need one, and horrible if you don't. I personally have basic distributed version control needs and git is far too sharp for my needs. I have managed to not cut anything important off, but I tread carefully around each command, often worrying that I will irrevocably destroy my files. So, +1 for being way better than previous version control systems, but a friendlier modern version control might easily win.
- pyre 16y ago> I wince every time I have to revert a file, as "git checkout" is friendly but "git checkout <filename>" is destructive without warning. From my point of view, that's like saying that 'rm -rf' is destructive 'without warning.' It does what it was meant to do, you can't expect everything to warn you all the time in an effort to save you from yourself. It would get really annoying, really fast if it asked you to confirm every time you performed an operation in git. 'git checkout <filename>' == 'replace <filename> with the version of <filename> in the index' (if the index is empty, then index == HEAD) I'm also unsure how 'svn checkout <filename>' is less destructive. [Note: Though these 'git debates' tend to get heated because you have "frustrated people that don't understand git but are trying to use it" on one side and "people that understand git and are frustrated at the 'ignorance of newbs'" on the other side, this is not an attack.]
- barrkel 16y ago'svn checkout <filename>' isn't a valid svn operation; checkout applies to directory urls. Actually, beyond svn revert, I struggle to think of an easy way for you to lose your local modifications. If you really just wanted the latest version of <filename>, I guess you might use svn cat, but you'd have to redirect it to overwrite the other file yourself. For svn update, it won't overwrite local modifications. svn revert seems to be better named for this purpose.
- deleted 16y ago[deleted]
- IsaacSchlueter 16y agoWe all need to throw a tantrum sometimes when things don't work the way we like. It's ok. Let it out. We're computer users, we understand. ...feel better? Now shut up and learn how to use your tools.
- jodrellblank 16y agoIt's true. www.ventatme.com isn't registered...
- alfredp 16y agoI felt the same way about git but I wasn't able to articulate it as well as he did. Go mercurial!
- santry 16y agoSeems to me he should just use Subversion. He has a mental model of how version control works (based on his prior use of CVS) and apparently doesn't wish to invest the time to learn git's model.
- pyre 16y agoI sort of take issue with this statement: “git is bad for me because it makes assumptions about how I work that don’t match how I actually work” I think that it's the other way around. git was built with a specific type of workflow in mind. If you take git and try to insert it into your current workflow with a minimal understand of git (or its intended workflow), then isn't it really you that are making assumptions about how the tool works, rather than the tool make assumptions about how you work? {edit} - I make a one-line change to a single file. - I commit my change. - I git push, only to be told “! [rejected] master -> master (non-fast forward)”. (This is git’s cuddly way of telling you to do a pull first.) - I git pull, only to be told “CONFLICT (content): Merge conflict in filename. Automatic merge failed; fix conflicts and then commit the result.” This is because you've created your local tree as such: A-B-C And the remote tree looks like: A-B-D When you run a 'git pull' it's a combination of two operations: 1. 'git fetch' or 'git remote update' which updates your local copy of the remote tree. This is stored locally in the branch <origin_name>/<branch_name> (e.g. origin/master). 2. 'git merge <branch_name> <origin_name>/<branch_name>' most of the time this merge is a fast-forward merge which you don't notice at all. It's when your local commit 'C' has conflict with remote commit 'D' that you run into an issue. In the end your tree will look like: A-B--D--E \_C_/ Where E is a commit with that resolves the conflict and has two parent commit IDs which point at D and C. In general, you want to just avoid this kind of stuff in the first place by either using rebase or doing the 'git pull' before you commit you changes, then push them out. [ I'm having a hard time picturing how you would have resolved this with SVN. If you have a conflict between a local file and an update that you are pulling down with 'svn up' what happens? (I've not used SVN extensively) ] {edit} > Well, darn. So, OK, no problem, I already fixed the conflict, so now I’ll just git merge again to get it to make its world consistent, right? Nope: “fatal: You have not concluded your merge. (MERGE_HEAD exists)”. Well, duh! I was telling you to merge, you stupid git. You’re the branches-and-merges-are-easy version-control system around here. You're telling git to start a new merge, not complete an in-progress merge. Think of 'git merge' as 'create a commit that merges these two things together.' When you run into a conflict 'git merge' tells you, "Sorry I couldn't automatically resolve this for you, but I got you as far as I could go. You'll have to manually resolve these conflicts and create the merge commit." At this point your working directory is in a state of 'middle of a merge.' You just have to resolve the conflicts that were pointed out to you (adding them to the index once they are resolved), and run a 'git commit' to push out the merge commit.
- weavejester 16y agoMike, Git seems unintuitive because you don't have a good grasp of what it does behind the scenes. Imagine trying to get to grips with a Unix shell, if you had no concept of files or directories. In such a scenario, even a simple command like "cat" would seem incomprehensible. If you'll indulge me, I'd like to propose a thought experiment. * * Designing a patch database * * Consider you're responsible for administering a busy open source project. You get dozens of patches a day from developers and you find it increasingly difficult to keep track of them. How might you go about managing this influx of patch files? The first thing you might consider is how do you know what each patch is supposed to do? How do you know who to contact about the patch? Or when the patch was sent to you? The solution to this is not too tricky; you just add some metadata to the patch detailing the author, the date, a description of the patch and so forth. The next problem you face is that some patches rely on other patches. For instance, Bob might publicly post a patch for a great new scheduler, but then Carol might post a patch correcting some bugs in Bob's code. Carol's patch cannot be applied without first applying Bob's patch. So you allow each patch to have parents. The parent of Carol's patch would be Bob's patch. You've solved two major problems, but now you face one final one. If you want to talk to other people about these patches, you need a common naming scheme. It's going to be problematic if you label a patch as ABC on your system, but a colleague labels a patch as XYZ. So you either need a central naming database, or some algorithm that can guarantee everyone gives the same label to the same patch. Fortunately, we have such algorithms; they're called one-way hashes. You take the contents of the patch, its metadata and parents, serialize all of that and SHA1 the result. Three perfectly logical solutions, and ones you may even have come up with yourself under similar circumstances. * * Merging patches * * Under this system, how would a merge be performed? Let's say you have two patches, A and B, and you want to combine them somehow. One way is to just apply each in turn to your source, fix any differences that can't be automatically resolved (conflicts), and then produce a new patch C from the combined diff. That works, but now you have to store A, B and C in your patch database, and you don't retain any history. But wait! Your patches can have parents, so what if you created a 'merge' patch, M, with parents A and B? A B \ / M This is externally equivalent to what you did to produce C: patches A and B are applied to the source code, and then you apply M to resolve the differences. M will contain both the differences that can be resolved automatically, and any conflicts we have to resolve manually. Having solved your problem, you write the code to your patch database and present the resulting program to your colleague. * * A user tries to merge * * "How do I merge?" he asks. "I've written a tool to help you do that," you say, "Just specify the two patches you want to combine, and the tool will merge them together." "Um, it says I have a merge conflict." "Well, fix the problem, then tell the system to add your file to the 'merge patch' it's making." Your colleague dutifully hacks away, and solves the conflict. "So I've fixed the file," he says, "But when I tell it to 'commit file' it fails." "Remember, this is a patch database," you reply, "We're not dealing with files, we're dealing with patches. You have to add your file changes to your patch, and then commit the patch. You can't commit an individual file." "What? That's not very intuitive," he grumbles, "Hey! I've added the file to the patch, but it tells me the merge isn't complete!" "You need to add all of the files that have differences that were automatically resolved as well." "Why?!" "Because," you explain patiently, "You might not like the way those files have been changed. It needs your approval that the way it's resolved the differences is correct." "Why to I have to re-commit everything my buddy has made?" he complains, "Seriously, I want to just commit one file. What the hell is up with your system?"
- dasil003 16y agoThe complaints about git porcelain are totally understandable. The UI is horrendous. However the internals are elegant and actually much simpler than subversion, so if you understand the internals and do a little rote memorization then suddenly you can manipulate your repository expertly, creating better commits and handling unusual needs with ease. It's the difference between being good with a unix shell and running windows configuration wizards to do everything. I don't expect the OA to grok that, however one thing that I hope the author takes to heart is this: With git plumbing it would be fairly straightforward to create a new porcelain VCS combining any balance of elegance, simplicity and power that you desire. With subversion on the other hand, it is almost unimaginable that they would ever be able to correctly track a merge without a hundred bizarre edge cases due to the fact that their repository structure muddles branches and directories. Why hasn't someone who knows git created a better porcelain yet? Probably because once you know git well enough you don't want to give up any of it's native power just to satisfy some noob's anxiety attack.
- dlsspy 16y ago> Why hasn't someone who knows git created a better porcelain yet? Probably because once you know git well enough you don't want to give up any of it's native power just to satisfy some noob's anxiety attack. They exist. gitx, magit, etc... are all great tools. Most people who use it for any length of time seem to be just fine with it, though. I can recognize a few things as... silly (e.g. checkout), but not so much as to try to introduce a new verb and redefine the semantics just to come up with a better separation when I already know what I'm doing with the tool. I certainly don't have enough of a problem to write an entirely new interface when the existing one continues to get incrementally better. Similarly vi and emacs are both great editors whose power cannot be harnessed by those who don't spend time trying to learn them. The vested are less affected by idiosyncrasies.
- dreyfiz 16y ago> Cheap branching is better than expensive branching, sure, but that’s like saying influenza is better than cancer. I’d rather just not be ill at all, thanks. Please stop posting this know-nothing's uninformed rants.
- angrycoder 16y agoI get the idea that he wants version control that 'just works'. Unfortunately version control, like most other software, has become complicated. He needs to spend less time typing and more time reading. I don't think git is something you can reason out just by throwing commands at it.
- twoism 16y agoAm I the only one who reads posts like this and wonders why people make merging/pushing/pulling with Git so complicated? It's really not that hard. Sure there are plenty of esoteric and strange things you can do with Git but I have seen devs go from zero knowledge to using the basics in no time. Some never have to go beyond the add, commit, push, pull and merge commands (with their respective switches) and work quite happily. Sure they aren't Git experts by any means but they are able to get their work done and the tool is just as transparent to their workflow as any other SCM tool.
- UnknownSource 16y agoThe fact that you need to install either Cygwin or a 100MB collection of Msys files put us off it for our project. We stuck to Mercurial because we thought it would be easier for newbies to get involved, and it seems to be working. Also, unlike Git, Mercurial is coded in Python.. Git is a mesh-mash of half a dozen different languages. I'm guessing long-term, Mercurial will be maintained better (but might be wrong).
- overgard 16y agoI generally agree with the sentiment of this article, though I feel like I need to get better at using git anyway. It's a leaky abstraction and very unintuitive, no doubt, but after using Git regularly I just can't go back to subversion, the workflow in Git is so much nicer (when everything goes as expected, at least...)
- Mc_Big_G 16y agoThe length of the explanations in this thread says something about the usability of git. Not hating, just saying.