Excellent dig into the underlying issues there, Patrick.
Patrick Maupin
Shared publicly -Partial git merges -- just say no.
(Unlearning subversion, or confessions of a git newbie.)
Git spawns a lot of blog posts. I think I read most of them, yet something still tripped me up badly. Fortunately, +Eric Raymond was there to set me straight.
Subversion has the concept of partial merging. The DAG actually records where things came from. No, it's not great, but it kinda, sorta works for some use cases.
Git doesn't. Git has cherry-picking. Now, you could, like I did, try to recreate subversion partial merges so that you know where each snippet originated, and keep the author information, etc. in the metadata.
Don't. It's a terrible idea.
The problem is not that you can't do it. Git is powerful enough that it will let you do fancy merge-fu. You can explain to it that this was partially merged in from here and that from there. Your graphs in gitk or on github will look seductively beautiful and fully match, in your mind, what happened with the code.
The problem is that, as far as git is concerned, the partial merge you expressed was actually a full merge, that conveys how these two branches should be combined. But this problem doesn't actually become apparent until the next time you try to merge.
Since any merge is, according to git, a full merge, git thinks it conveys intentions for downstream merges as well. Deleted this file because you weren't ready to merge it yet? That's just what you think. Git knows you deleted it because it's extraneous, so if you merge again it will helpfully re-delete it for you.
This is why the done thing in git is to create a branch to work on a single problem, merge it in when you are done, and then delete it. As far as git is concerned, re-merging should only pick up development done in the branch after the initial merge, e.g. for the case when somebody branched off your branch right before you merged it.
Also, as far as git is concerned, the merge is fully symmetric -- the only difference between merging A into B and merging B into A is which branch name moves to the result of the merge and which one stays put. So merging changes that others made off of either branch is an identical operation.
The right git workflow mostly avoids cherry-picks, but going out of your way to avoid them, or trying to map partial subversion merges to anything but cherry-picks will be a disaster, notwithstanding the fact that cherry-picking always destroys information. Git is generally smart enough to detect a cherry-pick in the next merge and avoid doing it twice; the human just has to be smart enough to use the commit comments and diffs to keep everything straight.
(Unlearning subversion, or confessions of a git newbie.)
Git spawns a lot of blog posts. I think I read most of them, yet something still tripped me up badly. Fortunately, +Eric Raymond was there to set me straight.
Subversion has the concept of partial merging. The DAG actually records where things came from. No, it's not great, but it kinda, sorta works for some use cases.
Git doesn't. Git has cherry-picking. Now, you could, like I did, try to recreate subversion partial merges so that you know where each snippet originated, and keep the author information, etc. in the metadata.
Don't. It's a terrible idea.
The problem is not that you can't do it. Git is powerful enough that it will let you do fancy merge-fu. You can explain to it that this was partially merged in from here and that from there. Your graphs in gitk or on github will look seductively beautiful and fully match, in your mind, what happened with the code.
The problem is that, as far as git is concerned, the partial merge you expressed was actually a full merge, that conveys how these two branches should be combined. But this problem doesn't actually become apparent until the next time you try to merge.
Since any merge is, according to git, a full merge, git thinks it conveys intentions for downstream merges as well. Deleted this file because you weren't ready to merge it yet? That's just what you think. Git knows you deleted it because it's extraneous, so if you merge again it will helpfully re-delete it for you.
This is why the done thing in git is to create a branch to work on a single problem, merge it in when you are done, and then delete it. As far as git is concerned, re-merging should only pick up development done in the branch after the initial merge, e.g. for the case when somebody branched off your branch right before you merged it.
Also, as far as git is concerned, the merge is fully symmetric -- the only difference between merging A into B and merging B into A is which branch name moves to the result of the merge and which one stays put. So merging changes that others made off of either branch is an identical operation.
The right git workflow mostly avoids cherry-picks, but going out of your way to avoid them, or trying to map partial subversion merges to anything but cherry-picks will be a disaster, notwithstanding the fact that cherry-picking always destroys information. Git is generally smart enough to detect a cherry-pick in the next merge and avoid doing it twice; the human just has to be smart enough to use the commit comments and diffs to keep everything straight.
6



3 comments
Thanks! Although I feel kind of foolish about how long it took me to figure it out...
One of the greatest teachers are your failures. ;)
Add a comment...


