{"thread":{"id":"20127","subject":"[PATCH 1/2] t5520-pull: Test for rebased upstream + fetch + pull --rebase","startedAt":"2009-07-16T00:09:14Z","lastAt":"2009-07-19T07:45:16Z","messageCount":19,"participants":["Santi Béjar","Junio C Hamano","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"118056","messageId":"1247702955-1559-1-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":null,"subject":"[PATCH 1/2] t5520-pull: Test for rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T00:09:14Z","receivedAt":"2009-07-16T00:09:14Z","isPatch":true,"sender":{"key":"santi@agolina.net","avatar":null},"body":"If your upstream has rebased you can do:\n\ngit pull --rebase\n\nbut only if you haven't fetch before.\n\nMark this case as test_expect_failure, in a later patch it will be\nchanged to test_expect_success.\n\nSigned-off-by: Santi Béjar <santi@agolina.net>\n---\n t/t5520-pull.sh |   14 ++++++++++++++\n 1 files changed, 14 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex c5a2e66..1aae494 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -117,6 +117,20 @@ test_expect_success '--rebase with rebased default upstream' '\n \n '\n \n+test_expect_failure 'rebased upstream + fetch + pull --rebase' '\n+\n+\tgit update-ref refs/remotes/me/copy copy-orig &&\n+\tgit reset --hard to-rebase-orig &&\n+\tgit checkout --track -b to-rebase3 me/copy &&\n+\tgit reset --hard to-rebase-orig &&\n+\tgit fetch &&\n+\ttest_must_fail git pull --rebase &&\n+\tgit rebase --abort &&\n+\ttest \"conflicting modification\" = \"$(cat file)\" &&\n+\ttest file = $(cat file2)\n+\n+'\n+\n test_expect_success 'pull --rebase dies early with dirty working directory' '\n \n \tgit checkout to-rebase &&\n-- \n1.6.4.rc0.18.g60787.dirty\n"},{"id":"118057","messageId":"1247702955-1559-2-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":"1247702955-1559-1-git-send-email-santi@agolina.net","subject":"[PATCH 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T00:09:15Z","receivedAt":"2009-07-16T00:09:15Z","isPatch":true,"sender":{"key":"santi@agolina.net","avatar":null},"body":"Use the fork commit of the current branch (where\nthe tip of upstream branch used to be) as the upstream parameter of\n\"git rebase\". Compute it walking the reflog to find the first commit\nwhich is an ancestor of the current branch.\n\nSigned-off-by: Santi Béjar <santi@agolina.net>\n---\n git-pull.sh     |    9 +++++++--\n t/t5520-pull.sh |    5 ++---\n 2 files changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 4b78a0c..f5bef53 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -126,8 +126,13 @@ test true = \"$rebase\" && {\n \n \t. git-parse-remote &&\n \treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n-\toldremoteref=\"$(git rev-parse -q --verify \\\n-\t\t\"$reflist\")\"\n+\tnum=0 &&\n+\twhile oldremoteref=\"$(git rev-parse -q --verify \"$reflist@{$num}\")\"\n+\tdo\n+\t\ttest $oldremoteref = $(git merge-base $oldremoteref $curr_branch) &&\n+\t\tbreak\n+\t\tnum=$((num+1))\n+\tdone\n }\n orig_head=$(git rev-parse -q --verify HEAD)\n git fetch $verbosity --update-head-ok \"$@\" || exit 1\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 1aae494..37a7e33 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -117,15 +117,14 @@ test_expect_success '--rebase with rebased default upstream' '\n \n '\n \n-test_expect_failure 'rebased upstream + fetch + pull --rebase' '\n+test_expect_success 'rebased upstream + fetch + pull --rebase' '\n \n \tgit update-ref refs/remotes/me/copy copy-orig &&\n \tgit reset --hard to-rebase-orig &&\n \tgit checkout --track -b to-rebase3 me/copy &&\n \tgit reset --hard to-rebase-orig &&\n \tgit fetch &&\n-\ttest_must_fail git pull --rebase &&\n-\tgit rebase --abort &&\n+\tgit pull --rebase &&\n \ttest \"conflicting modification\" = \"$(cat file)\" &&\n \ttest file = $(cat file2)\n \n-- \n1.6.4.rc0.18.g60787.dirty\n"},{"id":"118058","messageId":"7vab35cw2e.fsf@alter.siamese.dyndns.org","threadId":"20127","inReplyTo":"1247702955-1559-2-git-send-email-santi@agolina.net","subject":"Re: [PATCH 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-16T00:26:17Z","receivedAt":"2009-07-16T00:26:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Santi Béjar <santi@agolina.net> writes:\n\n>  \treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> -\toldremoteref=\"$(git rev-parse -q --verify \\\n> -\t\t\"$reflist\")\"\n> +\tnum=0 &&\n> +\twhile oldremoteref=\"$(git rev-parse -q --verify \"$reflist@{$num}\")\"\n\nApplying @{nth} reflog notation to something that identifies itself as a\n\"list\" made me go \"Huh?\".  Why is this variable called refLIST?  Shouldn't\nit be simply called something like \"remoteref\" or even \"ref\"?\n\n> +\tdo\n> +\t\ttest $oldremoteref = $(git merge-base $oldremoteref $curr_branch) &&\n> +\t\tbreak\n> +\t\tnum=$((num+1))\n\nI think we always write \"num=$(( $num + 1 ))\" for portability; notice the\nlack of $ in your version.\n\n> +\tdone\n\nDoes this loop ever give up?  Should it?\n\nWhat happens in the subsequent code outside of the patch context, when\nthis loop does not find any suitable \"old\" value?\n\nOther than that, looking good.\n\nThanks.\n"},{"id":"118076","messageId":"adf1fd3d0907152329v7f49999u42b0d0fc4d39f5e9@mail.gmail.com","threadId":"20127","inReplyTo":"7vab35cw2e.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T06:29:22Z","receivedAt":"2009-07-16T06:29:22Z","isPatch":true,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/16 Junio C Hamano <gitster@pobox.com>:\n> Santi Béjar <santi@agolina.net> writes:\n>\n>>       reflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n>> -     oldremoteref=\"$(git rev-parse -q --verify \\\n>> -             \"$reflist\")\"\n>> +     num=0 &&\n>> +     while oldremoteref=\"$(git rev-parse -q --verify \"$reflist@{$num}\")\"\n>\n> Applying @{nth} reflog notation to something that identifies itself as a\n> \"list\" made me go \"Huh?\".  Why is this variable called refLIST?  Shouldn't\n> it be simply called something like \"remoteref\" or even \"ref\"?\n\nIt used to be a list, before my patch 97af7ff (parse-remote: function\nto get the tracking branch to be merge, 2009-06-12). I'll change it.\n\n>\n>> +     do\n>> +             test $oldremoteref = $(git merge-base $oldremoteref $curr_branch) &&\n>> +             break\n>> +             num=$((num+1))\n>\n> I think we always write \"num=$(( $num + 1 ))\" for portability; notice the\n> lack of $ in your version.\n\nOops, you are right. I somehow missed, I even did \"git grep \"((\" *.sh\"\nto check it.\n\n>\n>> +     done\n>\n> Does this loop ever give up?  Should it?\n\nWhen remote/$origin/$branch@{nth} does not exist. I don't think we\nneed another way to give up (nth<10?) because normally nth is small,\nit does not harm the normal case and it can help when nth is large.\n\n>\n> What happens in the subsequent code outside of the patch context, when\n> this loop does not find any suitable \"old\" value?\n\nThen the $oldremoteref is empty and in the git-rebase command it is\nused as ${oldremoteref:-$merge_head} so it get replaced by\n$merge_head.\n\nThanks,\nSanti\n"},{"id":"118096","messageId":"1247731921-2290-1-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":"adf1fd3d0907152329v7f49999u42b0d0fc4d39f5e9@mail.gmail.com","subject":"[PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T08:12:00Z","receivedAt":"2009-07-16T08:12:00Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"Use the fork commit of the current branch (where\nthe tip of upstream branch used to be) as the upstream parameter of\n\"git rebase\". Compute it walking the reflog to find the first commit\nwhich is an ancestor of the current branch.\n\nSigned-off-by: Santi Béjar <santi@agolina.net>\n\nChanged since v1:\n  - rename reflist to remoteref to better reflect its use\n  - (( $num + 1 ))\n---\n git-pull.sh     |   11 ++++++++---\n t/t5520-pull.sh |    5 ++---\n 2 files changed, 10 insertions(+), 6 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 4b78a0c..31d3945 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -125,9 +125,14 @@ test true = \"$rebase\" && {\n \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n \n \t. git-parse-remote &&\n-\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n-\toldremoteref=\"$(git rev-parse -q --verify \\\n-\t\t\"$reflist\")\"\n+\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n+\tnum=0 &&\n+\twhile oldremoteref=\"$(git rev-parse -q --verify \"$remoteref@{$num}\")\"\n+\tdo\n+\t\ttest $oldremoteref = $(git merge-base $oldremoteref $curr_branch) &&\n+\t\tbreak\n+\t\tnum=$(( $num + 1 ))\n+\tdone\n }\n orig_head=$(git rev-parse -q --verify HEAD)\n git fetch $verbosity --update-head-ok \"$@\" || exit 1\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 1aae494..37a7e33 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -117,15 +117,14 @@ test_expect_success '--rebase with rebased default upstream' '\n \n '\n \n-test_expect_failure 'rebased upstream + fetch + pull --rebase' '\n+test_expect_success 'rebased upstream + fetch + pull --rebase' '\n \n \tgit update-ref refs/remotes/me/copy copy-orig &&\n \tgit reset --hard to-rebase-orig &&\n \tgit checkout --track -b to-rebase3 me/copy &&\n \tgit reset --hard to-rebase-orig &&\n \tgit fetch &&\n-\ttest_must_fail git pull --rebase &&\n-\tgit rebase --abort &&\n+\tgit pull --rebase &&\n \ttest \"conflicting modification\" = \"$(cat file)\" &&\n \ttest file = $(cat file2)\n \n-- \n1.6.4.rc0.19.g1b31.dirty\n"},{"id":"118094","messageId":"1247731921-2290-2-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":"1247731921-2290-1-git-send-email-santi@agolina.net","subject":"[PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T08:12:01Z","receivedAt":"2009-07-16T08:12:01Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"  and here the interdiff between v1 and v2.\n\nSanti\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex f5bef53..31d3945 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -125,13 +125,13 @@ test true = \"$rebase\" && {\n \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n \n \t. git-parse-remote &&\n-\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n+\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n \tnum=0 &&\n-\twhile oldremoteref=\"$(git rev-parse -q --verify \"$reflist@{$num}\")\"\n+\twhile oldremoteref=\"$(git rev-parse -q --verify \"$remoteref@{$num}\")\"\n \tdo\n \t\ttest $oldremoteref = $(git merge-base $oldremoteref $curr_branch) &&\n \t\tbreak\n-\t\tnum=$((num+1))\n+\t\tnum=$(( $num + 1 ))\n \tdone\n }\n orig_head=$(git rev-parse -q --verify HEAD)\n"},{"id":"118098","messageId":"adf1fd3d0907160115j24acf584ic4a8be6aa85b4606@mail.gmail.com","threadId":"20127","inReplyTo":"1247731921-2290-1-git-send-email-santi@agolina.net","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T08:15:51Z","receivedAt":"2009-07-16T08:15:51Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/16 Santi Béjar <santi@agolina.net>:\n> Use the fork commit of the current branch (where\n> the tip of upstream branch used to be) as the upstream parameter of\n> \"git rebase\". Compute it walking the reflog to find the first commit\n> which is an ancestor of the current branch.\n>\n> Signed-off-by: Santi Béjar <santi@agolina.net>\n>\n> Changed since v1:\n>  - rename reflist to remoteref to better reflect its use\n>  - (( $num + 1 ))\n\nArg! It should not be in the commit message! Sorry. Junio, can you\namend it if applied? Thanks\n\nSanti\n"},{"id":"118100","messageId":"alpine.DEB.1.00.0907161035060.3155@pacific.mpi-cbg.de","threadId":"20127","inReplyTo":"1247731921-2290-1-git-send-email-santi@agolina.net","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-07-16T08:51:46Z","receivedAt":"2009-07-16T08:51:46Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 16 Jul 2009, Santi Béjar wrote:\n\n> Use the fork commit of the current branch (where\n> the tip of upstream branch used to be) as the upstream parameter of\n> \"git rebase\". Compute it walking the reflog to find the first commit\n> which is an ancestor of the current branch.\n\nI finally understand what this patch is about.  Thanks.\n\n> diff --git a/git-pull.sh b/git-pull.sh\n> index 4b78a0c..31d3945 100755\n> --- a/git-pull.sh\n> +++ b/git-pull.sh\n> @@ -125,9 +125,14 @@ test true = \"$rebase\" && {\n>  \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n>  \n>  \t. git-parse-remote &&\n> -\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> -\toldremoteref=\"$(git rev-parse -q --verify \\\n> -\t\t\"$reflist\")\"\n> +\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> +\tnum=0 &&\n> +\twhile oldremoteref=\"$(git rev-parse -q --verify \"$remoteref@{$num}\")\"\n> +\tdo\n\nHow about\n\n\toldremoteref=\"$(git rev-list --boundary HEAD --not \\\n\t\t\t$(git rev-list -g $remoteref | sed 's/$/^@/') |\n\t\tsed -e '/^[^-]/d' -e q)\"\n\nExplanation: the \"git rev-list -g $remoteref\" lists the previous commits \nthe remote ref pointed to, and the ^@ appended to them means all their \nparents.  Now, the outer rev-list says to take everything in HEAD but \n_not_ in those parents, showing the boundary commits.  The \"sed\" call \nlists the first such boundary commit (which must, by construction, be one \nof the commits shown by the first rev-list).\n\nBut maybe this is trying to be too clever, and we should not bother with \nit until git-pull is made a builtin?\n\nCiao,\nDscho\n"},{"id":"118119","messageId":"adf1fd3d0907160932r313de6e8lec23e4f3409b8c05@mail.gmail.com","threadId":"20127","inReplyTo":"alpine.DEB.1.00.0907161035060.3155@pacific.mpi-cbg.de","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T16:32:39Z","receivedAt":"2009-07-16T16:32:39Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/16 Johannes Schindelin <Johannes.Schindelin@gmx.de>:\n> Hi,\n>\n> On Thu, 16 Jul 2009, Santi Béjar wrote:\n>\n>> Use the fork commit of the current branch (where\n>> the tip of upstream branch used to be) as the upstream parameter of\n>> \"git rebase\". Compute it walking the reflog to find the first commit\n>> which is an ancestor of the current branch.\n>\n> I finally understand what this patch is about.  Thanks.\n\nThanks, it was hard (at least for me) to provide a short and good\ncommit message.\n\n>\n>> diff --git a/git-pull.sh b/git-pull.sh\n>> index 4b78a0c..31d3945 100755\n>> --- a/git-pull.sh\n>> +++ b/git-pull.sh\n>> @@ -125,9 +125,14 @@ test true = \"$rebase\" && {\n>>       die \"refusing to pull with rebase: your working tree is not up-to-date\"\n>>\n>>       . git-parse-remote &&\n>> -     reflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n>> -     oldremoteref=\"$(git rev-parse -q --verify \\\n>> -             \"$reflist\")\"\n>> +     remoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n>> +     num=0 &&\n>> +     while oldremoteref=\"$(git rev-parse -q --verify \"$remoteref@{$num}\")\"\n>> +     do\n>\n> How about\n>\n>        oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n>                        $(git rev-list -g $remoteref | sed 's/$/^@/') |\n>                sed -e '/^[^-]/d' -e q)\"\n>\n> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n> the remote ref pointed to, and the ^@ appended to them means all their\n> parents.  Now, the outer rev-list says to take everything in HEAD but\n> _not_ in those parents, showing the boundary commits.  The \"sed\" call\n> lists the first such boundary commit (which must, by construction, be one\n> of the commits shown by the first rev-list).\n\nIt almost works, thanks. In fact this is how I represent it in my\nhead, but I couldn't find a working command (hint, hint, the\n--boundaries trick). Based on yours here it is the one I am using\nright now:\n\n\toldremoteref=\"$(git rev-list --boundary HEAD --not \\\n\t\t$(git rev-list -g $remoteref 2>/dev/null) |\n\t\tsed -e '/^[^-]/d' -e 's/^-//;q' )\"\n\ni.e. without the ^@ as you want the commits in the reflog as boundary\ncommits, and also remove the - in front of the commit.\n\nYour version performs equally than mine for the normal case but much\nbetter if it has to walk many reflog entries. Also mine has the\nproblem, at least currently, that it does not give up as \"git\nrev-parse -q --verify $branch@{n}\" does not return an error when n is\ntoo large:\n\n  $ git rev-parse -q --verify origin/next@{18} ; echo $?\nwarning: Log for 'origin/next' only has 17 entries.\n37eb784cfce07ba0048d64e352c5137454396d87\n0\n\neven with \"-q --verify\"!\n\nSo, I'll take yours and will send an updated patch (saying that is is\nbased on a command by you). With your Signed-off-by?\n\nThanks,\nSanti\n"},{"id":"118131","messageId":"7vhbxc8inp.fsf@alter.siamese.dyndns.org","threadId":"20127","inReplyTo":"alpine.DEB.1.00.0907161035060.3155@pacific.mpi-cbg.de","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-16T20:41:46Z","receivedAt":"2009-07-16T20:41:46Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> How about\n>\n> \toldremoteref=\"$(git rev-list --boundary HEAD --not \\\n> \t\t\t$(git rev-list -g $remoteref | sed 's/$/^@/') |\n> \t\tsed -e '/^[^-]/d' -e q)\"\n>\n> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits \n> the remote ref pointed to, and the ^@ appended to them means all their \n> parents.  Now, the outer rev-list says to take everything in HEAD but \n> _not_ in those parents, showing the boundary commits.  The \"sed\" call \n> lists the first such boundary commit (which must, by construction, be one \n> of the commits shown by the first rev-list).\n\nHmm, I am not sure about that \"(which must...\" part.  When you have\n\n          Y---X\n         /\n\tB---o---o---o---H\n\nwouldn't \"rev-list --boundary H --not X^@\" give B, not X nor Y?\n"},{"id":"118146","messageId":"adf1fd3d0907161618o61ee4b58of25659f8c36420f7@mail.gmail.com","threadId":"20127","inReplyTo":"7vhbxc8inp.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-16T23:18:14Z","receivedAt":"2009-07-16T23:18:14Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/16 Junio C Hamano <gitster@pobox.com>:\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>\n>> How about\n>>\n>>       oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n>>                       $(git rev-list -g $remoteref | sed 's/$/^@/') |\n>>               sed -e '/^[^-]/d' -e q)\"\n>>\n>> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n>> the remote ref pointed to, and the ^@ appended to them means all their\n>> parents.  Now, the outer rev-list says to take everything in HEAD but\n>> _not_ in those parents, showing the boundary commits.  The \"sed\" call\n>> lists the first such boundary commit (which must, by construction, be one\n>> of the commits shown by the first rev-list).\n>\n> Hmm, I am not sure about that \"(which must...\" part.  When you have\n>\n>          Y---X\n>         /\n>        B---o---o---o---H\n>\n> wouldn't \"rev-list --boundary H --not X^@\" give B, not X nor Y?\n>\n\n$git rev-list --boundary H --not X\nand\n$git rev-list --boundary H --not X^@\n\nreturn the same output in this case:\no\no\no\n-B\n\nIn this case the correct command is without ^@, because you want the\ncommits in the reflog as boundary commits.\n\nIn the simpler and usual case, without a rebased upstream:\n\n    z---B---o---o---o---H\n\nB=upstream@{0}\n\n$git rev-list --boundary H --not B^@\no\no\no\nB\n-z\n\nand:\n\n$git rev-list --boundary H --not B\no\no\no\n-B\n\nAlso in the rebased upstream case:\n\n      Y---X\n     /\n    z---B---o---o---o---H\n\n\nX=upstream@{0}\nB=upstream@{1}\n\n$git rev-list --boundary H --not X^@ B^@\no\no\no\nB\n-z\n\nand:\n\n$git rev-list --boundary H --not X B\no\no\no\n-B\n\nHTH,\nSanti\n"},{"id":"118157","messageId":"adf1fd3d0907170051u7268d8f6kba7f2e529381d275@mail.gmail.com","threadId":"20127","inReplyTo":"adf1fd3d0907161618o61ee4b58of25659f8c36420f7@mail.gmail.com","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-17T07:51:38Z","receivedAt":"2009-07-17T07:51:38Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/17 Santi Béjar <santi@agolina.net>:\n> 2009/7/16 Junio C Hamano <gitster@pobox.com>:\n>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>>\n>>> How about\n>>>\n>>>       oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n>>>                       $(git rev-list -g $remoteref | sed 's/$/^@/') |\n>>>               sed -e '/^[^-]/d' -e q)\"\n>>>\n>>> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n>>> the remote ref pointed to, and the ^@ appended to them means all their\n>>> parents.  Now, the outer rev-list says to take everything in HEAD but\n>>> _not_ in those parents, showing the boundary commits.  The \"sed\" call\n>>> lists the first such boundary commit (which must, by construction, be one\n>>> of the commits shown by the first rev-list).\n>>\n>> Hmm, I am not sure about that \"(which must...\" part.\n\nUnfortunatly you are right with the \"(which must...\" part. Even\nwithout the ^@. Normally gives the right answer, but it is not\nsure that the first commit boundary is the correct one. For\nexample:\n\n         o--C\n        /\n A--x--y--B--o--z\n     \\      /\n      o----o\n\nA, B, C are upstream@{n}\n\nIt involves a merge with a branch forked before the fork commit\nfor the current branch, and it will not work neither with git\npull --rebase. We could say that it is not supported, but\nnevertheless it gives the wrong answer.\n\nThe right answer is B, but:\n$ git rev-list --boundary z --not C B A\nz\no\no\no\n-x\n-B\n\nin this case we could take the boundaries commits and filter the\ncommits that are ancestor of some other boundary commit, and\nwould get B (git show-branch --independent x B -> B).\n\nHere it is a test case to see the above.\n\nrm -rf test\nmkdir test\ncd test\ngit init\necho A > file\ngit add .\ngit commit -mA\ngit tag A\necho o > file\ngit commit -a -mo\ngit tag fork1\necho z > file\ngit commit -a -mz\ngit tag fork2\necho B > file\ngit commit -a -mB\ngit tag B\ngit checkout -b topic fork1\necho oo > filetopic\ngit add .\ngit commit -moo\necho ooo > filetopic\ngit commit -a -mooo\ngit checkout master\ngit merge topic\necho c > file\ngit commit -a -mc\ngit checkout -b upstream fork2\necho o > fileupstream\ngit add .\ngit commit -a -mo5\necho C > fileupstream\ngit commit -a -mo\ngit tag C\ngit rev-list --boundary master --not C B A\necho answer: $(git rev-parse B^{})\n\nHTH,\nSanti\n"},{"id":"118158","messageId":"7vr5wf67iz.fsf@alter.siamese.dyndns.org","threadId":"20127","inReplyTo":"adf1fd3d0907170051u7268d8f6kba7f2e529381d275@mail.gmail.com","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-17T08:25:08Z","receivedAt":"2009-07-17T08:25:08Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Santi Béjar <santi@agolina.net> writes:\n\n> 2009/7/17 Santi Béjar <santi@agolina.net>:\n>> 2009/7/16 Junio C Hamano <gitster@pobox.com>:\n>>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>>>\n>>>> How about\n>>>>\n>>>>       oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n>>>>                       $(git rev-list -g $remoteref | sed 's/$/^@/') |\n>>>>               sed -e '/^[^-]/d' -e q)\"\n>>>>\n>>>> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n>>>> the remote ref pointed to, and the ^@ appended to them means all their\n>>>> parents.  Now, the outer rev-list says to take everything in HEAD but\n>>>> _not_ in those parents, showing the boundary commits.  The \"sed\" call\n>>>> lists the first such boundary commit (which must, by construction, be one\n>>>> of the commits shown by the first rev-list).\n>>>\n>>> Hmm, I am not sure about that \"(which must...\" part.\n>\n> Unfortunatly you are right with the \"(which must...\" part. Even\n> without the ^@. Normally gives the right answer, but it is not\n> sure that the first commit boundary is the correct one. For\n> example:\n>\n>          o--C\n>         /\n>  A--x--y--B--o--z\n>      \\      /\n>       o----o\n>\n> A, B, C are upstream@{n}\n>\n> It involves a merge with a branch forked before the fork commit\n> for the current branch, and it will not work neither with git\n> pull --rebase. We could say that it is not supported, but\n> nevertheless it gives the wrong answer.\n>\n> The right answer is B, but:\n> $ git rev-list --boundary z --not C B A\n> z\n> o\n> o\n> o\n> -x\n> -B\n\nNow a short question.  Does your original loop give a correct answer in\nthis case?\n"},{"id":"118170","messageId":"alpine.DEB.1.00.0907171211430.4495@intel-tinevez-2-302","threadId":"20127","inReplyTo":"adf1fd3d0907160932r313de6e8lec23e4f3409b8c05@mail.gmail.com","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-07-17T10:13:35Z","receivedAt":"2009-07-17T10:13:35Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 16 Jul 2009, Santi Béjar wrote:\n\n> 2009/7/16 Johannes Schindelin <Johannes.Schindelin@gmx.de>:\n>\n> > On Thu, 16 Jul 2009, Santi Béjar wrote:\n> >\n> >> Use the fork commit of the current branch (where\n> >> the tip of upstream branch used to be) as the upstream parameter of\n> >> \"git rebase\". Compute it walking the reflog to find the first commit\n> >> which is an ancestor of the current branch.\n> >\n> > I finally understand what this patch is about.  Thanks.\n> \n> Thanks, it was hard (at least for me) to provide a short and good\n> commit message.\n\nIt is the thing I found quite hard when I started contributing to Git, and \nit is still not exactly easy for me.\n\n> >> diff --git a/git-pull.sh b/git-pull.sh\n> >> index 4b78a0c..31d3945 100755\n> >> --- a/git-pull.sh\n> >> +++ b/git-pull.sh\n> >> @@ -125,9 +125,14 @@ test true = \"$rebase\" && {\n> >>       die \"refusing to pull with rebase: your working tree is not up-to-date\"\n> >>\n> >>       . git-parse-remote &&\n> >> -     reflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> >> -     oldremoteref=\"$(git rev-parse -q --verify \\\n> >> -             \"$reflist\")\"\n> >> +     remoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> >> +     num=0 &&\n> >> +     while oldremoteref=\"$(git rev-parse -q --verify \"$remoteref@{$num}\")\"\n> >> +     do\n> >\n> > How about\n> >\n> >        oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n> >                        $(git rev-list -g $remoteref | sed 's/$/^@/') |\n> >                sed -e '/^[^-]/d' -e q)\"\n> >\n> > Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n> > the remote ref pointed to, and the ^@ appended to them means all their\n> > parents.  Now, the outer rev-list says to take everything in HEAD but\n> > _not_ in those parents, showing the boundary commits.  The \"sed\" call\n> > lists the first such boundary commit (which must, by construction, be one\n> > of the commits shown by the first rev-list).\n> \n> It almost works, thanks. In fact this is how I represent it in my\n> head, but I couldn't find a working command (hint, hint, the\n> --boundaries trick). Based on yours here it is the one I am using\n> right now:\n> \n> \toldremoteref=\"$(git rev-list --boundary HEAD --not \\\n> \t\t$(git rev-list -g $remoteref 2>/dev/null) |\n> \t\tsed -e '/^[^-]/d' -e 's/^-//;q' )\"\n> \n> i.e. without the ^@ as you want the commits in the reflog as boundary\n> commits, and also remove the - in front of the commit.\n\nThanks for fixing it.  I should have mentioned that I did not test it (and \nusually stuff I do not test has blatant bugs in it, such as was the case \nhere).\n\n> Your version performs equally than mine for the normal case but much \n> better if it has to walk many reflog entries. Also mine has the problem, \n> at least currently, that it does not give up as \"git rev-parse -q \n> --verify $branch@{n}\" does not return an error when n is too large:\n> \n>   $ git rev-parse -q --verify origin/next@{18} ; echo $?\n> warning: Log for 'origin/next' only has 17 entries.\n> 37eb784cfce07ba0048d64e352c5137454396d87\n> 0\n> \n> even with \"-q --verify\"!\n> \n> So, I'll take yours and will send an updated patch (saying that is is\n> based on a command by you). With your Signed-off-by?\n\nMaybe an ACK instead?\n\nThanks,\nDscho\n"},{"id":"118173","messageId":"adf1fd3d0907170624t7c2bf8f5w35c03788fdd82422@mail.gmail.com","threadId":"20127","inReplyTo":"7vr5wf67iz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-17T13:24:21Z","receivedAt":"2009-07-17T13:24:21Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/17 Junio C Hamano <gitster@pobox.com>:\n> Santi Béjar <santi@agolina.net> writes:\n>\n>> 2009/7/17 Santi Béjar <santi@agolina.net>:\n>>> 2009/7/16 Junio C Hamano <gitster@pobox.com>:\n>>>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>>>>\n>>>>> How about\n>>>>>\n>>>>>       oldremoteref=\"$(git rev-list --boundary HEAD --not \\\n>>>>>                       $(git rev-list -g $remoteref | sed 's/$/^@/') |\n>>>>>               sed -e '/^[^-]/d' -e q)\"\n>>>>>\n>>>>> Explanation: the \"git rev-list -g $remoteref\" lists the previous commits\n>>>>> the remote ref pointed to, and the ^@ appended to them means all their\n>>>>> parents.  Now, the outer rev-list says to take everything in HEAD but\n>>>>> _not_ in those parents, showing the boundary commits.  The \"sed\" call\n>>>>> lists the first such boundary commit (which must, by construction, be one\n>>>>> of the commits shown by the first rev-list).\n>>>>\n>>>> Hmm, I am not sure about that \"(which must...\" part.\n>>\n>> Unfortunatly you are right with the \"(which must...\" part. Even\n>> without the ^@. Normally gives the right answer, but it is not\n>> sure that the first commit boundary is the correct one. For\n>> example:\n>>\n>>          o--C\n>>         /\n>>  A--x--y--B--o--z\n>>      \\      /\n>>       o----o\n>>\n>> A, B, C are upstream@{n}\n>>\n>> It involves a merge with a branch forked before the fork commit\n>> for the current branch, and it will not work neither with git\n>> pull --rebase. We could say that it is not supported, but\n>> nevertheless it gives the wrong answer.\n>>\n>> The right answer is B, but:\n>> $ git rev-list --boundary z --not C B A\n>> z\n>> o\n>> o\n>> o\n>> -x\n>> -B\n>\n> Now a short question.  Does your original loop give a correct answer in\n> this case?\n\nYes, it returns B. But there are other cases where there is not a single right\nanswer if you allow merges. For the moment the more sensible thing to do is to\nnot allow merges in the local commits. I hope nobody relies on \"git pull\n--rebase\" with local merges.\n\nJust an example:\n\n        E\n       /\n      D----a topic2\n     /      \\\n A--B--C--b--c--d--topic1\n\nA, B, C, D, E are upstream@{n} (n = 4,3,2,1,0)\n\nif you are on branch \"topic1\", and run \"git pull --rebase\" you would want to\nrebase only b, c and d (maybe \"a\" but you should not), but for sure not D.\nAnd my algorithm returns C, but a more \"correct\" answer would be C and D.\n\nAnother possibility could be to check that there is only one boundary\ncommit (only one fork point for all the local commits).\n\nWait! Let's return to the original problem. The original problem is that you\ncannot do a \"git pull --rebase\" with a rebased upstream if you have already\ndone \"git fetch\" before. And the solution would be:\nTry to behaved as if the \"git fetch\" was not run.\n\nAnd this is exactly what my patch does.\n\nAll the other \"problems\" happens already.\n\nNow I only have to solve the \"git rev-parse -q --verify upstream@{large_n}\"\nproblem or workaround it.\n\nSometimes thinks aloud,\nSanti\n"},{"id":"118230","messageId":"1247924785-31886-1-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":"adf1fd3d0907170624t7c2bf8f5w35c03788fdd82422@mail.gmail.com","subject":"[PATCHv3 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-18T13:46:25Z","receivedAt":"2009-07-18T13:46:25Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"The problem is that you cannot do a \"git pull --rebase\" with a rebased\nupstream if you have already run \"git fetch\" before. And the solution:\nTry to behaved as if the \"git fetch\" was not run.\n\nOr in other words, use the fork commit of the current branch (where\nthe tip of upstream branch used to be) as the upstream parameter of\n\"git rebase\".\n\nCompute it walking the reflog to find the first commit which is an\nancestor of the current branch.  Maybe there are smarter ways to\ncompute it, but this is a straight forward implementation of the above\n\"Try to behaved as if the \"git fetch\" was not run\".\n\nSigned-off-by: Santi Béjar <santi@agolina.net>\n---\nChanges since v2:\n  - Hopefully enhance the commit log\n  - Use a 'for' loop for the reflog entries\n  - provide a default value in case there is no reflog\nChanged since v1:\n  - rename reflist to remoteref to better reflect its use\n  - (( $num + 1 ))\n\n git-pull.sh     |   11 +++++++++--\n t/t5520-pull.sh |    5 ++---\n 2 files changed, 11 insertions(+), 5 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 4b78a0c..c8f1674 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -125,9 +125,16 @@ test true = \"$rebase\" && {\n \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n \n \t. git-parse-remote &&\n-\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n+\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n+\toldremoteref= &&\n+\tfor reflog in $(git rev-list -g $remoteref 2>/dev/null)\n+\tdo\n+\t\ttest $reflog = $(git merge-base $reflog $curr_branch) &&\n+\t\toldremoteref=$reflog && break\n+\tdone\n+\t[ -z \"$oldremoteref\" ] &&\n \toldremoteref=\"$(git rev-parse -q --verify \\\n-\t\t\"$reflist\")\"\n+\t\t\"$remoteref\")\"\n }\n orig_head=$(git rev-parse -q --verify HEAD)\n git fetch $verbosity --update-head-ok \"$@\" || exit 1\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 1aae494..37a7e33 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -117,15 +117,14 @@ test_expect_success '--rebase with rebased default upstream' '\n \n '\n \n-test_expect_failure 'rebased upstream + fetch + pull --rebase' '\n+test_expect_success 'rebased upstream + fetch + pull --rebase' '\n \n \tgit update-ref refs/remotes/me/copy copy-orig &&\n \tgit reset --hard to-rebase-orig &&\n \tgit checkout --track -b to-rebase3 me/copy &&\n \tgit reset --hard to-rebase-orig &&\n \tgit fetch &&\n-\ttest_must_fail git pull --rebase &&\n-\tgit rebase --abort &&\n+\tgit pull --rebase &&\n \ttest \"conflicting modification\" = \"$(cat file)\" &&\n \ttest file = $(cat file2)\n \n-- \n1.6.3.2.408.g8ecf\n"},{"id":"118239","messageId":"7vk5253mg8.fsf@alter.siamese.dyndns.org","threadId":"20127","inReplyTo":"1247924785-31886-1-git-send-email-santi@agolina.net","subject":"Re: [PATCHv3 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-18T17:55:35Z","receivedAt":"2009-07-18T17:55:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Santi Béjar <santi@agolina.net> writes:\n\n> Changes since v2:\n>   - Hopefully enhance the commit log\n>   - Use a 'for' loop for the reflog entries\n>   - provide a default value in case there is no reflog\n> diff --git a/git-pull.sh b/git-pull.sh\n> index 4b78a0c..c8f1674 100755\n> --- a/git-pull.sh\n> +++ b/git-pull.sh\n> @@ -125,9 +125,16 @@ test true = \"$rebase\" && {\n>  \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n>  \n>  \t. git-parse-remote &&\n> -\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> +\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n> +\toldremoteref= &&\n> +\tfor reflog in $(git rev-list -g $remoteref 2>/dev/null)\n> +\tdo\n> +\t\ttest $reflog = $(git merge-base $reflog $curr_branch) &&\n> +\t\toldremoteref=$reflog && break\n> +\tdone\n> +\t[ -z \"$oldremoteref\" ] &&\n>  \toldremoteref=\"$(git rev-parse -q --verify \\\n> -\t\t\"$reflist\")\"\n> +\t\t\"$remoteref\")\"\n>  }\n\nLooks nicer.\n\nI notice that you are breaking && chain with this patch.\n\nIf get_remote_merge_branch fails, oldremoteref is not initialized to empty\nstring, the for loop is skipped and then the last step (by the way, please\nwrite that as 'test -z \"$oldremoteref\"') may not kick in, using whatever\nrandom value the variable originally had in the environment.\n\nIt probably makes more sense to do it in a slightly different order:\n\n        . git-parse-remote &&\n        oldremoteref=\"$(get_remote_merge...)\" &&\n\tremoteref=$oldremoteref &&\n        for old in $(git rev-list -g \"$remoteref\" 2>/dev/null)\n        do\n        \tif test \"$old\" = \"$(git merge-base \"$old\" \"$current_branch\")\n\t\tthen\n\t\t\toldremoteref=\"$old\"\n\t\t\tbreak\n                fi\n\tdone\n\t# and you do not need 'if test -z \"$oldremoteref\"' anymore...\n\nBut other than that, I agree that this is the most straightforward\nalgorithm to express what you wanted to do.  I guess another possibility\nis to instead look in the reflog of the _current_ branch to check how the\nprevious rebase was done, iow, find out onto which commit the recent part\nof the current branch was rebased to, and rebase onto the current remote\ntip using that as the base.\n"},{"id":"118257","messageId":"adf1fd3d0907190027s2bf5380er8e59a60d1a3637ad@mail.gmail.com","threadId":"20127","inReplyTo":"7vk5253mg8.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv3 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-19T07:27:43Z","receivedAt":"2009-07-19T07:27:43Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"2009/7/18 Junio C Hamano <gitster@pobox.com>:\n> Santi Béjar <santi@agolina.net> writes:\n>\n>> Changes since v2:\n>>   - Hopefully enhance the commit log\n>>   - Use a 'for' loop for the reflog entries\n>>   - provide a default value in case there is no reflog\n>> diff --git a/git-pull.sh b/git-pull.sh\n>> index 4b78a0c..c8f1674 100755\n>> --- a/git-pull.sh\n>> +++ b/git-pull.sh\n>> @@ -125,9 +125,16 @@ test true = \"$rebase\" && {\n>>       die \"refusing to pull with rebase: your working tree is not up-to-date\"\n>>\n>>       . git-parse-remote &&\n>> -     reflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n>> +     remoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n>> +     oldremoteref= &&\n>> +     for reflog in $(git rev-list -g $remoteref 2>/dev/null)\n>> +     do\n>> +             test $reflog = $(git merge-base $reflog $curr_branch) &&\n>> +             oldremoteref=$reflog && break\n>> +     done\n>> +     [ -z \"$oldremoteref\" ] &&\n>>       oldremoteref=\"$(git rev-parse -q --verify \\\n>> -             \"$reflist\")\"\n>> +             \"$remoteref\")\"\n>>  }\n>\n> If get_remote_merge_branch fails, oldremoteref is not initialized to empty\n> string, the for loop is skipped and then the last step (by the way, please\n> write that as 'test -z \"$oldremoteref\"') may not kick in, using whatever\n> random value the variable originally had in the environment.\n\nNot a justification but it also happens with the original code.\n\n>\n> It probably makes more sense to do it in a slightly different order:\n>\n>        . git-parse-remote &&\n>        oldremoteref=\"$(get_remote_merge...)\" &&\n\noldremotref must be a sha1, because it changes during the fetch. But\nI'll use more o less this order.\n\n>        remoteref=$oldremoteref &&\n>        for old in $(git rev-list -g \"$remoteref\" 2>/dev/null)\n>        do\n>                if test \"$old\" = \"$(git merge-base \"$old\" \"$current_branch\")\n>                then\n>                        oldremoteref=\"$old\"\n>                        break\n>                fi\n>        done\n>        # and you do not need 'if test -z \"$oldremoteref\"' anymore...\n>\n> But other than that, I agree that this is the most straightforward\n> algorithm to express what you wanted to do.  I guess another possibility\n> is to instead look in the reflog of the _current_ branch to check how the\n> previous rebase was done, iow, find out onto which commit the recent part\n> of the current branch was rebased to, and rebase onto the current remote\n> tip using that as the base.\n\nIt supposes that it was rebased already, and you have to interpret the\nreflog history. And there are situations where you don't get the same\nanswer, i.e you create a new local branch using another local branch\nas the starting point but with the same upstream.\n\nSanti\n"},{"id":"118258","messageId":"1247989516-11508-1-git-send-email-santi@agolina.net","threadId":"20127","inReplyTo":"adf1fd3d0907190027s2bf5380er8e59a60d1a3637ad@mail.gmail.com","subject":"[PATCHv4 2/2] pull: support rebased upstream + fetch + pull --rebase","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2009-07-19T07:45:16Z","receivedAt":"2009-07-19T07:45:16Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"The problem is that you cannot do a \"git pull --rebase\" with a rebased\nupstream if you have already run \"git fetch\" before. And the solution:\nTry to behaved as if the \"git fetch\" was not run.\n\nOr in other words, use the fork commit of the current branch (where\nthe tip of upstream branch used to be) as the upstream parameter of\n\"git rebase\".\n\nCompute it walking the reflog to find the first commit which is an\nancestor of the current branch.  Maybe there are smarter ways to\ncompute it, but this is a straight forward implementation of the above\n\"Try to behaved as if the \"git fetch\" was not run\".\n\nSigned-off-by: Santi Béjar <santi@agolina.net>\n---\n\nChanges since v3:\n  - Provide the default at the begining\n  - some quotes\n  - replace && chain with an if\nChanges since v2:\n  - Hopefully enhance the commit log\n  - Use a 'for' loop for the reflog entries\n  - provide a default value in case there is no reflog\nChanged since v1:\n  - rename reflist to remoteref to better reflect its use\n  - (( $num + 1 ))\n git-pull.sh     |   13 +++++++++++--\n t/t5520-pull.sh |    5 ++---\n 2 files changed, 13 insertions(+), 5 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 4b78a0c..a7795b0 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -124,10 +124,19 @@ test true = \"$rebase\" && {\n \tgit diff-index --ignore-submodules --cached --quiet HEAD -- ||\n \tdie \"refusing to pull with rebase: your working tree is not up-to-date\"\n \n+\toldremoteref= &&\n \t. git-parse-remote &&\n-\treflist=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n+\tremoteref=\"$(get_remote_merge_branch \"$@\" 2>/dev/null)\" &&\n \toldremoteref=\"$(git rev-parse -q --verify \\\n-\t\t\"$reflist\")\"\n+\t\t\"$remoteref\")\" &&\n+\tfor reflog in $(git rev-list -g $remoteref 2>/dev/null)\n+\tdo\n+\t\tif test \"$reflog\" = \"$(git merge-base $reflog $curr_branch)\"\n+\t\tthen\n+\t\t\toldremoteref=\"$reflog\"\n+\t\t\tbreak\n+\t\tfi\n+\tdone\n }\n orig_head=$(git rev-parse -q --verify HEAD)\n git fetch $verbosity --update-head-ok \"$@\" || exit 1\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 1aae494..37a7e33 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -117,15 +117,14 @@ test_expect_success '--rebase with rebased default upstream' '\n \n '\n \n-test_expect_failure 'rebased upstream + fetch + pull --rebase' '\n+test_expect_success 'rebased upstream + fetch + pull --rebase' '\n \n \tgit update-ref refs/remotes/me/copy copy-orig &&\n \tgit reset --hard to-rebase-orig &&\n \tgit checkout --track -b to-rebase3 me/copy &&\n \tgit reset --hard to-rebase-orig &&\n \tgit fetch &&\n-\ttest_must_fail git pull --rebase &&\n-\tgit rebase --abort &&\n+\tgit pull --rebase &&\n \ttest \"conflicting modification\" = \"$(cat file)\" &&\n \ttest file = $(cat file2)\n \n-- \n1.6.4.rc1.2.gb13e8\n"}]}