{"thread":{"id":"16808","subject":"[PATCH] Add a documentat on how to revert a faulty merge","startedAt":"2008-12-20T11:27:02Z","lastAt":"2008-12-21T02:37:11Z","messageCount":3,"participants":["Nanako Shiraishi","Boyd Stephen Smith Jr.","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"98430","messageId":"20081220202702.6117@nanako3.lavabit.com","threadId":"16808","inReplyTo":null,"subject":"[PATCH] Add a documentat on how to revert a faulty merge","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2008-12-20T11:27:02Z","receivedAt":"2008-12-20T11:27:02Z","isPatch":true,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Linus and Junio explained issues that are involved in reverting a merge\nand how to continue working with a branch that was updated since such a\nrevert on the mailing list.  This is to help new people who did not see\nthese messages.\n\nSigned-off-by: Nanako Shiraishi <nanako3@lavabit.com>\n---\n Documentation/howto/revert-a-faulty-merge.txt |  179 +++++++++++++++++++++++++\n 1 files changed, 179 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/howto/revert-a-faulty-merge.txt\n\ndiff --git a/Documentation/howto/revert-a-faulty-merge.txt b/Documentation/howto/revert-a-faulty-merge.txt\nnew file mode 100644\nindex 0000000..c3ef24f\n--- /dev/null\n+++ b/Documentation/howto/revert-a-faulty-merge.txt\n@@ -0,0 +1,179 @@\n+Date: Fri, 19 Dec 2008 00:45:19 -0800\n+From: Linus Torvalds <torvalds@linux-foundation.org>, Junio C Hamano <gitster@pobox.com>\n+Subject: Re: Odd merge behaviour involving reverts\n+Abstract: Sometimes a branch that was already merged to the mainline\n+ is later found to be faulty.  Linus and Junio give guidance on\n+ recovering from such a premature merge and continuing development\n+ after the offending branch is fixed.\n+Message-ID: <7vocz8a6zk.fsf@gitster.siamese.dyndns.org>\n+References: <alpine.LFD.2.00.0812181949450.14014@localhost.localdomain>\n+\n+Alan <alan@clueserver.org> said:\n+\n+    I have a master branch.  We have a branch off of that that some\n+    developers are doing work on.  They claim it is ready. We merge it\n+    into the master branch.  It breaks something so we revert the merge.\n+    They make changes to the code.  they get it to a point where they say\n+    it is ok and we merge again.\n+\n+    When examined, we find that code changes made before the revert are\n+    not in the master branch, but code changes after are in the master\n+    branch.\n+\n+and asked for help recovering from this situation.\n+\n+The history immediately after the \"revert of the merge\" would look like\n+this:\n+\n+ ---o---o---o---M---x---x---W\n+               /\n+       ---A---B\n+\n+where A and B are on the side development that was not so good, M is the\n+merge that brings those premature changes into the mainline, x are changes\n+unrelated to what the side branch did and already made on the mainline,\n+and W is the \"revert of the merge M\" (doesn't W look M upside down?).\n+IOW, \"diff W^..W\" is similar to \"diff -R M^..M\".\n+\n+Such a \"revert\" of the merge can be made with:\n+\n+    $ git revert -m 1 M\n+\n+After the develpers of the side branch fixes up, the history may look like\n+this:\n+\n+ ---o---o---o---M---x---x---W---x\n+               /\n+       ---A---B-------------------C---D\n+\n+where C and D are to fix what was broken in A and B, and you may already\n+have some other changes on the mainline after W.\n+\n+If you merge the updated side branch (with D at its tip), none of the\n+changes made in A nor B will be in the result, because they were reverted\n+by W.  That is what Alan saw.\n+\n+Linus explains the situation:\n+\n+    Reverting a regular commit just effectively undoes what that commit\n+    did, and is fairly straightforward. But reverting a merge commit also\n+    undoes the _data_ that the commit changed, but it does absolutely\n+    nothing to the effects on _history_ that the merge had.\n+\n+    So the merge will still exist, and it will still be seen as joining\n+    the two branches together, and future merges will see that merge as\n+    the last shared state - and the revert that reverted the merge brought\n+    in will not affect that at all.\n+\n+    So a \"revert\" undoes the data changes, but it's very much _not_ an\n+    \"undo\" in the sense that it doesn't undo the effects of a commit on\n+    the repository history.\n+\n+    So if you think of \"revert\" as \"undo\", then you're going to always\n+    miss this part of reverts. Yes, it undoes the data, but no, it doesn't\n+    undo history.\n+\n+In such a situation, you would want to first revert the previous revert,\n+which would make the history look like this:\n+\n+ ---o---o---o---M---x---x---W---x---Y\n+               /\n+       ---A---B-------------------C---D\n+\n+where Y is the revert of W.  Such a \"revert of the revert\" can be done\n+with:\n+\n+    $ git revert W\n+\n+This history would (ignoring possible conflicts between what W and W..Y\n+changed) be equivalent to not having W nor Y at all in the history:\n+\n+ ---o---o---o---M---x---x-------x----\n+               /\n+       ---A---B-------------------C---D\n+\n+and merging the side branch again will not have conflict arising from an\n+earlier revert and revert of the revert.\n+\n+ ---o---o---o---M---x---x-------x-------*\n+               /                       /\n+       ---A---B-------------------C---D\n+\n+Of course the changes made in C and D still can conflict with what was\n+done by any of the x, but that is just a normal merge conflict.\n+\n+On the other hand, if the developers of the side branch discarded their\n+faulty A and B, and redone the changes on top of the updated master branch\n+after the revert, the history would have looked like this:\n+\n+ ---o---o---o---M---x---x---W---x---x\n+               /                 \\\n+       ---A---B                   A'--B'--C'\n+\n+If you reverted the revert in such a case as in the previous example:\n+\n+ ---o---o---o---M---x---x---W---x---x---Y---*\n+               /                 \\         /\n+       ---A---B                   A'--B'--C'\n+\n+where Y is the revert of W, A' and B'are rerolled A and B, and there may\n+also be a further fix-up C' on the side branch.  \"diff Y^..Y\" is similar\n+to \"diff -R W^..W\" (which in turn means it is similar to \"diff M^..M\"),\n+and \"diff A'^..C'\" by definition would be similar but different from that,\n+because it is a rerolled series of the earlier change.  There would be a\n+lot of overlapping change that results in conflicts.  So do not do \"revert\n+of revert\" blindly.\n+\n+ ---o---o---o---M---x---x---W---x---x\n+               /                 \\\n+       ---A---B                   A'--B'--C'\n+\n+In the history with rebased side branch, W (and M) are behind the merge\n+base of the updated branch and the tip of the master, and they should\n+merge without the past faulty merge and its revert getting in the way.\n+\n+To recap, these are two very different scenarios, and wants two very\n+different resolution strategies:\n+\n+ - If the faulty side branch was fixed by adding corrections on top, then\n+   doing a revert of the previous revert would be the right thing to do.\n+\n+ - If the faulty side branch whose effects were discarded by an earlier\n+   revert of a merge was rebuilt from scratch (i.e. rebasing and fixing,\n+   as you seem to have interpreted), then re-merging the result without\n+   doing anything else fancy would be the right thing to do.\n+\n+However, there are things to keep in mind when reverting a merge (and\n+reverting such a revert).\n+\n+For example, think about what reverting a merge (and then reverting the\n+revert) does to bisectability. Ignore the fact that the revert of a revert\n+is undoing it - just think of it as a \"single commit that does a lot\".\n+Because that is what it does.\n+\n+When you have a problem you are chasing down, and you hit a \"revert this\n+merge\", what you're hitting is essentially a single commit that contains\n+all the changes (but obviously in reverse) of all the commits that got\n+merged. So it's debugging hell, because now you don't have lots of small\n+changes that you can try to pinpoint which _part_ of it changes.\n+\n+But does it all work? Sure it does. You can revert a merge, and from a\n+purely technical angle, git did it very naturally and had no real\n+troubles. It just considered it a change from \"state before merge\" to\n+\"state after merge\", and that was it. Nothing complicated, nothing odd,\n+nothing really dangerous. Git will do it without even thinking about it.\n+\n+So from a technical angle, there's nothing wrong with reverting a merge,\n+but from a workflow angle it's something that you generally should try to\n+avoid.\n+\n+If at all possible, for example, if you find a problem that got merged\n+into the main tree, rather than revert the merge, try _really_ hard to\n+bisect the problem down into the branch you merged, and just fix it, or\n+try to revert the individual commit that caused it.\n+\n+Yes, it's more complex, and no, it's not always going to work (sometimes\n+the answer is: \"oops, I really shouldn't have merged it, because it wasn't\n+ready yet, and I really need to undo _all_ of the merge\"). So then you\n+really should revert the merge, but when you want to re-do the merge, you\n+now need to do it by reverting the revert.\n-- \n1.6.1.rc3\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"98460","messageId":"200812201612.37455.bss@iguanasuicide.net","threadId":"16808","inReplyTo":"20081220202702.6117@nanako3.lavabit.com","subject":"Re: [PATCH] Add a documentat on how to revert a faulty merge","fromName":"Boyd Stephen Smith Jr.","fromEmail":"bss@iguanasuicide.net","sentAt":"2008-12-20T22:12:33Z","receivedAt":"2008-12-20T22:12:33Z","isPatch":true,"sender":{"key":"bss@iguanasuicide.net","avatar":"https://gravatar.com/avatar/84b95eeff194b816c1568b1339e63e4b229825298664a9037b9f1ec713ead1e3?d=mp&s=160"},"body":"On Saturday 2008 December 20 05:27:02 Nanako Shiraishi wrote:\n> +Date: Fri, 19 Dec 2008 00:45:19 -0800\n> +From: Linus Torvalds <torvalds@linux-foundation.org>, Junio C Hamano\n> <gitster@pobox.com> +Subject: Re: Odd merge behaviour involving reverts\n> +Abstract: Sometimes a branch that was already merged to the mainline\n> + is later found to be faulty.  Linus and Junio give guidance on\n> + recovering from such a premature merge and continuing development\n> + after the offending branch is fixed.\n> +Message-ID: <7vocz8a6zk.fsf@gitster.siamese.dyndns.org>\n> +References: <alpine.LFD.2.00.0812181949450.14014@localhost.localdomain>\n> +\n> +Alan <alan@clueserver.org> said:\n\nI don't like the email headers as part of the documentation.  It would be \nbetter to have a title and abstract in prose.\n\nAlso, your email gave me some errors from 'git am':\n.dotest/patch:40: indent with spaces.\n               /\n.dotest/patch:57: indent with spaces.\n               /\n.dotest/patch:91: indent with spaces.\n               /\n.dotest/patch:103: indent with spaces.\n               /\n.dotest/patch:110: indent with spaces.\n               /                       /\nwarning: squelched 3 whitespace errors\nwarning: 8 lines add whitespace errors.\n\nThose errors aside, I think it's better formatted than what I had ready.  I \nalso think it would be nice to also modify the git-revert manpage to \nreference this documentation in the description on the -m option.\n-- \nBoyd Stephen Smith Jr.                     ,= ,-_-. =. \nbss@iguanasuicide.net                     ((_/)o o(\\_))\nICQ: 514984 YM/AIM: DaTwinkDaddy           `-'(. .)`-' \nhttp://iguanasuicide.net/                      \\_/     \n"},{"id":"98471","messageId":"7vocz6tfs8.fsf@gitster.siamese.dyndns.org","threadId":"16808","inReplyTo":"200812201612.37455.bss@iguanasuicide.net","subject":"Re: [PATCH] Add a documentat on how to revert a faulty merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-21T02:37:11Z","receivedAt":"2008-12-21T02:37:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Boyd Stephen Smith Jr.\" <bss@iguanasuicide.net> writes:\n\n> On Saturday 2008 December 20 05:27:02 Nanako Shiraishi wrote:\n>> +Date: Fri, 19 Dec 2008 00:45:19 -0800\n>> +From: Linus Torvalds <torvalds@linux-foundation.org>, Junio C Hamano\n>> <gitster@pobox.com> +Subject: Re: Odd merge behaviour involving reverts\n>> +Abstract: Sometimes a branch that was already merged to the mainline\n>> + is later found to be faulty.  Linus and Junio give guidance on\n>> + recovering from such a premature merge and continuing development\n>> + after the offending branch is fixed.\n>> +Message-ID: <7vocz8a6zk.fsf@gitster.siamese.dyndns.org>\n>> +References: <alpine.LFD.2.00.0812181949450.14014@localhost.localdomain>\n>> +\n>> +Alan <alan@clueserver.org> said:\n>\n> I don't like the email headers as part of the documentation.  It would be \n> better to have a title and abstract in prose.\n\nThe above follows the style of other files in Documentation/howto; if you\nlook at the build procedure of howto-index, you will notice that some of\nthese are required part of the documentation.\n\n> Also, your email gave me some errors from 'git am':\n> .dotest/patch:40: indent with spaces.\n>                /\n\nThat is \"C program source\" rules in action.\n\nI thought we had .gitattributes set up in Documentation/ area that applies\ndifferent rules to these?  Maybe they have not been tested with things in\nhowto.  \n"}]}