10

Coming from a SVN background, one of the hardest things to get used to when working with DVCS systems is the way they all seem to regard any uncommitted change whatsoever like a ticking time bomb.

In Mercurial, if you try to fetch changes and you have any uncommitted changes in your working copy, you have to jump through hoops to get it to just merge the incoming changes in. Try to switch branches? It'll force you to shelve everything and then you have to immediately un-shelve it all on the other end. (SVN has no trouble with either of these scenarios.)

Git is about the same way. I'm working side-by-side with another developer on a project, and I just tried to cherry-pick one of his commits into my fork. It refused to let me because I have uncommitted changes in my working copy, on completely different files than the ones changed in his commit. There's not even a merge option; apparently I have to stash my changes first!

If a person were to treat something completely harmless with such extreme caution, I would call it a "phobia," an irrational fear that should be regarded as a mental disorder. But Git and Mercurial were designed by two different teams of intelligent, rational developers, so I have to wonder if they know something I'm not aware of.

Is there a technical reason that justifies this attitude towards uncommitted changes? And if so, why does the problem in question only seem to exist on DVCSes?

  • 7
    Isn't the entire point of these things that you can check into your local branch trivially? Merging from the other developer then becomes an actual merge rather than trying to resolve three sources (your version, your changes, their version). I am no expert in this area though, so may be off base. – Telastyn Sep 16 '15 at 23:32
  • 3
    I agree with Telastyn. I think the reason you're encountering seemingly irrational restrictions is because you're not using Git in an idiomatic way. One of Git's major strengths is that you can commit locally. If I had to merge in somebody else's code into my working copy, I would sure as hell commit locally first. Local commits are cheap, easy to cleanup, and an amazing safety net. I'm not surprise Git workflows revolve around it (and consequently that warnings and restrictions assume you would rather commit than work on uncommited files). – MetaFight Sep 16 '15 at 23:45
  • 3
    @Telastyn: No, you can't, because a checkin--even to your local branch--requires a commit reason and creates a record in the history. So if you check in something that wasn't ready to be committed yet, eventually when you're ready to push changes to the remote repository, that history is going to be there unless you go through additional operations to rewrite history. That doesn't fit any definition of "trivial" that I recognize, and it seems to me like a lot of extra complexity without any articulable benefit. – Mason Wheeler Sep 17 '15 at 9:42
  • Really? "Stabilized XYZ for merge from main" is some burden, or going to overly polite history? – Telastyn Sep 17 '15 at 11:53
  • 1
    Would you submit a paper for publication without at least editing for clarity? Then don't submit your first-draft commit series for publication. Do everyone who will read your code a big favor: go back and produce the commit series you would have written if you'd had the foresight to do it that way in the first place. Interactive rebase isn't hard.. – jthill Sep 20 '15 at 20:41
4
  1. In DVCS-world commits are cheap and history is mutable. WIP can be as "dirty", as you want: and I can't see any reasons against "drop my current state in changeset for storing"
  2. SVN history is linear, thus - you must to merge you drafts with changes from new revisions. DVCS use (natually) DAG, and additional head (commit+pull+up) for diverged history is safer, than merging on the fly modified working dir with fetch'ed external changes
  3. When you switch (to some node) modified WC in Subversion, you get rid of one potential additional merge (contrary to "commit to old"-"switch"-"merge 1 rev. range")... and we know: merges in SVN are not the perfect side of tool, while it isn't a problem at all for DVCSes

Resume

It's not a phobia, it's (sometimes harsh) enforcement to following of good manners "commit often" (SVN-users sometimes are afraid of this style)

And, at last, hg qnew|qpop|qpush is small fair price for neatness and order

1

When you merge or cherry-pick in git, you are creating a commit immediately. The operation is not complete until that commit is finished and part of the history.

Now, what would happen if git allowed you to gloss over your uncommitted changes in your working directory? You would have a (more or less) hard time to differentiate between the changes/merge conflicts that you need to take care of for the merge/cherry-pick, and the changes that you introduced yourself. Also, it would be near impossible for you to test what you are actually committing.

Thus, forcing a clean working directory for merge situations helps to keep things simple and manageable. After all, all you need to do is to stash your uncommitted changes before the merge, and unstash them afterwards. Note, that in the workflow

git stash
git pull
git stash pop

you have two(!) merge operations. One that merges your last commit with the incoming changes, and one that merges your uncommitted changes with the resulting merge commit. In this way, you only ever need to merge two things into one, avoiding the confusion that would result from trying to merge three things into one in a single operation while trying to ignore of these three things. The git stash/git stash pop makes it easy and explicit that you are ignoring your uncommitted changes for the merge.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.