3 ms·
No, 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
by sshumaker 16y ago
No, 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 agoThere are a number of ways to do this in mercurial. If you've got a set of uncommitted changes, only some of which you want to push out. Just commit the files (or use the record extension to commit only parts of files). Then, update back to the previous revision and commit the remaining changes. This makes 2 heads. You can then update back to the first commit and nudge those changes out ("hg push --rev .", which will only push the current version and any unpushed parent revisions). Switch back to the other revision to finish off your work there and merge the 2 heads together when you're done and ready to push it all. You're basically working with anonymous branches at that point, but if you understand that the commits are really just nodes in a DAG, it's pretty easy to visualize what to do.
- pyre 16y ago> 1. If you have other uncomitted changes, you're simply hosed. You can't continue with the merge process with local changes at all. That's what 'git stash' is for. It stores away all changes to the local tree and index (but leaves ignore and untracked files alone). Then you can perform operations like changing branches, doing merges, etc. Then you run 'git stash pop' or 'git stash apply' to pull back your changes. (You'll need the '--index' option if you want you index back in the same state though. It won't 'trash' your changes. They will only be in the working tree, not in the index.) > 2. It pollutes your change list with unrelated, unconflicted changes belonging to your teammate (the whole changeset). Yes. The automatic algorithms have failed to determine how to cleanly merge the changes, so you have to rebuild the final state that you want the tree to be in. When you commit that state, it commits the diff of what is needed to resolve the conflict. Remote: A-B-C Local: A-B-D Final: A-B--D--E \_C_/ You are basically building the state that you want the source tree to look like in commit 'E'. Then the diff of what needs to be done to resolve the merge of states 'D' and 'C' is recorded in the merge commit 'E'. It's not 'polluting your change list' with those changes. It's setting your index into what the final state will look like and pointing out to you what the files that it couldn't figure out. You just need to make them look like they are supposed to (i.e. resolve the conflicts), put them into the index (i.e. 'git add') and push out the merge commit (i.e. 'git commit').
- sshumaker 16y ago1. Yes, git stash is an option. Unfortunately, if it's anything like mercurial's shelve, it's not a good one. What happens when you 'unstash'? Does it properly give you conflict markers, or does it generate patchfiles? The latter is mercurial's behavior, and it sucks. To do the former, the stash command needs to also track the repo version that the local changes were based upon, so it has the historical information to present conflict markers (effectively, enough info for a 3-way merge). FWIW, This is actually the only thing holding my team back from switching back to hg. If hg shelve were part of the standard distribution and rock solid (multiple shelves would form a queue, no chance of corruption, and unshelve preserved historical information so it could properly merge conflicts), the world would be a better place. :) 2. Yes, I know WHY it does what it does. But the way it presents this info is unfortunate, because after a merge it's far more difficult to know exactly which changes you were making - many programmers are in the habit of reviewing their changes before committing. Does GIT let you easily tease out these differences? [edit: call to action]