{"thread":{"id":"25735","subject":"[RFC] rebase: be cleverer with rebased upstream branches","startedAt":"2010-11-12T20:11:53Z","lastAt":"2010-11-14T02:46:03Z","messageCount":3,"participants":["Martin von Zweigbergk","Santi Béjar"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"155818","messageId":"1289592713-11786-1-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"25735","inReplyTo":null,"subject":"[RFC] rebase: be cleverer with rebased upstream branches","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2010-11-12T20:11:53Z","receivedAt":"2010-11-12T20:11:53Z","isPatch":false,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"Since c85c792 (pull --rebase: be cleverer with rebased upstream\nbranches, 2008-01-26), 'git pull --rebase' has used the reflog to try to\nrebase from the old upstream onto the new upstream.\n\nHowever, if, instead of 'git pull --rebase', the user were to do 'git\nfetch' followed by 'git rebase @{upstream}', the reflog would not be\nwalked. This patch teaches \"git rebase\" the same reflog-walking tricks\nthat 'git pull --rebase' already knows.\n\nApart from making 'git rebase' better aligned with 'git pull --rebase',\nthis may also be useful on its own for rebasing one branch against\nanother local branch that has been rebased. Currently, you would have to\ndo that using 'git rebase --onto' or by configuring it on the branch.\n\nIt might seem like most of the related code in git-pull.sh can be\nremoved once git-rebase.sh supports reflog walking. Unfortunately, not\nmuch of it can be removed, though. The reason is that git-pull.sh does\none step of 'reflog' walking even when the reflog is not used. There are\nat least two cases where the reflog is not used: a) when it is disabled,\nb) when the remote branch was specified on the command line (let's say\n'git pull --rebase origin master'). In both of these cases, git-pull.sh\nremembers the position of the reference before the fetch and uses that\nin place of '$ref@{1}'.\n---\nJunio, don't apply this patch yet, as I will rebase it on top of the\nrefactored rebase code once I'm done with that (to make it work with\ninteractive rebase as well).\n\nHowever, it should apply cleanly on top of the patches in\nhttp://thread.gmane.org/gmane.comp.version-control.git/160682/, and maybe\neven right on top of master.\n\nThe documentation was copied from git-pull before the patch on on that\ndocumentation that I sent out a little while ago, so the documentation\nfor this patch will at the very least be updated accordingly.\n\nShould the \"RECOVERING FROM UPSTREAM REBASE\" section of\nDocumentation/git-rebase.txt be updated?\n\n\n Documentation/git-rebase.txt |    7 ++++++-\n git-rebase.sh                |   13 +++++++++++++\n t/t3400-rebase.sh            |   26 ++++++++++++++++++++++++++\n 3 files changed, 45 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 30e5c0e..1baddd2 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -24,7 +24,12 @@ it remains on the current branch.\n All changes made by commits in the current branch but that are not\n in <upstream> are saved to a temporary area.  This is the same set\n of commits that would be shown by `git log <upstream>..HEAD` (or\n-`git log HEAD`, if --root is specified).\n+`git log HEAD`, if --root is specified). If, however, there is a ref\n+for the upstream branch, and this branch was rebased since the\n+current branch was last rebased, the rebase uses that information to\n+avoid rebasing changes done on the upstream branch. If you do not want\n+'git rebase' to use this intelligence, refer to the upstream without\n+using a reference (e.g. 'master~0').\n \n The current branch is reset to <upstream>, or <newbase> if the\n --onto option was supplied.  This has the exact same effect as\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 847555c..fade99a 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -495,6 +495,19 @@ case \"$#\" in\n esac\n orig_head=$branch\n \n+test -n $upstream_name && for reflog in \\\n+\t$(git rev-list -g $upstream_name 2>/dev/null)\n+do\n+\tif test $reflog = $(git merge-base $reflog $branch)\n+\tthen\n+\t\tif test $reflog != $(git merge-base $onto $reflog)\n+\t\tthen\n+\t\t\tupstream=$reflog\n+\t\tfi\n+\t\tbreak\n+\tfi\n+done\n+\n # Now we are rebasing commits $upstream..$branch (or with --root,\n # everything leading up to $branch) on top of $onto\n \ndiff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh\nindex 349eebd..b64df31 100755\n--- a/t/t3400-rebase.sh\n+++ b/t/t3400-rebase.sh\n@@ -209,4 +209,30 @@ test_expect_success 'rebase -m can copy notes' '\n \ttest \"a note\" = \"$(git notes show HEAD)\"\n '\n \n+test_expect_success 'rebase against rebased upstream uses reflog' '\n+\tgit checkout my-topic-branch &&\n+\techo \"Conflicting modification\" > B &&\n+\tgit add B &&\n+\tgit commit -m \"Modify B\" &&\n+\tgit reset --hard nonlinear &&\n+\tgit checkout -b old-topic my-topic-branch@{1} &&\n+\techo def > D &&\n+\tgit add D &&\n+\tgit commit -m \"Add D\" &&\n+\tgit rebase my-topic-branch &&\n+\ttest $(git rev-parse HEAD^) = $(git rev-parse my-topic-branch)\n+'\n+\n+test_expect_success 'rebase against forwarded upstream does not reapply patches' '\n+\tgit checkout my-topic-branch &&\n+\techo abc > B &&\n+\tgit add B &&\n+\tgit commit -m \"Conficting B\" &&\n+\tgit reset HEAD~2 &&\n+\tgit reset HEAD@{1} &&\n+\tgit checkout old-topic &&\n+\tgit rebase my-topic-branch &&\n+\ttest $(git rev-parse HEAD^) = $(git rev-parse my-topic-branch)\n+'\n+\n test_done\n-- \n1.7.3.2.167.ga361b\n"},{"id":"155836","messageId":"AANLkTincij4wR4=RhbA0oCwe66OhVry0AkS6GCALVWmz@mail.gmail.com","threadId":"25735","inReplyTo":"1289592713-11786-1-git-send-email-martin.von.zweigbergk@gmail.com","subject":"Re: [RFC] rebase: be cleverer with rebased upstream branches","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2010-11-13T23:30:47Z","receivedAt":"2010-11-13T23:30:47Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Fri, Nov 12, 2010 at 9:11 PM, Martin von Zweigbergk\n<martin.von.zweigbergk@gmail.com> wrote:\n> Since c85c792 (pull --rebase: be cleverer with rebased upstream\n> branches, 2008-01-26), 'git pull --rebase' has used the reflog to try to\n> rebase from the old upstream onto the new upstream.\n>\n> However, if, instead of 'git pull --rebase', the user were to do 'git\n> fetch' followed by 'git rebase @{upstream}', the reflog would not be\n> walked. This patch teaches \"git rebase\" the same reflog-walking tricks\n> that 'git pull --rebase' already knows.\n>\n> Apart from making 'git rebase' better aligned with 'git pull --rebase',\n> this may also be useful on its own for rebasing one branch against\n> another local branch that has been rebased. Currently, you would have to\n> do that using 'git rebase --onto' or by configuring it on the branch.\n>\n> It might seem like most of the related code in git-pull.sh can be\n> removed once git-rebase.sh supports reflog walking. Unfortunately, not\n> much of it can be removed, though. The reason is that git-pull.sh does\n> one step of 'reflog' walking even when the reflog is not used. There are\n> at least two cases where the reflog is not used: a) when it is disabled,\n> b) when the remote branch was specified on the command line (let's say\n> 'git pull --rebase origin master'). In both of these cases, git-pull.sh\n> remembers the position of the reference before the fetch and uses that\n> in place of '$ref@{1}'.\n\nIn the code I don't see when b) is different to call it without\ncommand line branches. And if it is different I suppose it is a bug.\n\nThe code must stay in git-pull.sh because there it has more\ninformation (commit before and after fetch) than in git-rebase,\nessentially when reflogs are disabled.\n\n> ---\n> Junio, don't apply this patch yet, as I will rebase it on top of the\n> refactored rebase code once I'm done with that (to make it work with\n> interactive rebase as well).\n\n>From a cursory view it looks ok.\n\nSanti\n"},{"id":"155840","messageId":"AANLkTikvpXpFH81q6f-xp5zKCNGFpYoVO7D9-Cy2M_J7@mail.gmail.com","threadId":"25735","inReplyTo":"AANLkTincij4wR4=RhbA0oCwe66OhVry0AkS6GCALVWmz@mail.gmail.com","subject":"Re: [RFC] rebase: be cleverer with rebased upstream branches","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2010-11-14T02:46:03Z","receivedAt":"2010-11-14T02:46:03Z","isPatch":false,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"On Sat, Nov 13, 2010 at 6:30 PM, Santi Béjar <santi@agolina.net> wrote:\n> On Fri, Nov 12, 2010 at 9:11 PM, Martin von Zweigbergk\n> <martin.von.zweigbergk@gmail.com> wrote:\n>> Since c85c792 (pull --rebase: be cleverer with rebased upstream\n>> branches, 2008-01-26), 'git pull --rebase' has used the reflog to try to\n>> rebase from the old upstream onto the new upstream.\n>>\n>> However, if, instead of 'git pull --rebase', the user were to do 'git\n>> fetch' followed by 'git rebase @{upstream}', the reflog would not be\n>> walked. This patch teaches \"git rebase\" the same reflog-walking tricks\n>> that 'git pull --rebase' already knows.\n>>\n>> Apart from making 'git rebase' better aligned with 'git pull --rebase',\n>> this may also be useful on its own for rebasing one branch against\n>> another local branch that has been rebased. Currently, you would have to\n>> do that using 'git rebase --onto' or by configuring it on the branch.\n>>\n>> It might seem like most of the related code in git-pull.sh can be\n>> removed once git-rebase.sh supports reflog walking. Unfortunately, not\n>> much of it can be removed, though. The reason is that git-pull.sh does\n>> one step of 'reflog' walking even when the reflog is not used. There are\n>> at least two cases where the reflog is not used: a) when it is disabled,\n>> b) when the remote branch was specified on the command line (let's say\n>> 'git pull --rebase origin master'). In both of these cases, git-pull.sh\n>> remembers the position of the reference before the fetch and uses that\n>> in place of '$ref@{1}'.\n>\n> In the code I don't see when b) is different to call it without\n> command line branches. And if it is different I suppose it is a bug.\n\nThe difference is somewhere in the code for 'git fetch'. I'm trying to\nrefer to the same thing as I did in\nhttp://thread.gmane.org/gmane.comp.version-control.git/160004/focus=160939.\n\n> The code must stay in git-pull.sh because there it has more\n> information (commit before and after fetch) than in git-rebase,\n> essentially when reflogs are disabled.\n\nYes, I think that's what I meant by reason 'a)', but maybe I could have\nexplained it in a better way.\n"}]}