{"thread":{"id":"15540","subject":"[IRC/patches] Failed octopus merge does not clean up","startedAt":"2008-09-15T22:48:19Z","lastAt":"2008-09-19T20:28:15Z","messageCount":17,"participants":["Thomas Rast","Junio C Hamano","Avery Pennarun","Jakub Narebski","Andreas Ericsson","Miklos Vajna","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"90783","messageId":"200809160048.31443.trast@student.ethz.ch","threadId":"15540","inReplyTo":null,"subject":"[IRC/patches] Failed octopus merge does not clean up","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2008-09-15T22:48:19Z","receivedAt":"2008-09-15T22:48:19Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Hi *\n\nJames \"jammyd\" Mulcahy pointed out on IRC that the octopus merge\nstrategy doesn't properly clean up behind itself.  To wit:\n\n  git init\n  echo initial > foo\n  git add foo\n  git commit -m initial\n  echo a > foo\n  git commit -m a foo\n  git checkout -b b HEAD^\n  echo b > foo\n  git commit -m b foo\n  git checkout -b c HEAD^\n  echo c > foo\n  git commit -m c foo\n  git checkout master\n  git merge b c\n\nThe merge says\n\n  Trying simple merge with 5b3e4bb1c2d88d6967fb575729fbfc86df5eaec9\n  Simple merge did not work, trying automatic merge.\n  Auto-merging foo\n  ERROR: Merge conflict in foo\n  fatal: merge program failed\n  Automated merge did not work.\n  Should not be doing an Octopus.\n  Merge with strategy octopus failed.\n\nSo far so good.  However, 'git status' claims\n\n  #       unmerged:   foo\n\nand indeed the contents of 'foo' are the conflicted merge between\n'master' and 'b', yet there is no .git/MERGE_HEAD.  This behaviour is\nidentical for 1.5.6 and 1.6.0.2, so it is not caused by the merge\nrewrite as a builtin.  Shouldn't it either really clean up, or really\nleave the repo in a conflicted merge state?  (I'm following up with a\npatch that turns the above into a test.  Octopus doesn't really have\nmany tests, does it?)\n\nOn the code path to the \"Merge with strategy %s failed\" message,\nbuiltin-merge.c:1134 runs restore_state() which runs reset_hard().\nBut (as Miklos pointed out) that cannot actually do 'git reset --hard'\nbecause it is possible (though not recommended, see below) to start a\nmerge with a dirty index.\n\nJakub mentioned that there are only three index stages for a three-way\nmerge, so a conflicted n-way (simultaneous) merge is not really\npossible.\n\nThe merge manpage should warn about merging with uncommitted changes.\nIt recommends 'git rebase --hard' to abort during conflicts, but does\nnot mention that this throws away said changes.  I'm following up with\na patch for this.\n\n- Thomas\n\n-- \nThomas Rast\ntrast@student.ethz.ch\n\n\n"},{"id":"90784","messageId":"1221518994-26111-1-git-send-email-trast@student.ethz.ch","threadId":"15540","inReplyTo":"200809160048.31443.trast@student.ethz.ch","subject":"[PATCH] Add test that checks octopus merge cleanup","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2008-09-15T22:49:53Z","receivedAt":"2008-09-15T22:49:53Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Currently, a conflicted octopus merge leaves the repository in a\n\"halfway into the merge state\", where .git/MERGE_HEAD is missing but\nthe files are listed as conflicted in the index and have conflict\nmarkers in them.  It should either clean up everything, or add a\nMERGE_HEAD.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\n\n---\n t/t7607-merge-octopus-cleanup.sh |   31 +++++++++++++++++++++++++++++++\n 1 files changed, 31 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t7607-merge-octopus-cleanup.sh b/t/t7607-merge-octopus-cleanup.sh\nnew file mode 100755\nindex 0000000..4d82867\n--- /dev/null\n+++ b/t/t7607-merge-octopus-cleanup.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+\n+test_description='git merge\n+\n+Testing that conflicting octopus merge fails cleanly.'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\techo initial > foo &&\n+\tgit add foo &&\n+\tgit commit -m initial &&\n+\techo a > foo &&\n+\tgit commit -m a foo &&\n+\tgit checkout -b b HEAD^ &&\n+\techo b > foo &&\n+\tgit commit -m b foo &&\n+\tgit checkout -b c HEAD^ &&\n+\techo c > foo &&\n+\tgit commit -m c foo &&\n+\tgit checkout master\n+'\n+\n+test_expect_failure 'conflicted octopus merge' '\n+\ttest_must_fail git merge b c &&\n+\ttest -z \"$(git ls-files --unmerged)\" &&\n+\ttest \"$(cat foo)\" == a &&\n+\ttest ! -f .git/MERGE_HEAD\n+'\n+\n+test_done\n-- \ntg: (1293c95..) t/test-octopus-cleanup (depends on: origin/master)\n"},{"id":"90785","messageId":"1221518994-26111-2-git-send-email-trast@student.ethz.ch","threadId":"15540","inReplyTo":"1221518994-26111-1-git-send-email-trast@student.ethz.ch","subject":"[PATCH] Documentation: warn against merging in a dirty tree","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2008-09-15T22:49:54Z","receivedAt":"2008-09-15T22:49:54Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Merging in a dirty tree is usually a bad idea because you need to\nreset --hard to abort; but the docs didn't say anything about it.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\n\n---\n Documentation/git-merge.txt |    5 +++++\n 1 files changed, 5 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt\nindex 685e1fe..3798e16 100644\n--- a/Documentation/git-merge.txt\n+++ b/Documentation/git-merge.txt\n@@ -22,6 +22,11 @@ The second syntax (<msg> `HEAD` <remote>) is supported for\n historical reasons.  Do not use it from the command line or in\n new scripts.  It is the same as `git merge -m <msg> <remote>`.\n \n+NOTE: Usually it is a bad idea to merge with a dirty tree or index.\n+      If you get conflicts and want to abort (instead of resolving),\n+      you need to `git reset \\--hard` which loses the uncommitted\n+      changes.\n+\n \n OPTIONS\n -------\n-- \ntg: (1293c95..) t/doc-merge-reset (depends on: origin/master)\n"},{"id":"90787","messageId":"7v63ox9e20.fsf@gitster.siamese.dyndns.org","threadId":"15540","inReplyTo":"200809160048.31443.trast@student.ethz.ch","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-15T23:36:55Z","receivedAt":"2008-09-15T23:36:55Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> The merge says\n>\n>   Trying simple merge with 5b3e4bb1c2d88d6967fb575729fbfc86df5eaec9\n>   Simple merge did not work, trying automatic merge.\n>   Auto-merging foo\n>   ERROR: Merge conflict in foo\n>   fatal: merge program failed\n>   Automated merge did not work.\n>   Should not be doing an Octopus.\n>   Merge with strategy octopus failed.\n>\n> So far so good.  However, 'git status' claims\n> ...  This behaviour is\n> identical for 1.5.6 and 1.6.0.2, so it is not caused by the merge\n> rewrite as a builtin.  Shouldn't it either really clean up, or really\n> leave the repo in a conflicted merge state?  (I'm following up with a\n> patch that turns the above into a test.  Octopus doesn't really have\n> many tests, does it?)\n\nYour analysis is correct --- this has been the correct/established\nbehaviour of Octopus from day one.\n\nRead the second from the last line of what you were told by git.  Run \"git\nreset --hard\" after that, perhaps.\n"},{"id":"90788","messageId":"7vtzch7z7u.fsf@gitster.siamese.dyndns.org","threadId":"15540","inReplyTo":"1221518994-26111-2-git-send-email-trast@student.ethz.ch","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-15T23:42:45Z","receivedAt":"2008-09-15T23:42:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> Merging in a dirty tree is usually a bad idea because you need to\n> reset --hard to abort; but the docs didn't say anything about it.\n\nStrictly speaking, you do not have to worry about anything if (1) all of\nyour work tree changes are easily reproducible (Linus's keeping a new\nEXTRAVERSION in his Makefile, never staged nor committed is an often cited\nexample), or (2) you know beforehand that a merge with the other party\nwill not touch the part you have local changes that you care about.\n\nIn other words, you need to know what you are doing, and a warning with\n\"usually it is a bad idea\" would be an appropriate thing to do.\n"},{"id":"90789","messageId":"200809160147.45095.trast@student.ethz.ch","threadId":"15540","inReplyTo":"7v63ox9e20.fsf@gitster.siamese.dyndns.org","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2008-09-15T23:47:42Z","receivedAt":"2008-09-15T23:47:42Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano wrote:\n> Thomas Rast <trast@student.ethz.ch> writes:\n[...]\n> >   Should not be doing an Octopus.\n[...]\n> > Shouldn't it either really clean up, or really\n> > leave the repo in a conflicted merge state?\n[...]\n> Your analysis is correct --- this has been the correct/established\n> behaviour of Octopus from day one.\n\nIncluding not cleaning up the half-merged state?  If the answer is\n\"yes\", then so be it, merge-octopus has been on this project longer\nthan I have ;-)\n\nHowever,\n\n> Run \"git reset --hard\" after that, perhaps.\n\nwasn't immediately obvious to the end-user (jammyd in this case),\nwhich started the discussion.\n\n-- \nThomas Rast\ntrast@student.ethz.ch\n\n"},{"id":"90790","messageId":"32541b130809151653w27d7876fp35e0967d597ae2a9@mail.gmail.com","threadId":"15540","inReplyTo":"7vtzch7z7u.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2008-09-15T23:53:07Z","receivedAt":"2008-09-15T23:53:07Z","isPatch":true,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Mon, Sep 15, 2008 at 7:42 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Thomas Rast <trast@student.ethz.ch> writes:\n>\n>> Merging in a dirty tree is usually a bad idea because you need to\n>> reset --hard to abort; but the docs didn't say anything about it.\n>\n> Strictly speaking, you do not have to worry about anything if (1) all of\n> your work tree changes are easily reproducible (Linus's keeping a new\n> EXTRAVERSION in his Makefile, never staged nor committed is an often cited\n> example), or (2) you know beforehand that a merge with the other party\n> will not touch the part you have local changes that you care about.\n>\n> In other words, you need to know what you are doing, and a warning with\n> \"usually it is a bad idea\" would be an appropriate thing to do.\n\nBut how do you abort a *failed* merge in a situation like Linus's\nexample?  \"git reset --hard HEAD\" would destroy the unstaged Makefile\nchange.\n\nI would love to know the answer to this for my own work, and I guess\nit would be relevant to the documentation too.\n\nHave fun,\n\nAvery\n"},{"id":"90793","messageId":"7vprn57y45.fsf@gitster.siamese.dyndns.org","threadId":"15540","inReplyTo":"32541b130809151653w27d7876fp35e0967d597ae2a9@mail.gmail.com","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-16T00:06:34Z","receivedAt":"2008-09-16T00:06:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avery Pennarun\" <apenwarr@gmail.com> writes:\n\n> But how do you abort a *failed* merge in a situation like Linus's\n> example?  \"git reset --hard HEAD\" would destroy the unstaged Makefile\n> change.\n\n\"All of your work tree changes are easily reproducible\" implies you do not\nmind losing them, Ok?\n\nAlso \"git reset HEAD\" (that is, without --hard) would not touch the work\ntree changes.  You need to remove the work-tree cruft left by new files\nyourself, if you go this route, though.  New files are rare enough so it\nmay be more appropriate (and you can \"git clean -n $that_subdirectory\" to\nenumerate them).\n\nIt all depends on your workflow.\n"},{"id":"90795","messageId":"7vhc8h7xgj.fsf@gitster.siamese.dyndns.org","threadId":"15540","inReplyTo":"7v63ox9e20.fsf@gitster.siamese.dyndns.org","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-16T00:20:44Z","receivedAt":"2008-09-16T00:20:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Thomas Rast <trast@student.ethz.ch> writes:\n>\n>> The merge says\n>>\n>>   Trying simple merge with 5b3e4bb1c2d88d6967fb575729fbfc86df5eaec9\n>>   Simple merge did not work, trying automatic merge.\n>>   Auto-merging foo\n>>   ERROR: Merge conflict in foo\n>>   fatal: merge program failed\n>>   Automated merge did not work.\n>>   Should not be doing an Octopus.\n>>   Merge with strategy octopus failed.\n> ...\n> Read the second from the last line of what you were told by git.  Run \"git\n> reset --hard\" after that, perhaps.\n\nBy the way, there are three failure modes in Octopus.\n\n (0) your index (not work tree) is dirty; this is not limited to octopus\n     merge but any merge will be refused;\n\n (1) while it merges other heads one-by-one, it gets conflicts on an\n     earlier one, before it even attempts to merge all of them.  Recording\n     the heads that it so far attempted to merge in MERGE_HEAD is wrong\n     (the result won't be an Octopus the end user wanted to carete), and\n     recording all the heads the user gave in MERGE_HEAD is even more\n     wrong (it hasn't even looked at the later heads yet, so there is no\n     way for the index or work tree to contain anything from them).\n\n     The above is hitting this case.\n\n (2) it gets conflicts while merging the _last_ head.  It records\n     MERGE_HEAD and allows you to record the resolved result.\n\nI think originally we treated (1) and (2) the same way, because an Octopus\nis to record the most trivial merge with more than 2 legs, and a rough\ndefinition of \"the most trivial\" is \"tracks of totally independent works;\nyou could merge them one by one and _in any order_, and the result won't\nmatter because they are logically independent.  However if they are _so_\nindependent, why not record them as merged in one step (i.e. octopus),\ninstead of insisting on recording in what order you merged them\".\n\nObviously, if you get a conflict during Octopus creation, they were not\ntracks of totally independent works, and that is where the \"Should not\" in\nthe message comes from.\n\nWe later relaxed it to allow a conflict at the last step, not because\nrecording an Octopus with nontrivial merge is particuarly a good idea we\nshould encourage, but because there simply weren't reason not to.\n"},{"id":"90871","messageId":"200809170053.15341.jnareb@gmail.com","threadId":"15540","inReplyTo":"7vhc8h7xgj.fsf@gitster.siamese.dyndns.org","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-09-16T22:53:13Z","receivedAt":"2008-09-16T22:53:13Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia wtorek 16. września 2008 02:20, Junio C Hamano napisał:\n> Junio C Hamano <gitster@pobox.com> writes:\n>> Thomas Rast <trast@student.ethz.ch> writes:\n>>\n>>> The merge says\n>>>\n>>>   Trying simple merge with 5b3e4bb1c2d88d6967fb575729fbfc86df5eaec9\n>>>   Simple merge did not work, trying automatic merge.\n>>>   Auto-merging foo\n>>>   ERROR: Merge conflict in foo\n>>>   fatal: merge program failed\n>>>   Automated merge did not work.\n>>>   Should not be doing an Octopus.\n>>>   Merge with strategy octopus failed.\n>> ...\n>> Read the second from the last line of what you were told by git.  Run \"git\n>> reset --hard\" after that, perhaps.\n\nThe problem, as far as I understand it, is not that octopus merge fails.\nThe problem is that it fails halfway, and it leaves working are in\ninconsistent state: git-status output with its \"unmerged\" suggests that\nwe are in the middle of the merge, but we are not.\n\n> By the way, there are three failure modes in Octopus.\n> \n>  (0) your index (not work tree) is dirty; this is not limited to octopus\n>      merge but any merge will be refused;\n\nIIRC the idea of stashing away changes, doing merge, and then unstashing\nwas shot down as encouraging bad workflows, and more often than not\nleading only to mess in workdir and index.\n\n>  (1) while it merges other heads one-by-one, it gets conflicts on an\n>      earlier one, before it even attempts to merge all of them.  Recording\n>      the heads that it so far attempted to merge in MERGE_HEAD is wrong\n>      (the result won't be an Octopus the end user wanted to carete), and\n>      recording all the heads the user gave in MERGE_HEAD is even more\n>      wrong (it hasn't even looked at the later heads yet, so there is no\n>      way for the index or work tree to contain anything from them).\n> \n>      The above is hitting this case.\n\nIMVHO the correct solution would be to rollback changes to the state\nbefore attempting a merge. I'd rather 'octopus' did its thing as\ntransaction; contrary to ordinary merges if merge fails it doesn't\nmean necessary that it is in the state of resolvable conflict, state\nwe can stop at. Perhaps (if it is still a shell script, doing git-stash\nat beginning, and either dropping or popping the stash at the end;\nor just saving old index if it is built-in).\n\n\nBTW. does it mean that \"git merge a b\" might be not the same as\n\"git merge b a\"?\n\n>  (2) it gets conflicts while merging the _last_ head.  It records\n>      MERGE_HEAD and allows you to record the resolved result.\n> \n> I think originally we treated (1) and (2) the same way, because an Octopus\n> is to record the most trivial merge with more than 2 legs, and a rough\n> definition of \"the most trivial\" is \"tracks of totally independent works;\n> you could merge them one by one and _in any order_, and the result won't\n> matter because they are logically independent.  However if they are _so_\n> independent, why not record them as merged in one step (i.e. octopus),\n> instead of insisting on recording in what order you merged them\".\n> \n> Obviously, if you get a conflict during Octopus creation, they were not\n> tracks of totally independent works, and that is where the \"Should not\" in\n> the message comes from.\n> \n> We later relaxed it to allow a conflict at the last step, not because\n> recording an Octopus with nontrivial merge is particuarly a good idea we\n> should encourage, but because there simply weren't reason not to.\n\nWell, octopus merge could simply fail when merge is nontrivial (not\nlimited to being tree-level merge only).\n\n-- \nJakub Narebski\nPoland\n"},{"id":"90899","messageId":"48D0A776.1000009@op5.se","threadId":"15540","inReplyTo":"200809170053.15341.jnareb@gmail.com","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2008-09-17T06:45:10Z","receivedAt":"2008-09-17T06:45:10Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Jakub Narebski wrote:\n> Dnia wtorek 16. września 2008 02:20, Junio C Hamano napisał:\n>> Junio C Hamano <gitster@pobox.com> writes:\n>>> Thomas Rast <trast@student.ethz.ch> writes:\n>>>\n>>>> The merge says\n>>>>\n>>>>   Trying simple merge with 5b3e4bb1c2d88d6967fb575729fbfc86df5eaec9\n>>>>   Simple merge did not work, trying automatic merge.\n>>>>   Auto-merging foo\n>>>>   ERROR: Merge conflict in foo\n>>>>   fatal: merge program failed\n>>>>   Automated merge did not work.\n>>>>   Should not be doing an Octopus.\n>>>>   Merge with strategy octopus failed.\n>>> ...\n>>> Read the second from the last line of what you were told by git.  Run \"git\n>>> reset --hard\" after that, perhaps.\n> \n> The problem, as far as I understand it, is not that octopus merge fails.\n> The problem is that it fails halfway, and it leaves working are in\n> inconsistent state: git-status output with its \"unmerged\" suggests that\n> we are in the middle of the merge, but we are not.\n> \n>> By the way, there are three failure modes in Octopus.\n>>\n>>  (0) your index (not work tree) is dirty; this is not limited to octopus\n>>      merge but any merge will be refused;\n> \n> IIRC the idea of stashing away changes, doing merge, and then unstashing\n> was shot down as encouraging bad workflows, and more often than not\n> leading only to mess in workdir and index.\n> \n>>  (1) while it merges other heads one-by-one, it gets conflicts on an\n>>      earlier one, before it even attempts to merge all of them.  Recording\n>>      the heads that it so far attempted to merge in MERGE_HEAD is wrong\n>>      (the result won't be an Octopus the end user wanted to carete), and\n>>      recording all the heads the user gave in MERGE_HEAD is even more\n>>      wrong (it hasn't even looked at the later heads yet, so there is no\n>>      way for the index or work tree to contain anything from them).\n>>\n>>      The above is hitting this case.\n> \n> IMVHO the correct solution would be to rollback changes to the state\n> before attempting a merge. I'd rather 'octopus' did its thing as\n> transaction; contrary to ordinary merges if merge fails it doesn't\n> mean necessary that it is in the state of resolvable conflict, state\n> we can stop at. Perhaps (if it is still a shell script, doing git-stash\n> at beginning, and either dropping or popping the stash at the end;\n> or just saving old index if it is built-in).\n> \n> \n> BTW. does it mean that \"git merge a b\" might be not the same as\n> \"git merge b a\"?\n> \n\nNo. Git merges all the sub-things together and then merges the result\nof that jumble into the branch you're on.\n\nSomeone might have to correct me on that, but that's as far as I've\nunderstood it.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"90903","messageId":"200809171011.06714.jnareb@gmail.com","threadId":"15540","inReplyTo":"48D0A776.1000009@op5.se","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-09-17T08:11:02Z","receivedAt":"2008-09-17T08:11:02Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Andreas Ericsson wrote:\n> Jakub Narebski wrote:\n> > Junio C Hamano wrote:\n\n>>>  (1) while it merges other heads one-by-one, it gets conflicts on an\n>>>      earlier one, before it even attempts to merge all of them.  Recording\n>>>      the heads that it so far attempted to merge in MERGE_HEAD is wrong\n>>>      (the result won't be an Octopus the end user wanted to carete), and\n>>>      recording all the heads the user gave in MERGE_HEAD is even more\n>>>      wrong (it hasn't even looked at the later heads yet, so there is no\n>>>      way for the index or work tree to contain anything from them).\n>>>\n>>>      The above is hitting this case.\n[...] \n \n>> BTW. does it mean that \"git merge a b\" might be not the same as\n>> \"git merge b a\"?\n>> \n> \n> No. Git merges all the sub-things together and then merges the result\n> of that jumble into the branch you're on.\n> \n> Someone might have to correct me on that, but that's as far as I've\n> understood it.\n\n>From what I understand from above explanation, and from thread on git\nmailing list about better implementation of and documenting finding\nmerge bases for multiple heads, I think octopus merge is done by merging\n[reduced] heads one by one into given branch.\n\nThis means that \"git merge a b\" does internally \"git merge a; git merge b\"\nas I understand it.\n-- \nJakub Narebski\nPoland\n"},{"id":"90953","messageId":"20080917155933.GI4829@genesis.frugalware.org","threadId":"15540","inReplyTo":"200809171011.06714.jnareb@gmail.com","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-09-17T15:59:33Z","receivedAt":"2008-09-17T15:59:33Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Wed, Sep 17, 2008 at 10:11:02AM +0200, Jakub Narebski <jnareb@gmail.com> wrote:\n> >> BTW. does it mean that \"git merge a b\" might be not the same as\n> >> \"git merge b a\"?\n> >> \n> > \n> > No. Git merges all the sub-things together and then merges the result\n> > of that jumble into the branch you're on.\n> > \n> > Someone might have to correct me on that, but that's as far as I've\n> > understood it.\n> \n> From what I understand from above explanation, and from thread on git\n> mailing list about better implementation of and documenting finding\n> merge bases for multiple heads, I think octopus merge is done by merging\n> [reduced] heads one by one into given branch.\n> \n> This means that \"git merge a b\" does internally \"git merge a; git merge b\"\n> as I understand it.\n\nSure, but given that both 'a' and 'b' merged (so none of them is subset\nof the other, for example so that reduce_heads() would drop one of them)\nthe order of the parents will be different so the resulting commit will\ndiffer. The resulting tree will no, I think.\n"},{"id":"90957","messageId":"48D13317.3090301@op5.se","threadId":"15540","inReplyTo":"20080917155933.GI4829@genesis.frugalware.org","subject":"Re: [IRC/patches] Failed octopus merge does not clean up","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2008-09-17T16:40:55Z","receivedAt":"2008-09-17T16:40:55Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Miklos Vajna wrote:\n> On Wed, Sep 17, 2008 at 10:11:02AM +0200, Jakub Narebski <jnareb@gmail.com> wrote:\n>>>> BTW. does it mean that \"git merge a b\" might be not the same as\n>>>> \"git merge b a\"?\n>>>>\n>>> No. Git merges all the sub-things together and then merges the result\n>>> of that jumble into the branch you're on.\n>>>\n>>> Someone might have to correct me on that, but that's as far as I've\n>>> understood it.\n>> From what I understand from above explanation, and from thread on git\n>> mailing list about better implementation of and documenting finding\n>> merge bases for multiple heads, I think octopus merge is done by merging\n>> [reduced] heads one by one into given branch.\n>>\n>> This means that \"git merge a b\" does internally \"git merge a; git merge b\"\n>> as I understand it.\n> \n> Sure, but given that both 'a' and 'b' merged (so none of them is subset\n> of the other, for example so that reduce_heads() would drop one of them)\n> the order of the parents will be different so the resulting commit will\n> differ. The resulting tree will no, I think.\n\n\nI got it wrong (not wrt reduced heads, but still). My apologies.\n\nIf octopus (the program/strategy/whatever) continues to merge after a\nbranch conflicting against the currently checked out branch (let's call\nit \"master\"), the resulting tree may not differ, but then again, it might.\nOTOH, if octopus quits the merge after having encountered a conflict, the\norder the branches to merge were passed will always have an impact.\n\nLet's say you have two branches, \"clean\" and \"conflict\". Which one is\nwhich should be obvious here.\n\n\tgit merge clean conflict\n\nwill produce a tree with 'master', 'clean' and a conflicted merge of\n'conflict', while\n\n\tgit merge conflict clean\n\nwill produce a tree with 'master' and a conflicted merge of 'conflict'.\n\nIn short, backing out the entire merge in case of a conflict is almost\ncertainly the only sane thing to do. If one branch depends on another\nto merge cleanly, a different approach should have been taken (depending\nbranch should have been rebased onto the dependent one prior to merging),\nbut the merge *might* succeed depending on in which order the other\nbranches are given as arguments. It's not a very clever idea to merge\nsomething like that though, as bisection will invariably have to mark the\nentire depending branch as BAD, although the merge itself could obviously\nbe a good one.\n\nClearly, an octopus merge should not be undertaken without knowing very\nwell what it is one is merging in.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"91030","messageId":"alpine.LFD.1.10.0809180804100.3337@nehalem.linux-foundation.org","threadId":"15540","inReplyTo":"32541b130809151653w27d7876fp35e0967d597ae2a9@mail.gmail.com","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2008-09-18T15:15:13Z","receivedAt":"2008-09-18T15:15:13Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 15 Sep 2008, Avery Pennarun wrote:\n> \n> But how do you abort a *failed* merge in a situation like Linus's\n> example?  \"git reset --hard HEAD\" would destroy the unstaged Makefile\n> change.\n\nAs mentioned by others, sometimes you are simply willing to take the risk. \nIf I have dirty data, I still want to merge, because (a) my dirty data is \na _convenience_ and (b) the risk of me having to do a \"git reset\" is \npretty low anyway.\n\nThat said, it's actually kind of sad that we don't expose a real \ncapability that the git plumbing does have. Namely\n\n\tgit read-tree -u -m HEAD ORIG_HEAD\n\nshould do the right thing if you want to undo a merge (except it doesn't \nactually write ORIG_HEAD to be the new head: you could use \"git reset\" \nwith --soft to do that, or just git update-ref).\n\nSo it _may_ be that something like\n\n\t[alias]\n\t\tundo = !git read-tree -u -m HEAD ORIG_HEAD && git reset --soft ORIG_HEAD\n\nwould actually give you \"git undo\". \n\nSo we have the technology, and we just don't _expose_ that capability as a \n\"git reset\" thing. And we probably should. In fact, that is often the \nthing people really want, and it would have made sense to have it as the \ndefault action, but the initial design for \"git reset\" was literally as a \nway to get you out of a sticky corner when you had unmerged entries and \nyou just wanted to throw away crud.\n\nNOTE NOTE NOTE! I did _not_ test that the git read-tree thing actually \nworks, or that the above alias does the right thing. Caveat testor! You're \non your own. But I agree that we should have something like that.\n\n\t\tLinus\n"},{"id":"91064","messageId":"32541b130809181118s1a4cffa6u3ad139aa05443ea6@mail.gmail.com","threadId":"15540","inReplyTo":"alpine.LFD.1.10.0809180804100.3337@nehalem.linux-foundation.org","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2008-09-18T18:18:41Z","receivedAt":"2008-09-18T18:18:41Z","isPatch":true,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Thu, Sep 18, 2008 at 11:15 AM, Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n> On Mon, 15 Sep 2008, Avery Pennarun wrote:\n>>\n>> But how do you abort a *failed* merge in a situation like Linus's\n>> example?  \"git reset --hard HEAD\" would destroy the unstaged Makefile\n>> change.\n>\n> As mentioned by others, sometimes you are simply willing to take the risk.\n> If I have dirty data, I still want to merge, because (a) my dirty data is\n> a _convenience_ and (b) the risk of me having to do a \"git reset\" is\n> pretty low anyway.\n\nIn that case, my next question is how you pull off (b), because that's\n*way* better than just being able to undo when I get myself into\ntrouble :)  I do and then reset test merges all the time.\n\n> That said, it's actually kind of sad that we don't expose a real\n> capability that the git plumbing does have. Namely\n>\n>        git read-tree -u -m HEAD ORIG_HEAD\n>\n> should do the right thing if you want to undo a merge (except it doesn't\n> actually write ORIG_HEAD to be the new head: you could use \"git reset\"\n> with --soft to do that, or just git update-ref).\n\nHmm,\n\n   $ git read-tree -u -m HEAD ORIG_HEAD\n   fatal: you need to resolve your current index first\n\nIt appears that the above would be great for undoing a\n*non*conflicting merge, but that's not as important ;)\n\n> So it _may_ be that something like\n>\n>        [alias]\n>                undo = !git read-tree -u -m HEAD ORIG_HEAD && git reset --soft ORIG_HEAD\n>\n> would actually give you \"git undo\".\n>\n> So we have the technology, and we just don't _expose_ that capability as a\n> \"git reset\" thing. And we probably should. In fact, that is often the\n> thing people really want, and it would have made sense to have it as the\n> default action, but the initial design for \"git reset\" was literally as a\n> way to get you out of a sticky corner when you had unmerged entries and\n> you just wanted to throw away crud.\n\nNote that if we were going to do an undo, it would be nice to be\ncareful about allowing multiple consecutive undos.  \"git undo; git\nundo;\" shouldn't be a no-op, it should undo two things.  At least,\nthat's how the rest of the world (okay, my text editor) works.  \"git\nredo\" could be the opposite of \"git undo\".\n\nI imagine some trick using the reflog would thus be better here than\nupdating ORIG_HEAD.\n\nSince that's a lot of work, I'd propose having a first pass at the\nundo operation use ORIG_HEAD and then just delete or rename ORIG_HEAD,\nso that 'git undo; git undo' is meaningless.\n\nHave fun,\n\nAvery\n"},{"id":"91141","messageId":"7vljxnswww.fsf@gitster.siamese.dyndns.org","threadId":"15540","inReplyTo":"alpine.LFD.1.10.0809180804100.3337@nehalem.linux-foundation.org","subject":"Re: [PATCH] Documentation: warn against merging in a dirty tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-19T20:28:15Z","receivedAt":"2008-09-19T20:28:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> That said, it's actually kind of sad that we don't expose a real \n> capability that the git plumbing does have. Namely\n>\n> \tgit read-tree -u -m HEAD ORIG_HEAD\n\nI do not think this is quite enough.  \"read-tree --reset -u\" is probably\ncloser, but it may discard the entries added (and got conflicted) by the\nmerge before actually updating the working tree (the right thing there\nwould be to remove them).\n"}]}