{"thread":{"id":"20139","subject":"[PATCH] Fix rebase -p --onto","startedAt":"2009-07-16T23:00:32Z","lastAt":"2009-07-17T19:00:44Z","messageCount":9,"participants":["Greg Price","Johannes Sixt","Junio C Hamano","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"118145","messageId":"20090716230031.GM7503@vinegar-pot.mit.edu","threadId":"20139","inReplyTo":null,"subject":"[PATCH] Fix rebase -p --onto","fromName":"Greg Price","fromEmail":"price@ksplice.com","sentAt":"2009-07-16T23:00:32Z","receivedAt":"2009-07-16T23:00:32Z","isPatch":true,"sender":{"key":"price@mit.edu","avatar":"https://avatars.githubusercontent.com/u/28173?v=4"},"body":"In a rebase with --onto, the correct test for whether we can skip\nrewriting a commit is if it is already on top of $ONTO, not $UPSTREAM.\nWithout --onto, this distinction does not exist and the behavior does\nnot change.\n\n\nIn the situation\n\n X---o---o---o---M\n  \\             /\n   x---x---x---x\n\n Y\n\nif we try to move the branches merged at M from their base on X to be\nbased on Y, so as to get\n\n X\n\n Y---o'--o'--o'--M'\n  \\             /\n   x'--x'--x'--x'\n\nthen we fail.  The command `git rebase -p --onto Y X M` moves only the\nfirst-parent chain, like so:\n\n X\n  \\\n   x---x---x---x\n                \\\n Y---o'--o'--o'--M'\n\nbecause it mistakenly drops the other branch(es) x---x---x---x from\nthe TODO file.  This tests and fixes this behavior.\n\nSigned-off-by: Greg Price <price@ksplice.com>\nCc: Stephen Haberman <stephen@exigencecorp.com>\n---\n\n git-rebase--interactive.sh      |    2 +-\n t/t3414-rebase-preserve-onto.sh |   48 +++++++++++++++++++++++++++++++++++++++\n 2 files changed, 49 insertions(+), 1 deletions(-)\n create mode 100644 t/t3414-rebase-preserve-onto.sh\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex f96d887..23ded48 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -703,7 +703,7 @@ first and then run 'git rebase --continue' again.\"\n \t\t\t\t\tpreserve=t\n \t\t\t\t\tfor p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)\n \t\t\t\t\tdo\n-\t\t\t\t\t\tif test -f \"$REWRITTEN\"/$p -a \\( $p != $UPSTREAM -o $sha1 = $first_after_upstream \\)\n+\t\t\t\t\t\tif test -f \"$REWRITTEN\"/$p -a \\( $p != $ONTO -o $sha1 = $first_after_upstream \\)\n \t\t\t\t\t\tthen\n \t\t\t\t\t\t\tpreserve=f\n \t\t\t\t\t\tfi\ndiff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh\nnew file mode 100644\nindex 0000000..ee29517\n--- /dev/null\n+++ b/t/t3414-rebase-preserve-onto.sh\n@@ -0,0 +1,48 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2009 Greg Price\n+#\n+\n+test_description='git rebase -p should respect --onto\n+\n+In a rebase with --onto, we should rewrite all the commits that\n+aren'\"'\"'t on top of $ONTO, even if they are on top of $UPSTREAM.\n+'\n+. ./test-lib.sh\n+\n+. ../lib-rebase.sh\n+\n+# Set up branches like this:\n+# A1---B1---D1---E1\n+#  \\    \\        /\n+#   \\    \\--C1--/\n+#    F1\n+\n+test_expect_success 'setup' '\n+\ttest_commit A1 &&\n+\ttest_commit B1 &&\n+\ttest_commit C1 &&\n+\tgit reset --hard B1 &&\n+\ttest_commit D1 &&\n+\ttest_merge E1 C1 &&\n+\tgit reset --hard A1 &&\n+\ttest_commit F1\n+'\n+\n+# Now rebase E1 from B1 onto F1, expect to get this:\n+# A1---B1---D1---E1\n+#  \\    \\        /\n+#   \\    \\--C1--/\n+#    \\\n+#     F1---D2---E2\n+#      \\        /\n+#       \\--C2--/\n+\n+test_expect_success 'rebase from B1 onto F1' '\n+\tgit checkout E1 &&\n+\tgit rebase -p --onto F1 B1 &&\n+\ttest \"$(git rev-parse HEAD^1^1)\" = \"$(git rev-parse F1)\" &&\n+\ttest \"$(git rev-parse HEAD^2^1)\" = \"$(git rev-parse F1)\"\n+'\n+\n+test_done\n-- \n1.6.4.rc0.19.gbedf\n"},{"id":"118154","messageId":"4A601C59.8040108@viscovery.net","threadId":"20139","inReplyTo":"20090716230031.GM7503@vinegar-pot.mit.edu","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-07-17T06:38:17Z","receivedAt":"2009-07-17T06:38:17Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Greg Price schrieb:\n> In a rebase with --onto, the correct test for whether we can skip\n> rewriting a commit is if it is already on top of $ONTO, not $UPSTREAM.\n> Without --onto, this distinction does not exist and the behavior does\n> not change.\n> \n> \n> In the situation\n> \n>  X---o---o---o---M\n>   \\             /\n>    x---x---x---x\n> \n>  Y\n> \n> if we try to move the branches merged at M from their base on X to be\n> based on Y, so as to get\n> \n>  X\n> \n>  Y---o'--o'--o'--M'\n>   \\             /\n>    x'--x'--x'--x'\n> \n> then we fail.  The command `git rebase -p --onto Y X M` moves only the\n> first-parent chain, like so:\n> \n>  X\n>   \\\n>    x---x---x---x\n>                 \\\n>  Y---o'--o'--o'--M'\n> \n> because it mistakenly drops the other branch(es) x---x---x---x from\n> the TODO file.  This tests and fixes this behavior.\n\nI think the current behavior is by design. There is nothing to fix.\n\nThe purpose of rebase -p is to leave non-first children alone and rebase\nonly the first child parenthood chain. It is not the purpose to reseat an\nentire history DAG.\n\n-- Hannes\n"},{"id":"118159","messageId":"7vk52767el.fsf@alter.siamese.dyndns.org","threadId":"20139","inReplyTo":"4A601C59.8040108@viscovery.net","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-17T08:27:46Z","receivedAt":"2009-07-17T08:27:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Greg Price schrieb:\n>> In a rebase with --onto, the correct test for whether we can skip\n>> rewriting a commit is if it is already on top of $ONTO, not $UPSTREAM.\n>> Without --onto, this distinction does not exist and the behavior does\n>> not change.\n>> \n>> \n>> In the situation\n>> \n>>  X---o---o---o---M\n>>   \\             /\n>>    x---x---x---x\n>> \n>>  Y\n>> ...\n>> The command `git rebase -p --onto Y X M` moves only the\n>> first-parent chain, like so:\n>> \n>>  X\n>>   \\\n>>    x---x---x---x\n>>                 \\\n>>  Y---o'--o'--o'--M'\n>> \n>> because it mistakenly drops the other branch(es) x---x---x---x from\n>> the TODO file.  This tests and fixes this behavior.\n>\n> I think the current behavior is by design. There is nothing to fix.\n>\n> The purpose of rebase -p is to leave non-first children alone and rebase\n> only the first child parenthood chain. It is not the purpose to reseat an\n> entire history DAG.\n\nHmm, if the original history were\n\n .---X---o---o---o---M\n  \\                 /\n   x---x---x---x---x\n\n     Y\n\nand the rebase is about moving history leading to M since X on top of Y,\nI would actually have agreed that this\n\n .---X---o---o---o---M\n  \\                 /\n   x---x---x---x---x\n                    \\\n     Y---o'--o'--o'--M'\n\nwould be the right thing to do (IOW, I would agree with you).\n\nCan the current code distinguish the two cases?  More generally, can we\nalways tell these two cases apart, or is it fundamentally not possible to\ndifferentiate the two cases and we should simplify the problem space by\nlimiting ourselves by treating the first parent in a special way?\n"},{"id":"118161","messageId":"4A6038E8.1090402@viscovery.net","threadId":"20139","inReplyTo":"7vk52767el.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-07-17T08:40:08Z","receivedAt":"2009-07-17T08:40:08Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Junio C Hamano schrieb:\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> \n>> Greg Price schrieb:\n>>> In a rebase with --onto, the correct test for whether we can skip\n>>> rewriting a commit is if it is already on top of $ONTO, not $UPSTREAM.\n>>> Without --onto, this distinction does not exist and the behavior does\n>>> not change.\n>>>\n>>>\n>>> In the situation\n>>>\n>>>  X---o---o---o---M\n>>>   \\             /\n>>>    x---x---x---x\n>>>\n>>>  Y\n>>> ...\n>>> The command `git rebase -p --onto Y X M` moves only the\n>>> first-parent chain, like so:\n>>>\n>>>  X\n>>>   \\\n>>>    x---x---x---x\n>>>                 \\\n>>>  Y---o'--o'--o'--M'\n>>>\n>>> because it mistakenly drops the other branch(es) x---x---x---x from\n>>> the TODO file.  This tests and fixes this behavior.\n>> I think the current behavior is by design. There is nothing to fix.\n>>\n>> The purpose of rebase -p is to leave non-first children alone and rebase\n>> only the first child parenthood chain. It is not the purpose to reseat an\n>> entire history DAG.\n> \n> Hmm, if the original history were\n> \n>  .---X---o---o---o---M\n>   \\                 /\n>    x---x---x---x---x\n> \n>      Y\n> \n> and the rebase is about moving history leading to M since X on top of Y,\n> I would actually have agreed that this\n> \n>  .---X---o---o---o---M\n>   \\                 /\n>    x---x---x---x---x\n>                     \\\n>      Y---o'--o'--o'--M'\n> \n> would be the right thing to do (IOW, I would agree with you).\n> \n> Can the current code distinguish the two cases?  More generally, can we\n> always tell these two cases apart, or is it fundamentally not possible to\n> differentiate the two cases and we should simplify the problem space by\n> limiting ourselves by treating the first parent in a special way?\n\nI have used rebase -i -p in the past to rewrite history that involves\nmerges of topic branches like this:\n\n  ---------Y--M--M--F     <-- master\n             /  /\n  ----a--a--a  /\n              /\n  --b--b--b--b\n\nwhere F is a fixup that I want to insert between Y and M, and I thought\nrebase -i -p was intended for this use-case.\n\nWith this in mind, I do not see why should we distinguish the cases. I\nwould even go so far to say that this is OK:\n\n  X---a---o---o---M            X---a\n       \\         /    ===>          \\\n        x---x---x                    x---x---x\n                                              \\\n  Y                            Y---a'--o'--o'--M'\n"},{"id":"118163","messageId":"4A603AA4.7020800@viscovery.net","threadId":"20139","inReplyTo":"4A6038E8.1090402@viscovery.net","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-07-17T08:47:32Z","receivedAt":"2009-07-17T08:47:32Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Johannes Sixt schrieb:\n> I have used rebase -i -p in the past to rewrite history that involves\n> merges of topic branches like this:\n> \n>   ---------Y--M--M--F     <-- master\n>              /  /\n>   ----a--a--a  /\n>               /\n>   --b--b--b--b\n> \n> where F is a fixup that I want to insert between Y and M, and I thought\n> rebase -i -p was intended for this use-case.\n> \n> With this in mind, I do not see why should we distinguish the cases. I\n> would even go so far to say that this is OK:\n> \n>   X---a---o---o---M            X---a\n>        \\         /    ===>          \\\n>         x---x---x                    x---x---x\n>                                               \\\n>   Y                            Y---a'--o'--o'--M'\n\nbecause it is a user error: wrong tool for the task. The right tool would\nperhaps be git-sequencer.\n\n-- Hannes\n(I hit the send button too early by accident, sorry for the excessive\nquoting in the previous mail.)\n"},{"id":"118185","messageId":"20090717163350.GK7878@vinegar-pot.mit.edu","threadId":"20139","inReplyTo":"7vk52767el.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Greg Price","fromEmail":"price@ksplice.com","sentAt":"2009-07-17T16:33:50Z","receivedAt":"2009-07-17T16:33:50Z","isPatch":true,"sender":{"key":"price@mit.edu","avatar":"https://avatars.githubusercontent.com/u/28173?v=4"},"body":"On Fri, Jul 17, 2009 at 01:27:46AM -0700, Junio C Hamano wrote:\n> Hmm, if the original history were\n> \n>  .---X---o---o---o---M\n>   \\                 /\n>    x---x---x---x---x\n> \n>      Y\n> \n> and the rebase is about moving history leading to M since X on top of Y,\n> I would actually have agreed that this\n> \n>  .---X---o---o---o---M\n>   \\                 /\n>    x---x---x---x---x\n>                     \\\n>      Y---o'--o'--o'--M'\n> \n> would be the right thing to do (IOW, I would agree with you).\n\nYes, I agree.\n\n\n> Can the current code distinguish the two cases?\n\nYes.  Stephen's commit acc8559 already limits $TODO to the descendants\nof the merge-bases of HEAD and UPSTREAM, which captures the\ndistinction here.  When we rebase from X, the merge-base is X, so only\nthat branch moves.  When we rebase from the base of both branches,\nboth branches should move.\n\nI've added a test demonstrating this case to a revised version of the\npatch, below.\n\nGreg\n\n\n\n>From dcab1103e14394364c15136823269416f8c56e97 Mon Sep 17 00:00:00 2001\nFrom: Greg Price <price@ksplice.com>\nDate: Thu, 16 Jul 2009 12:48:40 -0400\nSubject: [PATCH] Fix rebase -p --onto\n\nIn a rebase with --onto, the correct test for whether we can skip\nrewriting a commit is if it is already on top of $ONTO, not $UPSTREAM.\nWithout --onto, this distinction does not exist and the behavior does\nnot change.\n\nIn the situation\n\n X---o---o---o---M\n  \\             /\n   x---x---x---x\n\n Y\n\nif we try to move the branches merged at M from their base on X to be\nbased on Y, so as to get\n\n X\n\n Y---o'--o'--o'--M'\n  \\             /\n   x'--x'--x'--x'\n\nthen we fail.  The command `git rebase -p --onto Y X M` moves only the\nfirst-parent chain, like so:\n\n X\n  \\\n   x---x---x---x\n                \\\n Y---o'--o'--o'--M'\n\nbecause it mistakenly drops the other branch(es) x---x---x---x from\nthe TODO file.  This tests and fixes this behavior.\n\nSigned-off-by: Greg Price <price@ksplice.com>\n---\n git-rebase--interactive.sh      |    2 +-\n t/t3414-rebase-preserve-onto.sh |   80 +++++++++++++++++++++++++++++++++++++++\n 2 files changed, 81 insertions(+), 1 deletions(-)\n create mode 100755 t/t3414-rebase-preserve-onto.sh\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex f96d887..23ded48 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -703,7 +703,7 @@ first and then run 'git rebase --continue' again.\"\n \t\t\t\t\tpreserve=t\n \t\t\t\t\tfor p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)\n \t\t\t\t\tdo\n-\t\t\t\t\t\tif test -f \"$REWRITTEN\"/$p -a \\( $p != $UPSTREAM -o $sha1 = $first_after_upstream \\)\n+\t\t\t\t\t\tif test -f \"$REWRITTEN\"/$p -a \\( $p != $ONTO -o $sha1 = $first_after_upstream \\)\n \t\t\t\t\t\tthen\n \t\t\t\t\t\t\tpreserve=f\n \t\t\t\t\t\tfi\ndiff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh\nnew file mode 100755\nindex 0000000..80019ee\n--- /dev/null\n+++ b/t/t3414-rebase-preserve-onto.sh\n@@ -0,0 +1,80 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2009 Greg Price\n+#\n+\n+test_description='git rebase -p should respect --onto\n+\n+In a rebase with --onto, we should rewrite all the commits that\n+aren'\"'\"'t on top of $ONTO, even if they are on top of $UPSTREAM.\n+'\n+. ./test-lib.sh\n+\n+. ../lib-rebase.sh\n+\n+# Set up branches like this:\n+# A1---B1---E1---F1---G1\n+#  \\    \\             /\n+#   \\    \\--C1---D1--/\n+#    H1\n+\n+test_expect_success 'setup' '\n+\ttest_commit A1 &&\n+\ttest_commit B1 &&\n+\ttest_commit C1 &&\n+\ttest_commit D1 &&\n+\tgit reset --hard B1 &&\n+\ttest_commit E1 &&\n+\ttest_commit F1 &&\n+\ttest_merge G1 D1 &&\n+\tgit reset --hard A1 &&\n+\ttest_commit H1\n+'\n+\n+# Now rebase merge G1 from both branches' base B1, both should move:\n+# A1---B1---E1---F1---G1\n+#  \\    \\             /\n+#   \\    \\--C1---D1--/\n+#    \\\n+#     H1---E2---F2---G2\n+#      \\             /\n+#       \\--C2---D2--/\n+\n+test_expect_success 'rebase from B1 onto H1' '\n+\tgit checkout G1 &&\n+\tgit rebase -p --onto H1 B1 &&\n+\ttest \"$(git rev-parse HEAD^1^1^1)\" = \"$(git rev-parse H1)\" &&\n+\ttest \"$(git rev-parse HEAD^2^1^1)\" = \"$(git rev-parse H1)\"\n+'\n+\n+# On the other hand if rebase from E1 which is within one branch,\n+# then the other branch stays:\n+# A1---B1---E1---F1---G1\n+#  \\    \\             /\n+#   \\    \\--C1---D1--/\n+#    \\             \\\n+#     H1-----F3-----G3\n+\n+test_expect_success 'rebase from E1 onto H1' '\n+\tgit checkout G1 &&\n+\tgit rebase -p --onto H1 E1 &&\n+\ttest \"$(git rev-parse HEAD^1^1)\" = \"$(git rev-parse H1)\" &&\n+\ttest \"$(git rev-parse HEAD^2)\" = \"$(git rev-parse D1)\"\n+'\n+\n+# And the same if we rebase from a commit in the second-parent branch.\n+# A1---B1---E1---F1----G1\n+#  \\    \\          \\   /\n+#   \\    \\--C1---D1-\\-/\n+#    \\               \\\n+#     H1------D3------G4\n+\n+test_expect_success 'rebase from C1 onto H1' '\n+\tgit checkout G1 &&\n+\tgit rev-list --first-parent --pretty=oneline C1..G1 &&\n+\tgit rebase -p --onto H1 C1 &&\n+\ttest \"$(git rev-parse HEAD^2^1)\" = \"$(git rev-parse H1)\" &&\n+\ttest \"$(git rev-parse HEAD^1)\" = \"$(git rev-parse F1)\"\n+'\n+\n+test_done\n-- \n1.6.3.1.499.ge7b8da\n"},{"id":"118187","messageId":"20090717164845.GL7878@vinegar-pot.mit.edu","threadId":"20139","inReplyTo":"4A6038E8.1090402@viscovery.net","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Greg Price","fromEmail":"price@ksplice.com","sentAt":"2009-07-17T16:48:46Z","receivedAt":"2009-07-17T16:48:46Z","isPatch":true,"sender":{"key":"price@mit.edu","avatar":"https://avatars.githubusercontent.com/u/28173?v=4"},"body":"On Fri, Jul 17, 2009 at 10:40:08AM +0200, Johannes Sixt wrote:\n> I have used rebase -i -p in the past to rewrite history that involves\n> merges of topic branches like this:\n> \n>   ---------Y--M--M--F     <-- master\n>              /  /\n>   ----a--a--a  /\n>               /\n>   --b--b--b--b\n> \n> where F is a fixup that I want to insert between Y and M, and I thought\n> rebase -i -p was intended for this use-case.\n\nI don't believe rebase -i -p has ever worked with reordering commits.\nIt certainly doesn't now, as the tests below demonstrate both for your\ncase and for the most trivial possible situation without even any merges.\n\nThis is not a mere coding error, as in the general case with a hairy\nset of merges it's not clear what an arbitrary reordering of the\ncommits would even mean.  To really fix it will require a richer TODO\nfile format, as in the sequencer or the discussion Johannes Schindelin\nstarted in January about a rebase -i -p rework.\n\n\nIn any case, this has nothing to do with my patch to fix -p --onto,\nwhich is a no-op when --onto is not used.  You want `git rebase -i -p Y`,\nand the generation of the TODO file correctly gives you M, M, F.\nIt's the execution of the TODO file you give back, with F, M, M,\nthat does not do what you want.\n\nCheers,\nGreg\n\n\n\n>From 185fa9da4caee5a0a96105e60269d02ec832e876 Mon Sep 17 00:00:00 2001\nFrom: Greg Price <price@ksplice.com>\nDate: Fri, 17 Jul 2009 11:55:11 -0400\nSubject: [PATCH] Add failing test for commit reordering in rebase -i -p\n\nSigned-off-by: Greg Price <price@ksplice.com>\n---\n t/t3411-rebase-preserve-around-merges.sh |   59 ++++++++++++++++++++++++++++++\n 1 files changed, 59 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh\nindex 6533505..1759a98 100755\n--- a/t/t3411-rebase-preserve-around-merges.sh\n+++ b/t/t3411-rebase-preserve-around-merges.sh\n@@ -71,4 +71,63 @@ test_expect_success 'rebase two levels of merge' '\n \ttest \"$(git rev-parse HEAD^2^1^1)\" = \"$(git rev-parse HEAD^2^2^1)\"\n '\n \n+# Reorder commits while using -p.  Basic prerequisite for the next test\n+# to have a hope of working.\n+#\n+# a---b---c\n+#\n+# want\n+#\n+# a---c---b\n+\n+test_expect_failure 'reorder with -p' '\n+\ttest_commit a &&\n+\ttest_commit b &&\n+\ttest_commit c &&\n+\tFAKE_LINES=\"2 1\" git rebase -i -p HEAD~2 &&\n+\ttest \"$(git rev-parse HEAD~2)\" = \"$(git rev-parse a)\" &&\n+\tgit log -n1 --pretty=format:%s HEAD | grep b &&\n+\tgit log -n1 --pretty=format:%s HEAD^ | grep c\n+'\n+\n+\n+# Reorder a commit to before a merge.  From\n+#\n+# R---x---Ma--Mb--F\n+#  \\     /   /\n+#   a1--a2  /\n+#    \\     /\n+#     b1--b2\n+#\n+# we get\n+#\n+# R---x---F*--Ma*--Mb*\n+#  \\         /    /\n+#   a1--a2--/    /\n+#    \\          /\n+#     b1--b2---/\n+\n+test_expect_failure 'rewrite to before merge' '\n+\ttest_commit R &&\n+\ttest_commit a1 &&\n+\ttest_commit b1 &&\n+\ttest_commit b2 &&\n+\tgit reset --hard a1 &&\n+\ttest_commit a2 &&\n+\tgit reset --hard R &&\n+\ttest_commit x &&\n+\ttest_merge Ma a2 &&\n+\ttest_merge Mb b2 &&\n+\ttest_commit F &&\n+\n+\tFAKE_LINES=\"3 1 2\" git rebase -i -p x &&\n+\tgit log --pretty=oneline HEAD && echo &&\n+\tgit log --pretty=oneline HEAD^2 && echo &&\n+\tgit log --pretty=oneline HEAD^^2 && echo &&\n+\tgit log --pretty=oneline HEAD^^ && echo &&\n+\ttest \"$(git rev-parse HEAD^2)\" = \"$(git rev-parse b2)\" &&\n+\ttest \"$(git rev-parse HEAD^1^2)\" = \"$(git rev-parse a2)\" &&\n+\ttest \"$(git rev-parse HEAD~3)\" = \"$(git rev-parse x)\"\n+'\n+\n test_done\n-- \n1.6.3.1.499.ge7b8da\n"},{"id":"118192","messageId":"alpine.DEB.1.00.0907172029230.4495@intel-tinevez-2-302","threadId":"20139","inReplyTo":"20090717164845.GL7878@vinegar-pot.mit.edu","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-07-17T18:32:20Z","receivedAt":"2009-07-17T18:32:20Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 17 Jul 2009, Greg Price wrote:\n\n> On Fri, Jul 17, 2009 at 10:40:08AM +0200, Johannes Sixt wrote:\n> > I have used rebase -i -p in the past to rewrite history that involves\n> > merges of topic branches like this:\n> > \n> >   ---------Y--M--M--F     <-- master\n> >              /  /\n> >   ----a--a--a  /\n> >               /\n> >   --b--b--b--b\n> > \n> > where F is a fixup that I want to insert between Y and M, and I thought\n> > rebase -i -p was intended for this use-case.\n> \n> I don't believe rebase -i -p has ever worked with reordering commits.\n\nIt was not meant to.  Actually, it was never meant as \"rebase -i -p\", but \nalways as \"rebase -p\" (which, for technical reasons, would be implemented \nin git-rebase--interactive.sh).\n\nHaving said that, I am working on a rebase-i-p series which _does_ allow \nreordering commits, putting commits on newly-created topic branches, \nredoing merges explicitely.\n\nUnfortunately, I seem to have less and less time for Git (which is not \nhelped by the frustrating experience of a first-slow then-failing GSoC \nproject), and when I finally decided to set aside some time to polish the \nseries and submit it, 1.6.4-rc0 came out.  And I do not want Junio to be \ndistracted from that very important (think push-to-current-branch) \nrelease.\n\nCiao,\nDscho\n"},{"id":"118193","messageId":"20090717190043.GM7878@vinegar-pot.mit.edu","threadId":"20139","inReplyTo":"alpine.DEB.1.00.0907172029230.4495@intel-tinevez-2-302","subject":"Re: [PATCH] Fix rebase -p --onto","fromName":"Greg Price","fromEmail":"price@ksplice.com","sentAt":"2009-07-17T19:00:44Z","receivedAt":"2009-07-17T19:00:44Z","isPatch":true,"sender":{"key":"price@mit.edu","avatar":"https://avatars.githubusercontent.com/u/28173?v=4"},"body":"On Fri, Jul 17, 2009 at 08:32:20PM +0200, Johannes Schindelin wrote:\n> > I don't believe rebase -i -p has ever worked with reordering commits.\n> \n> It was not meant to.  Actually, it was never meant as \"rebase -i -p\", but \n> always as \"rebase -p\" (which, for technical reasons, would be implemented \n> in git-rebase--interactive.sh).\n\nUnderstood.  The -p functionality is invaluable already without -i,\nand reordering commits with -p raises substantial new questions about\nwhat the behavior should be.\n\nI wonder if it might be worth giving an error message when the user\nattempts to reorder commits under -p?  The current behavior is\nsurprising (reordering A after B, C, D causes B, C, D to be dropped)\neven when no merges are involved.  I wouldn't want to give an error on\njust the combination of options -i -p, though, since \"edit\" is useful.\n\n\n> Having said that, I am working on a rebase-i-p series which _does_ allow \n> reordering commits, putting commits on newly-created topic branches, \n> redoing merges explicitely.\n\nThat would be excellent.  I'm using git-sequencer from Stephan Beyer's\nseq-builtin-dev branch for some work because I need this kind of\nfunctionality.  It would be great to see it in mainline in one form or\nanother.  I don't doubt that it will require a good deal of work.\n\nThanks!\nGreg\n"}]}