But how do I merge your "foo" and my "woot"? Um ... why should I even have to care? Why aren't we just working on the same branch by default?
> Is this supposed to mean that the concept of private, local branches is confusing?
Yes. What happens when I type "git push"? Which of my named branches got transferred? Um ...
> "Why not just clone the whole repository?" really baffles me, because that's exactly what cloning already does...
So, is that before or after having been gc'd? Which branches did you get? etc.
If there are 3 people generating code artifacts in an office, one of which is an artist, I DON'T CARE about any of these things. Worse, they are wasted mental energy for people who don't like this kind of stuff (the artist, for example, likely doesn't enjoy graph theory). Worst, they are ways that you can corrupt your repository or blow your code away.
The fact that I have to think about graph theory to use a DVCS in daily use is unacceptable. It means I can't explain this to writers, artists, and other non-programmers who I would really like to have in source control, too.
I explain mercurial vs git like the difference between a high-end chainsaw and a logging chainsaw. A high-end chainsaw has things like safeties, a blade clutch, electric starters, comfortable handles, etc. It will go through 99% of the trees anybody will use it for. A logging chainsaw doesn't have lots of amenities, but the motor is bigger and it will blow through 100% of trees. It's also a hell of a lot heavier which means it's harder to control and more likely to seriously hurt you when something goes wrong.
`git checkout woot; git merge his/foo`?
> Um ... why should I even have to care?
Because it helps encourage separating work logically, and gives you quick way to reset your working tree to a known state should merging upstream changes go awry?
> Why aren't we just working on the same branch by default?
You are, you just create topic branches off the development one to focus a series of commits on some goal. When you're ready to share it, just merge it into the development branch and push it. If you and your colleague are working on a topic together, you do the same, just push to some common remote branch for that topic.
> What happens when I type "git push"?
In Git 2.0, it pushes the current branch iff it tracks a remote upstream one; otherwise it prints an error explaining how to set the upstream branch for the current branch.
> So, is that before or after having been gc'd?
GCing only removes garbage. Since you're creating branches to keep track of your topics, this shouldn't ever be a problem. If you had no references to a commit, it must not have been important!
> Which branches did you get? etc.
As far as I know, cloning gets every branch from a remote; not all branches will automatically have tracking branches, but making those is easy enough.
> Worst, they are ways that you can corrupt your repository or blow your code away.
Do you mean making incompatible commits via rebasing by "corruption," or are you referring to actual repository data loss due to bugs? I'm unaware of the latter. If you consistently make temporary private branches, it should be impossible to lose work.
Is graph theory really that complicated? I always thought it was one of the more intuitive compsci topics, since it's very visual. Maybe that's my bias, though.
I try Mercurial every once in a while, so I'm not basing my opinion only on old versions (in fact, I just played around with it again today.) I always feel constrained--like it's trying to prevent me from doing what I want to do. A lot of it is familiarity, I'm sure, and differences in nomenclature (though, I'll say, "checkout" makes a lot more sense than "update" to me--I would assume that "update" would be analogous to "fetch").
> GCing only removes garbage. Since you're creating branches to keep track of your topics, this shouldn't ever be a problem. If you had no references to a commit, it must not have been important!
Coming from Mercurial to Git, this has been the single hardest thing to wrap my head around (so far). Why should I have to tell my version control system twice not to throw away my work? Committing a change should be sufficient to let the VCS know that I want to save it. That's what that word means.
If we think of the VCS like a text editor, then a branch is like a file that you can write changes to. However, if you're working on an unnamed file, then the editor (or its designers) has to make a choice about what to do with that unnamed document when you're done.
Git treats an unnamed branch like the scratch buffer in Emacs. You can make all the changes you want, but once you close it, it's gone (in this case, eligible for GC). This seems reasonable, because if you cared about it, you would have given it a name.
Mercurial's designers work off a different assumption: all the work that you do is important (and it provides other mechanisms to allow rough work). So if you start working in an unnamed branch, that's no problem. You can have as many unnamed branches as you like, but it's up to you to remember your way around. Going back to the filesystem analogy, it becomes like navigating between your unnamed text files by their address on the disk, rather than a nice human readable name.
Does this analogy make sense to anybody else?
Not bugs. Actual repository loss due to commands functioning as intended. "git push" tends to be the culprit. I have seen more people blast repositories with it than you would believe.
> Is graph theory really that complicated? I always thought it was one of the more intuitive compsci topics, since it's very visual. Maybe that's my bias, though.
Repeat after me: "Not everybody is a programmer."
Okay? Really. I want my artists, composers, writers, etc. to put their stuff in version control. They can't do that if a third or fourth year course in CS is a prerequisite.
And that's my biggest counterpoint. I can and have taught people who have basic computer literacy how to use CVS, svn, hg, and even bzr. git is completely opaque to those same people.
Also, a "third or fourth year course in CS" is not a prerequisite for understanding git. I am proof of that :-)
Sure, maybe the data was actually there and a git god could have unwound whatever brain damaged state "git push" stuck the repo in. Maybe. However, it's not like everybody didn't try. The only thing that saved them was that I take snapshots of git repositories via rsync every hour because I know this is going to happen. Not might--will.
I have never had this happen with Mercurial. Ever. I don't even think about it. I wouldn't dream of rsync'ing a Mercurial repository because I've never put a repo in a state that I can't find the data.
Everybody apologizes for git. I don't have to apologize for Mercurial.
! [rejected] master -> master (non-fast-forward)
# error: failed to push some refs to 'https://github.com/
USERNAME/REPOSITORY.git'
# To prevent you from losing history, non-fast-forward updates were rejected
# Merge the remote changes (e.g. 'git pull') before pushing again. See the
# 'Note about fast-forwards' section of 'git push --help' for details.> Dude, this is NOT theory. I watched it happen.
No, you thought you saw it happen. "git push" does not remove data, it can only add new commits (and their contents) and update refs (branch names and tags) so you were mistaken in what you saw.
> Sure, maybe the data was actually there
Yup, exactly. No data was lost. It was actually there.
> and a git god could have unwound whatever brain damaged state "git push" stuck the repo in
I like the "git god" moniker. Thanks! But it's not really that complicated. What probably happened was that "git push" added a new line of commits, and updated your branch name (let's say it was "master") to point at these new ones. The old ones were still there though, they just weren't an ancestor of your current "master" so you couldn't see them immediately with "git log".
If you wanted to get your repository back to its previous state, you just needed to look with "git reflog" and see what commit master used to point to, and then set it back to that. That's the only change you needed to make. The repository wasn't broken in any way, it just had a few more commits in it.
Now, you might say that "git push" shouldn't make it so easy to do this: and you'd be right, so it doesn't. You need to have used "--force" to get it to behave in this way. Really, if this is a happening regularly, you clearly have a broken workflow. Perhaps introducing some Code Review in there would help? Gerrit maybe?