{"thread":{"id":"13241","subject":"[PATCH 4/5] Head reduction before selecting merge strategy","startedAt":"2008-04-24T05:52:07Z","lastAt":"2008-05-04T04:52:32Z","messageCount":3,"participants":["Sverre Hvammen Johansen","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"75133","messageId":"402c10cd0804232252g43606767r10344ebbb2a44af9@mail.gmail.com","threadId":"13241","inReplyTo":null,"subject":"[PATCH 4/5] Head reduction before selecting merge strategy","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-04-24T05:52:07Z","receivedAt":"2008-04-24T05:52:07Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"See the documentation for an explanation of this feature.\n\nSigned-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>\n---\n Documentation/git-merge.txt |   43 ++++++++++++++++++++++++++++++++++++-\n git-merge.sh                |   50 ++++++++++++++++++++++++-------------------\n 2 files changed, 70 insertions(+), 23 deletions(-)\n\ndiff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt\nindex 2af33d8..f6bc96f 100644\n--- a/Documentation/git-merge.txt\n+++ b/Documentation/git-merge.txt\n@@ -36,7 +36,7 @@ include::merge-options.txt[]\n <remote>::\n        Other branch head merged into our branch.  You need at\n        least one <remote>.  Specifying more than one <remote>\n-       obviously means you are trying an Octopus.\n+       usually means you are trying an Octopus.\n\n\n include::fast-forward-options.txt[]\n@@ -133,6 +133,47 @@ merge (which is typically a fraction of the whole\ntree), you can\n have local modifications in your working tree as long as they do\n not overlap with what the merge updates.\n\n+If more than one commit are specified on the command line, git will\n+try to reduce the number of commits used (reduced parents) by\n+eliminating commits than can be reached from other commits.  The\n+commit message will reflect the commits specified on the command line\n+but the merge strategy will be selected based on the reduced parents\n+including `HEAD`.  The reduced parents are the parents recorded in the\n+merge commit object.\n+\n+The following shows master and three topic branches.  topicB is based\n+on topicA, topicA is previously branched off from master, and topicC\n+is based on the tip of the master branch:\n+\n+------------\n+                    o---o---o  topicB\n+                   /\n+          o---o---o  topicA\n+         /\n+    o---o---o---o---o---o  master\n+                         \\\n+                          o---o  topicC\n+------------\n+\n+Merging topicA, B and C to the master branch will select the merge\n+strategy based on the three branches master, topicB, and topicC\n+(topicA is eliminated since it can be reached from topicB).  topicB\n+and topicC are the reduced parents and are therefore the only\n+parents recorded in the merge commit object:\n+\n+------------\n+         $ git checkout master\n+         $ git merge topicA topicB topicC\n+\n+                    o---o---o  topicB\n+                   /         \\\n+          o---o---o  topicA   \\\n+         /                     \\\n+    o---o---o---o---o---o       o  master\n+                         \\     /\n+                          o---o  topicC\n+------------\n+\n When there are conflicts, these things happen:\n\n 1. `HEAD` stays the same.\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 7c34b6c..7c70c56 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -337,11 +337,16 @@ set x $remoteheads ; shift\n\n find_reduced_parents \"$@\"\n\n-actual_parents=$(git rev-parse \"$@\")\n+# ff_head may be included here or later in actual parents\n+if test -n \"$reduced_parents\"\n+then\n+       test $head = $ff_head ||\n+               reduced_parents=\"$ff_head$LF$reduced_parents\"\n+fi\n\n case \"$use_strategies\" in\n '')\n-       case \"$actual_parents\" in\n+       case \"$reduced_parents\" in\n        ?*\"$LF\"?*)\n                var=\"`git config --get pull.octopus`\"\n                if test -n \"$var\"\n@@ -406,17 +411,23 @@ then\n                finish \"$new_head\" \"$msg\" || exit\n                dropsave\n                exit 0\n+       else\n+               reduced_parents=\"$ff_head\"\n+               ff_head=$head\n        fi\n+else\n+       test $head != $ff_head -a $fast_forward = never &&\n+               reduced_parents=\"$ff_head$LF$reduced_parents\"\n fi\n\n-case \"$actual_parents\" in\n+case \"$reduced_parents\" in\n ?*\"$LF\"?*)\n-       # We have more than one actual parent\n-       common=$(git show-branch --merge-base $head $actual_parents)\n+       # We have more than one reduced parent\n+       common=$(git show-branch --merge-base $head $reduced_parents)\n        ;;\n *)\n-       # We have exactly one actual parent\n-       test \"$common\" != not_queried || common=$(git merge-base --all\n$head $actual_parents)\n+       # We have exactly one reduced parent\n+       test \"$common\" != not_queried || common=$(git merge-base --all\n$head $reduced_parents)\n        case \"$common\" in\n        ?*\"$LF\"?*)\n                # We are not doing octopus and not fast forward.  Need a\n@@ -429,13 +440,13 @@ case \"$actual_parents\" in\n                        # See if it is really trivial.\n                        git var GIT_COMMITTER_IDENT >/dev/null || exit\n                        echo \"Trying really trivial in-index merge...\"\n-                       if git read-tree --trivial -m -u -v $common\n$head $actual_parents &&\n+                       if git read-tree --trivial -m -u -v $common\n$head $reduced_parents &&\n                                result_tree=$(git write-tree)\n                        then\n                                echo \"Wonderful.\"\n                                result_commit=$(\n                                        printf '%s\\n' \"$merge_msg\" |\n-                                       git commit-tree $result_tree\n-p HEAD -p $actual_parents\n+                                       git commit-tree $result_tree\n-p HEAD -p $reduced_parents\n                                ) || exit\n                                finish \"$result_commit\" \"In-index merge\"\n                                dropsave\n@@ -484,7 +495,7 @@ do\n     # Remember which strategy left the state in the working tree\n     wt_strategy=$strategy\n\n-    git-merge-$strategy $common -- \"$head_arg\" $actual_parents\n+    git-merge-$strategy $common -- \"$head_arg\" $reduced_parents\n     exit=$?\n     if test \"$no_commit\" = t && test \"$exit\" = 0\n     then\n@@ -520,17 +531,12 @@ done\n # auto resolved the merge cleanly.\n if test '' != \"$result_tree\"\n then\n-    if test $fast_forward = allow\n-    then\n-        parents=$(git show-branch --independent \"$head\" \"$@\")\n-    else\n-        parents=$(git rev-parse \"$head\" \"$@\")\n-    fi\n-    parents=$(echo \"$parents\" | sed -e 's/^/-p /')\n-    result_commit=$(printf '%s\\n' \"$merge_msg\" | git commit-tree\n$result_tree $parents) || exit\n-    finish \"$result_commit\" \"Merge made by $wt_strategy.\"\n-    dropsave\n-    exit 0\n+       test $head = $ff_head && reduced_parents=\"$head$LF$reduced_parents\"\n+       parents=$(echo \"$reduced_parents\" | sed -e 's/^/-p /')\n+       result_commit=$(printf '%s\\n' \"$merge_msg\" | git commit-tree\n$result_tree $parents) || exit\n+       finish \"$result_commit\" \"Merge made by $wt_strategy.\"\n+       dropsave\n+       exit 0\n fi\n\n # Pick the result from the best strategy and have the user fix it up.\n@@ -554,7 +560,7 @@ case \"$best_strategy\" in\n        echo \"Rewinding the tree to pristine...\"\n        restorestate\n        echo \"Using the $best_strategy to prepare resolving by hand.\"\n-       git-merge-$best_strategy $common -- \"$head_arg\" $actual_parents\n+       git-merge-$best_strategy $common -- \"$head_arg\" $reduced_parents\n        ;;\n esac\n\n-- \nSverre Hvammen Johansen\n"},{"id":"75180","messageId":"m3prsep6oy.fsf@localhost.localdomain","threadId":"13241","inReplyTo":"402c10cd0804232252g43606767r10344ebbb2a44af9@mail.gmail.com","subject":"Re: [PATCH 4/5] Head reduction before selecting merge strategy","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-04-25T10:31:14Z","receivedAt":"2008-04-25T10:31:14Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Sverre Hvammen Johansen\" <hvammen@gmail.com> writes:\n\n> See the documentation for an explanation of this feature.\n\nI think I get the idea now.\n\nYou want to generalize fast-forward merge, or what's equivalent make\nfast-formard merge to be special case of head reduction.  This should\nbe written both in commit message and in documentation.  Do I\nunderstand your goal correctly?\n\nWith head reduction comes three things:\n * the merge strategy used\n * recorded parents\n * generated merge commit message\nThe simplest way would be to use reduced head for all three things,\nI think.\n\nBut I also think that this commit in series is the most controversial\none; is it realy needed for other commits?  I would put it then as the\nlast commit in series...\n \n> +If more than one commit are specified on the command line, git will\n> +try to reduce the number of commits used (reduced parents) by\n> +eliminating commits than can be reached from other commits.  The\n> +commit message will reflect the commits specified on the command line\n> +but the merge strategy will be selected based on the reduced parents\n> +including `HEAD`.  The reduced parents are the parents recorded in the\n> +merge commit object.\n\nIs it a correct solution, to use provided (specified) heads for\ngeneration of merge commit message, but use reduced heads for\nselecting merge strategy _and_ also as parents recorded in merge\ncommits?  Perhaps it is; but IMHO you should have written it in the\ncommit message, and defend this decision in commit message.\n\n> +\n> +The following shows master and three topic branches.  topicB is based\n> +on topicA, topicA is previously branched off from master, and topicC\n> +is based on the tip of the master branch:\n> +\n> +------------\n> +                    o---o---o  topicB\n> +                   /\n> +          o---o---o  topicA\n> +         /\n> +    o---o---o---o---o---o  master\n> +                         \\\n> +                          o---o  topicC\n> +------------\n\nI think I would start with simpler example without 'topicC', of\nreduction of octopus to two-parent ordinary merge.\n\n> diff --git a/git-merge.sh b/git-merge.sh\n> index 7c34b6c..7c70c56 100755\n> --- a/git-merge.sh\n> +++ b/git-merge.sh\n> @@ -337,11 +337,16 @@ set x $remoteheads ; shift\n> \n>  find_reduced_parents \"$@\"\n> \n> -actual_parents=$(git rev-parse \"$@\")\n\nThis was introduced by some of your earlier commits, isn't it?\n\n[...]\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"75977","messageId":"402c10cd0805032152g1cb3f10cr69f1735785c5d647@mail.gmail.com","threadId":"13241","inReplyTo":"m3prsep6oy.fsf@localhost.localdomain","subject":"Re: [PATCH 4/5] Head reduction before selecting merge strategy","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-05-04T04:52:32Z","receivedAt":"2008-05-04T04:52:32Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"On Fri, Apr 25, 2008 at 3:31 AM, Jakub Narebski <jnareb@gmail.com> wrote:\n> \"Sverre Hvammen Johansen\" <hvammen@gmail.com> writes:\n>\n>  > See the documentation for an explanation of this feature.\n>\n>  I think I get the idea now.\n>\n>  You want to generalize fast-forward merge, or what's equivalent make\n>  fast-formard merge to be special case of head reduction.  This should\n>  be written both in commit message and in documentation.  Do I\n>  understand your goal correctly?\n>\n>  With head reduction comes three things:\n>   * the merge strategy used\n>   * recorded parents\n>   * generated merge commit message\n\nThe recorded parents and the generated merge commit message is the\nsame with or without this patch.  The only difference is the merge\nstrategy used.\n\n>  The simplest way would be to use reduced head for all three things,\n>  I think.\n\nActually, we can't do that.  A real merge always need to involve HEAD.\n In the case that HEAD is not included in the reduced parents we could\ndo a FF+merge, but that is a rather radical change that deserve its\nown patch.\n\nChanging the generated merge commit message is also a radical change.\n\nI don't intend to write any patches for this for now.  Maybe later if\nthe series gets accepted.\n\n>  But I also think that this commit in series is the most controversial\n>  one; is it realy needed for other commits?  I would put it then as the\n>  last commit in series...\n\nI agree with you, but I don't intend to spend time on this now to\nrewrite it again.  I am quite happy with how the series turned out.\n\n>  > +The following shows master and three topic branches.  topicB is based\n>  > +on topicA, topicA is previously branched off from master, and topicC\n>  > +is based on the tip of the master branch:\n>  > +\n>  > +------------\n>  > +                    o---o---o  topicB\n>  > +                   /\n>  > +          o---o---o  topicA\n>  > +         /\n>  > +    o---o---o---o---o---o  master\n>  > +                         \\\n>  > +                          o---o  topicC\n>  > +------------\n>\n>  I think I would start with simpler example without 'topicC', of\n>  reduction of octopus to two-parent ordinary merge.\n\nI am not sure that we need to have this in the documentation at all.\nI have asked for comments on this before but not received any\nfeedback.  This late, the documentation will have to be fixed in-tree,\nif needed.\n\n>  > diff --git a/git-merge.sh b/git-merge.sh\n>  > index 7c34b6c..7c70c56 100755\n>  > --- a/git-merge.sh\n>  > +++ b/git-merge.sh\n>  > @@ -337,11 +337,16 @@ set x $remoteheads ; shift\n>  >\n>  >  find_reduced_parents \"$@\"\n>  >\n>  > -actual_parents=$(git rev-parse \"$@\")\n>\n>  This was introduced by some of your earlier commits, isn't it?\n\nYes,  [PATCH 3/5] Restructure git-merge.sh\n\n-- \nSverre Hvammen Johansen\n"}]}