git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Should "pull --rebase" try to be a little cleverer?
@ 2008-01-21 15:47 Johannes Schindelin
  2008-01-21 16:03 ` Nicolas Pitre
  2008-01-21 18:21 ` Junio C Hamano
  0 siblings, 2 replies; 8+ messages in thread
From: Johannes Schindelin @ 2008-01-21 15:47 UTC (permalink / raw)
  To: git

Hi,

last night an idea hit me: if I "git pull --rebase blabla master", it 
could be that "blabla" decided to rebase "master" already, and ATM this 
would lead to quite a few conflicts, since commits that were not mine were 
rewritten.

However, if we already have refs/remotes/blabla/master, we could DWIM the 
--rebase call to

	git rebase --onto FETCH_HEAD refs/remotes/blabla/master

Of course, this would mean that git-pull would need to source 
git-parse-remote again...

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Should "pull --rebase" try to be a little cleverer?
  2008-01-21 15:47 Should "pull --rebase" try to be a little cleverer? Johannes Schindelin
@ 2008-01-21 16:03 ` Nicolas Pitre
  2008-01-21 16:21   ` Johannes Schindelin
  2008-01-21 18:21 ` Junio C Hamano
  1 sibling, 1 reply; 8+ messages in thread
From: Nicolas Pitre @ 2008-01-21 16:03 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

On Mon, 21 Jan 2008, Johannes Schindelin wrote:

> Hi,
> 
> last night an idea hit me: if I "git pull --rebase blabla master", it 
> could be that "blabla" decided to rebase "master" already, and ATM this 
> would lead to quite a few conflicts, since commits that were not mine were 
> rewritten.

Indeed.

> However, if we already have refs/remotes/blabla/master, we could DWIM the 
> --rebase call to
> 
> 	git rebase --onto FETCH_HEAD refs/remotes/blabla/master

I was believing this was already the case.  Mind you, I never verified 
it.

I think the best is really to have the equivalent of:

	git fetch blabla/master
	git rebase --onto blabla/master blabla/master@{1} HEAD


Nicolas

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Should "pull --rebase" try to be a little cleverer?
  2008-01-21 16:03 ` Nicolas Pitre
@ 2008-01-21 16:21   ` Johannes Schindelin
  2008-01-21 16:42     ` Nicolas Pitre
  0 siblings, 1 reply; 8+ messages in thread
From: Johannes Schindelin @ 2008-01-21 16:21 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git

Hi,

On Mon, 21 Jan 2008, Nicolas Pitre wrote:

> On Mon, 21 Jan 2008, Johannes Schindelin wrote:
> 
> > last night an idea hit me: if I "git pull --rebase blabla master", it 
> > could be that "blabla" decided to rebase "master" already, and ATM 
> > this would lead to quite a few conflicts, since commits that were not 
> > mine were rewritten.
> 
> Indeed.
> 
> > However, if we already have refs/remotes/blabla/master, we could DWIM 
> > the --rebase call to
> > 
> > 	git rebase --onto FETCH_HEAD refs/remotes/blabla/master
> 
> I was believing this was already the case.  Mind you, I never verified 
> it.
> 
> I think the best is really to have the equivalent of:
> 
> 	git fetch blabla/master
> 	git rebase --onto blabla/master blabla/master@{1} HEAD

Not exactly... what would you do with this:

	git pull --rebase git://git.kernel.org/... master

Hm?

So I think that _only_ in the case that a remote ref is updated, _and_ 
that there is already one, can we do the DWIMery.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Should "pull --rebase" try to be a little cleverer?
  2008-01-21 16:21   ` Johannes Schindelin
@ 2008-01-21 16:42     ` Nicolas Pitre
  0 siblings, 0 replies; 8+ messages in thread
From: Nicolas Pitre @ 2008-01-21 16:42 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

On Mon, 21 Jan 2008, Johannes Schindelin wrote:

> Hi,
> 
> On Mon, 21 Jan 2008, Nicolas Pitre wrote:
> 
> > On Mon, 21 Jan 2008, Johannes Schindelin wrote:
> > 
> > > last night an idea hit me: if I "git pull --rebase blabla master", it 
> > > could be that "blabla" decided to rebase "master" already, and ATM 
> > > this would lead to quite a few conflicts, since commits that were not 
> > > mine were rewritten.
> > 
> > Indeed.
> > 
> > > However, if we already have refs/remotes/blabla/master, we could DWIM 
> > > the --rebase call to
> > > 
> > > 	git rebase --onto FETCH_HEAD refs/remotes/blabla/master
> > 
> > I was believing this was already the case.  Mind you, I never verified 
> > it.
> > 
> > I think the best is really to have the equivalent of:
> > 
> > 	git fetch blabla/master
> > 	git rebase --onto blabla/master blabla/master@{1} HEAD
> 
> Not exactly... what would you do with this:
> 
> 	git pull --rebase git://git.kernel.org/... master
> 
> Hm?
> 
> So I think that _only_ in the case that a remote ref is updated, _and_ 
> that there is already one, can we do the DWIMery.

Well, sure.  That's the case I care about.


Nicolas

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Should "pull --rebase" try to be a little cleverer?
  2008-01-21 15:47 Should "pull --rebase" try to be a little cleverer? Johannes Schindelin
  2008-01-21 16:03 ` Nicolas Pitre
@ 2008-01-21 18:21 ` Junio C Hamano
  2008-01-26 18:04   ` [PATCH] pull --rebase: be cleverer with rebased upstream branches Johannes Schindelin
  1 sibling, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2008-01-21 18:21 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> However, if we already have refs/remotes/blabla/master, we could DWIM the 
> --rebase call to
>
> 	git rebase --onto FETCH_HEAD refs/remotes/blabla/master

FWIW, I like it, and I think that is what users expect it to do.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] pull --rebase: be cleverer with rebased upstream branches
  2008-01-21 18:21 ` Junio C Hamano
@ 2008-01-26 18:04   ` Johannes Schindelin
  2008-01-26 19:34     ` Junio C Hamano
  0 siblings, 1 reply; 8+ messages in thread
From: Johannes Schindelin @ 2008-01-26 18:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


When the upstream branch is tracked, we can detect if that branch
was rebased since it was last fetched.  Teach git to use that
information to rebase from the old remote head onto the new remote head.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	On Mon, 21 Jan 2008, Junio C Hamano wrote:

	> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
	> 
	> > However, if we already have refs/remotes/blabla/master, we 
	> > could DWIM the --rebase call to
	> >
	> > 	git rebase --onto FETCH_HEAD refs/remotes/blabla/master
	> 
	> FWIW, I like it, and I think that is what users expect it to do.

	Sorry, took me quite some time.

	But I had a problem with the documentation: how am I supposed to 
	do the continuation of an indented paragraph, without using that 
	ugly "+" and unindenting the next paragraph?

 Documentation/git-pull.txt |    6 +++++-
 git-pull.sh                |   12 +++++++++++-
 t/t5520-pull.sh            |   17 +++++++++++++++++
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index f9f1e0d..4cc633a 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -35,7 +35,11 @@ include::urls-remotes.txt[]
 include::merge-strategies.txt[]
 
 \--rebase::
-	Instead of a merge, perform a rebase after fetching.
+	Instead of a merge, perform a rebase after fetching.  If
+	there is a remote ref for the upstream branch, and this branch
+	was rebased since last fetched, the rebase uses that information
+	to avoid rebasing non-local changes.
+
 	*NOTE:* This is a potentially _dangerous_ mode of operation.
 	It rewrites history, which does not bode well when you
 	published that history already.  Do *not* use this option
diff --git a/git-pull.sh b/git-pull.sh
index fa97b0f..46da0f4 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -106,6 +106,15 @@ error_on_no_merge_candidates () {
 	exit 1
 }
 
+test true = "$rebase" && {
+	. git-parse-remote &&
+	origin="$1"
+	test -z "$origin" && origin=$(get_default_remote)
+	reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
+		sed "s|refs/heads/\(.*\):|\1|")" &&
+	oldremoteref="$(git rev-parse --verify \
+		"refs/remotes/$origin/$reflist" 2>/dev/null)"
+}
 orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
 git-fetch --update-head-ok "$@" || exit 1
 
@@ -164,6 +173,7 @@ then
 fi
 
 merge_name=$(git fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
-test true = "$rebase" && exec git-rebase $merge_head
+test true = "$rebase" &&
+	exec git-rebase --onto $merge_head ${oldremoteref:-$merge_head}
 exec git-merge $no_summary $no_commit $squash $no_ff $strategy_args \
 	"$merge_name" HEAD $merge_head
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 52b3a0c..9484129 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -71,8 +71,25 @@ test_expect_success 'branch.to-rebase.rebase' '
 	git reset --hard before-rebase &&
 	git config branch.to-rebase.rebase 1 &&
 	git pull . copy &&
+	git config branch.to-rebase.rebase 0 &&
 	test $(git rev-parse HEAD^) = $(git rev-parse copy) &&
 	test new = $(git show HEAD:file2)
 '
 
+test_expect_success '--rebase with rebased upstream' '
+
+	git remote add -f me . &&
+	git checkout copy &&
+	git reset --hard HEAD^ &&
+	echo conflicting modification > file &&
+	git commit -m conflict file &&
+	git checkout to-rebase &&
+	echo file > file2 &&
+	git commit -m to-rebase file2 &&
+	git pull --rebase me copy &&
+	test "conflicting modification" = "$(cat file)" &&
+	test file = $(cat file2)
+
+'
+
 test_done
-- 
1.5.4.rc4.36.g6e122

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] pull --rebase: be cleverer with rebased upstream branches
  2008-01-26 18:04   ` [PATCH] pull --rebase: be cleverer with rebased upstream branches Johannes Schindelin
@ 2008-01-26 19:34     ` Junio C Hamano
  2008-01-26 19:49       ` Johannes Schindelin
  0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2008-01-26 19:34 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> When the upstream branch is tracked, we can detect if that branch
> was rebased since it was last fetched.  Teach git to use that
> information to rebase from the old remote head onto the new remote head.
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

This is certainly nicer than the original (which is not in
1.5.3, so even this late in the cycle it is "fixing up a new
feature we will be introducing in 1.5.4" category that I will
apply).  But I think a bit of caution and perhaps an
illustration or two in the doucmentation would help.

If you do "git fetch" from the origin since the last time you
ran "pull --rebase" for the remote, we will have the same
issue.  Suppose you have this history:

                   .---x---x---x
                  /
         .---A---B
        /
    ---0---o---o---A'--B'--C'--D'
                \
                 o---o---A''-B''-C''-D''-E''

Originally your upstream had 0---A---B; you built your 'x' on
top of it.  Then the upstream rebases and publishes history that
leads to D' (i.e. A and B are rewritten).  Later, the history is
further rewritten and E'' is the latest upstream tip.

If you haven't done "git fetch" since you started building on
top of B, refs/remotes/ will still say B and using B as base
(and E'' as onto) will give you the right rebase.  Earlier, we
did not use B in the rebase in any way, so your patch is
definitely an improvement.

However, if you have run "git fetch" (say, to peek what the
upstream has been up to), your refs/remote/ may say D'.  Using
that as the base and rebasing onto E'' is not quite optimal,
isn't it?

So it might make sense to make the logic to figure out B, given
your local history that leads from 0 to x's (and nothing else),
a bit cleverer than looking at the tracking branch.  We can look
at reflog for example.  "git log -g --pretty=oneline" may have
entries of this form:

    * branch: Created from B
    * rebase finished <branch> onto B

and the latest (i.e. younguest) entry is where the part of your
current history to be rebased (i.e. base commit) starts.  This
is much more reliable than looking at the tracking branch, whose
answer may or may not match B at all.

I do not mean this comment makes your approach invalid, though.
It is a start in the good direction.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] pull --rebase: be cleverer with rebased upstream branches
  2008-01-26 19:34     ` Junio C Hamano
@ 2008-01-26 19:49       ` Johannes Schindelin
  0 siblings, 0 replies; 8+ messages in thread
From: Johannes Schindelin @ 2008-01-26 19:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Hi,

On Sat, 26 Jan 2008, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > When the upstream branch is tracked, we can detect if that branch was 
> > rebased since it was last fetched.  Teach git to use that information 
> > to rebase from the old remote head onto the new remote head.
> 
> This is certainly nicer than the original (which is not in 1.5.3, so 
> even this late in the cycle it is "fixing up a new feature we will be 
> introducing in 1.5.4" category that I will apply).  But I think a bit of 
> caution and perhaps an illustration or two in the doucmentation would 
> help.

Well, I half expected it to be post-1.5.4.

> If you do "git fetch" from the origin since the last time you ran "pull 
> --rebase" for the remote, we will have the same issue.

Yes, that occurred to me, too.

> So it might make sense to make the logic to figure out B, given
> your local history that leads from 0 to x's (and nothing else),
> a bit cleverer than looking at the tracking branch.  We can look
> at reflog for example.  "git log -g --pretty=oneline" may have
> entries of this form:
> 
>     * branch: Created from B
>     * rebase finished <branch> onto B
> 
> and the latest (i.e. younguest) entry is where the part of your current 
> history to be rebased (i.e. base commit) starts.  This is much more 
> reliable than looking at the tracking branch, whose answer may or may 
> not match B at all.

I did not want to do that, because it is quite possible that the reflogs 
were disabled, or that the relevant reflogs were already expired.

However, I think that it might be a good approach to try reflogs first, 
and fallback to what I sent if there are no reflogs (or if it is detected 
that the reflog entry is not possibly the correct one, since what was 
rebased to is no longer an ancestor of the current branch).

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-01-26 19:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-21 15:47 Should "pull --rebase" try to be a little cleverer? Johannes Schindelin
2008-01-21 16:03 ` Nicolas Pitre
2008-01-21 16:21   ` Johannes Schindelin
2008-01-21 16:42     ` Nicolas Pitre
2008-01-21 18:21 ` Junio C Hamano
2008-01-26 18:04   ` [PATCH] pull --rebase: be cleverer with rebased upstream branches Johannes Schindelin
2008-01-26 19:34     ` Junio C Hamano
2008-01-26 19:49       ` Johannes Schindelin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).