{"thread":{"id":"11693","subject":"Should \"pull --rebase\" try to be a little cleverer?","startedAt":"2008-01-21T15:47:13Z","lastAt":"2008-01-26T19:49:13Z","messageCount":8,"participants":["Johannes Schindelin","Nicolas Pitre","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"66144","messageId":"alpine.LSU.1.00.0801211542150.5731@racer.site","threadId":"11693","inReplyTo":null,"subject":"Should \"pull --rebase\" try to be a little cleverer?","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-01-21T15:47:13Z","receivedAt":"2008-01-21T15:47:13Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nlast night an idea hit me: if I \"git pull --rebase blabla master\", it \ncould be that \"blabla\" decided to rebase \"master\" already, and ATM this \nwould lead to quite a few conflicts, since commits that were not mine were \nrewritten.\n\nHowever, if we already have refs/remotes/blabla/master, we could DWIM the \n--rebase call to\n\n\tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n\nOf course, this would mean that git-pull would need to source \ngit-parse-remote again...\n\nCiao,\nDscho\n"},{"id":"66145","messageId":"alpine.LFD.1.00.0801211054320.20753@xanadu.home","threadId":"11693","inReplyTo":"alpine.LSU.1.00.0801211542150.5731@racer.site","subject":"Re: Should \"pull --rebase\" try to be a little cleverer?","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2008-01-21T16:03:37Z","receivedAt":"2008-01-21T16:03:37Z","isPatch":false,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Mon, 21 Jan 2008, Johannes Schindelin wrote:\n\n> Hi,\n> \n> last night an idea hit me: if I \"git pull --rebase blabla master\", it \n> could be that \"blabla\" decided to rebase \"master\" already, and ATM this \n> would lead to quite a few conflicts, since commits that were not mine were \n> rewritten.\n\nIndeed.\n\n> However, if we already have refs/remotes/blabla/master, we could DWIM the \n> --rebase call to\n> \n> \tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n\nI was believing this was already the case.  Mind you, I never verified \nit.\n\nI think the best is really to have the equivalent of:\n\n\tgit fetch blabla/master\n\tgit rebase --onto blabla/master blabla/master@{1} HEAD\n\n\nNicolas\n"},{"id":"66148","messageId":"alpine.LSU.1.00.0801211619530.5731@racer.site","threadId":"11693","inReplyTo":"alpine.LFD.1.00.0801211054320.20753@xanadu.home","subject":"Re: Should \"pull --rebase\" try to be a little cleverer?","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-01-21T16:21:14Z","receivedAt":"2008-01-21T16:21:14Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 21 Jan 2008, Nicolas Pitre wrote:\n\n> On Mon, 21 Jan 2008, Johannes Schindelin wrote:\n> \n> > last night an idea hit me: if I \"git pull --rebase blabla master\", it \n> > could be that \"blabla\" decided to rebase \"master\" already, and ATM \n> > this would lead to quite a few conflicts, since commits that were not \n> > mine were rewritten.\n> \n> Indeed.\n> \n> > However, if we already have refs/remotes/blabla/master, we could DWIM \n> > the --rebase call to\n> > \n> > \tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n> \n> I was believing this was already the case.  Mind you, I never verified \n> it.\n> \n> I think the best is really to have the equivalent of:\n> \n> \tgit fetch blabla/master\n> \tgit rebase --onto blabla/master blabla/master@{1} HEAD\n\nNot exactly... what would you do with this:\n\n\tgit pull --rebase git://git.kernel.org/... master\n\nHm?\n\nSo I think that _only_ in the case that a remote ref is updated, _and_ \nthat there is already one, can we do the DWIMery.\n\nCiao,\nDscho\n"},{"id":"66149","messageId":"alpine.LFD.1.00.0801211140170.20753@xanadu.home","threadId":"11693","inReplyTo":"alpine.LSU.1.00.0801211619530.5731@racer.site","subject":"Re: Should \"pull --rebase\" try to be a little cleverer?","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2008-01-21T16:42:25Z","receivedAt":"2008-01-21T16:42:25Z","isPatch":false,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Mon, 21 Jan 2008, Johannes Schindelin wrote:\n\n> Hi,\n> \n> On Mon, 21 Jan 2008, Nicolas Pitre wrote:\n> \n> > On Mon, 21 Jan 2008, Johannes Schindelin wrote:\n> > \n> > > last night an idea hit me: if I \"git pull --rebase blabla master\", it \n> > > could be that \"blabla\" decided to rebase \"master\" already, and ATM \n> > > this would lead to quite a few conflicts, since commits that were not \n> > > mine were rewritten.\n> > \n> > Indeed.\n> > \n> > > However, if we already have refs/remotes/blabla/master, we could DWIM \n> > > the --rebase call to\n> > > \n> > > \tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n> > \n> > I was believing this was already the case.  Mind you, I never verified \n> > it.\n> > \n> > I think the best is really to have the equivalent of:\n> > \n> > \tgit fetch blabla/master\n> > \tgit rebase --onto blabla/master blabla/master@{1} HEAD\n> \n> Not exactly... what would you do with this:\n> \n> \tgit pull --rebase git://git.kernel.org/... master\n> \n> Hm?\n> \n> So I think that _only_ in the case that a remote ref is updated, _and_ \n> that there is already one, can we do the DWIMery.\n\nWell, sure.  That's the case I care about.\n\n\nNicolas\n"},{"id":"66161","messageId":"7vir1nxcoh.fsf@gitster.siamese.dyndns.org","threadId":"11693","inReplyTo":"alpine.LSU.1.00.0801211542150.5731@racer.site","subject":"Re: Should \"pull --rebase\" try to be a little cleverer?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-21T18:21:02Z","receivedAt":"2008-01-21T18:21:02Z","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> However, if we already have refs/remotes/blabla/master, we could DWIM the \n> --rebase call to\n>\n> \tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n\nFWIW, I like it, and I think that is what users expect it to do.\n"},{"id":"66644","messageId":"alpine.LSU.1.00.0801261801360.23907@racer.site","threadId":"11693","inReplyTo":"7vir1nxcoh.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] pull --rebase: be cleverer with rebased upstream branches","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-01-26T18:04:37Z","receivedAt":"2008-01-26T18:04:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen the upstream branch is tracked, we can detect if that branch\nwas rebased since it was last fetched.  Teach git to use that\ninformation to rebase from the old remote head onto the new remote head.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Mon, 21 Jan 2008, Junio C Hamano wrote:\n\n\t> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\t> \n\t> > However, if we already have refs/remotes/blabla/master, we \n\t> > could DWIM the --rebase call to\n\t> >\n\t> > \tgit rebase --onto FETCH_HEAD refs/remotes/blabla/master\n\t> \n\t> FWIW, I like it, and I think that is what users expect it to do.\n\n\tSorry, took me quite some time.\n\n\tBut I had a problem with the documentation: how am I supposed to \n\tdo the continuation of an indented paragraph, without using that \n\tugly \"+\" and unindenting the next paragraph?\n\n Documentation/git-pull.txt |    6 +++++-\n git-pull.sh                |   12 +++++++++++-\n t/t5520-pull.sh            |   17 +++++++++++++++++\n 3 files changed, 33 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex f9f1e0d..4cc633a 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -35,7 +35,11 @@ include::urls-remotes.txt[]\n include::merge-strategies.txt[]\n \n \\--rebase::\n-\tInstead of a merge, perform a rebase after fetching.\n+\tInstead of a merge, perform a rebase after fetching.  If\n+\tthere is a remote ref for the upstream branch, and this branch\n+\twas rebased since last fetched, the rebase uses that information\n+\tto avoid rebasing non-local changes.\n+\n \t*NOTE:* This is a potentially _dangerous_ mode of operation.\n \tIt rewrites history, which does not bode well when you\n \tpublished that history already.  Do *not* use this option\ndiff --git a/git-pull.sh b/git-pull.sh\nindex fa97b0f..46da0f4 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -106,6 +106,15 @@ error_on_no_merge_candidates () {\n \texit 1\n }\n \n+test true = \"$rebase\" && {\n+\t. git-parse-remote &&\n+\torigin=\"$1\"\n+\ttest -z \"$origin\" && origin=$(get_default_remote)\n+\treflist=\"$(get_remote_refs_for_fetch \"$@\" 2>/dev/null |\n+\t\tsed \"s|refs/heads/\\(.*\\):|\\1|\")\" &&\n+\toldremoteref=\"$(git rev-parse --verify \\\n+\t\t\"refs/remotes/$origin/$reflist\" 2>/dev/null)\"\n+}\n orig_head=$(git rev-parse --verify HEAD 2>/dev/null)\n git-fetch --update-head-ok \"$@\" || exit 1\n \n@@ -164,6 +173,7 @@ then\n fi\n \n merge_name=$(git fmt-merge-msg <\"$GIT_DIR/FETCH_HEAD\") || exit\n-test true = \"$rebase\" && exec git-rebase $merge_head\n+test true = \"$rebase\" &&\n+\texec git-rebase --onto $merge_head ${oldremoteref:-$merge_head}\n exec git-merge $no_summary $no_commit $squash $no_ff $strategy_args \\\n \t\"$merge_name\" HEAD $merge_head\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 52b3a0c..9484129 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -71,8 +71,25 @@ test_expect_success 'branch.to-rebase.rebase' '\n \tgit reset --hard before-rebase &&\n \tgit config branch.to-rebase.rebase 1 &&\n \tgit pull . copy &&\n+\tgit config branch.to-rebase.rebase 0 &&\n \ttest $(git rev-parse HEAD^) = $(git rev-parse copy) &&\n \ttest new = $(git show HEAD:file2)\n '\n \n+test_expect_success '--rebase with rebased upstream' '\n+\n+\tgit remote add -f me . &&\n+\tgit checkout copy &&\n+\tgit reset --hard HEAD^ &&\n+\techo conflicting modification > file &&\n+\tgit commit -m conflict file &&\n+\tgit checkout to-rebase &&\n+\techo file > file2 &&\n+\tgit commit -m to-rebase file2 &&\n+\tgit pull --rebase me copy &&\n+\ttest \"conflicting modification\" = \"$(cat file)\" &&\n+\ttest file = $(cat file2)\n+\n+'\n+\n test_done\n-- \n1.5.4.rc4.36.g6e122\n"},{"id":"66645","messageId":"7vk5lwz8ia.fsf@gitster.siamese.dyndns.org","threadId":"11693","inReplyTo":"alpine.LSU.1.00.0801261801360.23907@racer.site","subject":"Re: [PATCH] pull --rebase: be cleverer with rebased upstream branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-26T19:34:05Z","receivedAt":"2008-01-26T19:34:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> When the upstream branch is tracked, we can detect if that branch\n> was rebased since it was last fetched.  Teach git to use that\n> information to rebase from the old remote head onto the new remote head.\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nThis is certainly nicer than the original (which is not in\n1.5.3, so even this late in the cycle it is \"fixing up a new\nfeature we will be introducing in 1.5.4\" category that I will\napply).  But I think a bit of caution and perhaps an\nillustration or two in the doucmentation would help.\n\nIf you do \"git fetch\" from the origin since the last time you\nran \"pull --rebase\" for the remote, we will have the same\nissue.  Suppose you have this history:\n\n                   .---x---x---x\n                  /\n         .---A---B\n        /\n    ---0---o---o---A'--B'--C'--D'\n                \\\n                 o---o---A''-B''-C''-D''-E''\n\nOriginally your upstream had 0---A---B; you built your 'x' on\ntop of it.  Then the upstream rebases and publishes history that\nleads to D' (i.e. A and B are rewritten).  Later, the history is\nfurther rewritten and E'' is the latest upstream tip.\n\nIf you haven't done \"git fetch\" since you started building on\ntop of B, refs/remotes/ will still say B and using B as base\n(and E'' as onto) will give you the right rebase.  Earlier, we\ndid not use B in the rebase in any way, so your patch is\ndefinitely an improvement.\n\nHowever, if you have run \"git fetch\" (say, to peek what the\nupstream has been up to), your refs/remote/ may say D'.  Using\nthat as the base and rebasing onto E'' is not quite optimal,\nisn't it?\n\nSo it might make sense to make the logic to figure out B, given\nyour local history that leads from 0 to x's (and nothing else),\na bit cleverer than looking at the tracking branch.  We can look\nat reflog for example.  \"git log -g --pretty=oneline\" may have\nentries of this form:\n\n    * branch: Created from B\n    * rebase finished <branch> onto B\n\nand the latest (i.e. younguest) entry is where the part of your\ncurrent history to be rebased (i.e. base commit) starts.  This\nis much more reliable than looking at the tracking branch, whose\nanswer may or may not match B at all.\n\nI do not mean this comment makes your approach invalid, though.\nIt is a start in the good direction.\n"},{"id":"66646","messageId":"alpine.LSU.1.00.0801261945210.23907@racer.site","threadId":"11693","inReplyTo":"7vk5lwz8ia.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] pull --rebase: be cleverer with rebased upstream branches","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-01-26T19:49:13Z","receivedAt":"2008-01-26T19:49:13Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 26 Jan 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > When the upstream branch is tracked, we can detect if that branch was \n> > rebased since it was last fetched.  Teach git to use that information \n> > to rebase from the old remote head onto the new remote head.\n> \n> This is certainly nicer than the original (which is not in 1.5.3, so \n> even this late in the cycle it is \"fixing up a new feature we will be \n> introducing in 1.5.4\" category that I will apply).  But I think a bit of \n> caution and perhaps an illustration or two in the doucmentation would \n> help.\n\nWell, I half expected it to be post-1.5.4.\n\n> If you do \"git fetch\" from the origin since the last time you ran \"pull \n> --rebase\" for the remote, we will have the same issue.\n\nYes, that occurred to me, too.\n\n> So it might make sense to make the logic to figure out B, given\n> your local history that leads from 0 to x's (and nothing else),\n> a bit cleverer than looking at the tracking branch.  We can look\n> at reflog for example.  \"git log -g --pretty=oneline\" may have\n> entries of this form:\n> \n>     * branch: Created from B\n>     * rebase finished <branch> onto B\n> \n> and the latest (i.e. younguest) entry is where the part of your current \n> history to be rebased (i.e. base commit) starts.  This is much more \n> reliable than looking at the tracking branch, whose answer may or may \n> not match B at all.\n\nI did not want to do that, because it is quite possible that the reflogs \nwere disabled, or that the relevant reflogs were already expired.\n\nHowever, I think that it might be a good approach to try reflogs first, \nand fallback to what I sent if there are no reflogs (or if it is detected \nthat the reflog entry is not possibly the correct one, since what was \nrebased to is no longer an ancestor of the current branch).\n\nCiao,\nDscho\n"}]}