Re: [BUG] rebase no longer omits local commits

2014-07-07 Thread John Keeping
On Mon, Jul 07, 2014 at 10:56:23AM -0700, Junio C Hamano wrote:
> John Keeping  writes:
> 
> > Perhaps we shuld do something like this (which passes the test suite):
> >
> > -- >8 --
> > diff --git a/git-rebase.sh b/git-rebase.sh
> > index 06c810b..0c6c5d3 100755
> > --- a/git-rebase.sh
> > +++ b/git-rebase.sh
> > @@ -544,7 +544,8 @@ if test "$fork_point" = t
> >  then
> > new_upstream=$(git merge-base --fork-point "$upstream_name" \
> > "${switch_to:-HEAD}")
> > -   if test -n "$new_upstream"
> > +   if test -n "$new_upstream" &&
> > +  ! git merge-base --is-ancestor "$new_upstream" "$upstream_name"
> > then
> > upstream=$new_upstream
> > fi
> > -- 8< --
> >
> > Since the intent of `--fork-point` is to find the best starting point
> > for the "$upstream...$orig_head" range, if the fork point is behind the
> > new location of the upstream then should we leave the upstream as it
> > was?
> 
> Probably; but the check to avoid giving worse fork-point should be
> in the implementation of "merge-base --fork-point" itself, so that
> we do not have to do the above to both "rebase" and "pull --rebase",
> no?

I don't think so, since in that case we're not actually finding the fork
point as defined in the documentation, we're finding the upstream rebase
wants.

Having played with this a bit, I think we shouldn't be replacing the
upstream with the fork point but should instead add the fork point as an
additional negative ref:

$upstream...$orig_head ^$fork_point

Here's a script that creates a repository showing this:

-- >8 --
#!/bin/sh
git init rebase-test &&
cd rebase-test &&
echo one >file &&
git add file &&
git commit -m one &&
echo frist >file2 &&
git add file2 &&
git commit -m first &&
git branch --track dev &&
echo first >file2 &&
git commit -a --amend --no-edit &&
echo two >file &&
git commit -a -m two &&
echo three >file &&
git commit -a -m three &&
echo second >file2 &&
git commit -a -m second &&
git checkout dev &&
git cherry-pick -2 master &&
echo four >file &&
git commit -a -m four &&
printf '\nWithout fork point (old behaviour)\n' &&
git rev-list --oneline --cherry @{u}... &&
printf '\nFork point as upstream (current behaviour)\n' &&
git rev-list --oneline --cherry $(git merge-base --fork-point master HEAD)... &&
printf '\nWith fork point\n' &&
git rev-list --oneline --cherry @{u}... ^$(git merge-base --fork-point master 
HEAD)
-- 8< --

In this case the rebase should be clean since the only applicable patch
changes "three" to "four" in "file", but the current rebase code fails
both with `--fork-point` and with `--no-fork-point`.

With `--fork-point` we try to apply "two" and "three" which have already
been cherry-picked across (as Ted originally reported) and with
`--no-fork-point`, we try to apply "first" which conflicts because we
have the version prior to it being fixed up on master.

I hacked up git-rebase to test this and the change to use the fork point
as in the last line of the script above does indeed make the rebase go
through cleanly, but I have not yet looked at how to cleanly patch in
that behaviour.

I haven't tested git-pull, but it looks like it has always (since 2009)
behaved in the way `git rebase --fork-point` does now, failing to detect
cherry-picked commits that are now in the upstream.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] rebase no longer omits local commits

2014-07-07 Thread Junio C Hamano
John Keeping  writes:

> Perhaps we shuld do something like this (which passes the test suite):
>
> -- >8 --
> diff --git a/git-rebase.sh b/git-rebase.sh
> index 06c810b..0c6c5d3 100755
> --- a/git-rebase.sh
> +++ b/git-rebase.sh
> @@ -544,7 +544,8 @@ if test "$fork_point" = t
>  then
>   new_upstream=$(git merge-base --fork-point "$upstream_name" \
>   "${switch_to:-HEAD}")
> - if test -n "$new_upstream"
> + if test -n "$new_upstream" &&
> +! git merge-base --is-ancestor "$new_upstream" "$upstream_name"
>   then
>   upstream=$new_upstream
>   fi
> -- 8< --
>
> Since the intent of `--fork-point` is to find the best starting point
> for the "$upstream...$orig_head" range, if the fork point is behind the
> new location of the upstream then should we leave the upstream as it
> was?

Probably; but the check to avoid giving worse fork-point should be
in the implementation of "merge-base --fork-point" itself, so that
we do not have to do the above to both "rebase" and "pull --rebase",
no?

> I haven't thought through this completely, but it seems like we should
> be doing a check like the above, at least when we're in
> "$fork_point=auto" mode.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] rebase no longer omits local commits

2014-07-03 Thread John Keeping
On Thu, Jul 03, 2014 at 08:09:17PM +0100, John Keeping wrote:
> On Thu, Jul 03, 2014 at 11:14:26AM -0400, Ted Felix wrote:
> > Starting with git 1.9.0, rebase no longer omits local commits that 
> > appear in both the upstream and local branches.
> 
> It is the problem that bb3f458 fixes.  The change in behaviour is
> actually introduced by ad8261d (rebase: use reflog to find common base
> with upstream).
> 
> In your example, I think this is working as designed.  You can restore
> the previous behaviour either with `git rebase --no-fork-point` or with
> `git rebase @{u}`.
> 
> The change is designed to help users recover from an upstream rebase, as
> described in the "DISCUSSION ON FORK-POINT MODE" section of
> git-merge-base(1).

Having thought about this a bit more, I think the case you've identified
is an unexpected side effect of that commit.

Perhaps we shuld do something like this (which passes the test suite):

-- >8 --
diff --git a/git-rebase.sh b/git-rebase.sh
index 06c810b..0c6c5d3 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -544,7 +544,8 @@ if test "$fork_point" = t
 then
new_upstream=$(git merge-base --fork-point "$upstream_name" \
"${switch_to:-HEAD}")
-   if test -n "$new_upstream"
+   if test -n "$new_upstream" &&
+  ! git merge-base --is-ancestor "$new_upstream" "$upstream_name"
then
upstream=$new_upstream
fi
-- 8< --

Since the intent of `--fork-point` is to find the best starting point
for the "$upstream...$orig_head" range, if the fork point is behind the
new location of the upstream then should we leave the upstream as it
was?

I haven't thought through this completely, but it seems like we should
be doing a check like the above, at least when we're in
"$fork_point=auto" mode.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] rebase no longer omits local commits

2014-07-03 Thread John Keeping
On Thu, Jul 03, 2014 at 11:14:26AM -0400, Ted Felix wrote:
> Starting with git 1.9.0, rebase no longer omits local commits that 
> appear in both the upstream and local branches.
> 
> I've bisected this down to commit bb3f458: "rebase: fix fork-point with 
> zero arguments".  The attached script reproduces the problem.  Reverting 
> the aforementioned commit fixes the problem.
> 
> A failed run of this script will result in conflicts.  A successful run 
> against master with bb3f458 reverted ends as follows:
> 
>  From /tmp/rebase-issue/maint
> fe401cd..955af04  master -> origin/master
> fatal: Not a valid object name: ''
> First, rewinding head to replay your work on top of it...
> Applying: Third change
> 
> (I'm not sure if that "fatal: Not a valid object name: ''" is of any 
> concern.  It started appearing for me at some point during the bisect.)

It is the problem that bb3f458 fixes.  The change in behaviour is
actually introduced by ad8261d (rebase: use reflog to find common base
with upstream).

In your example, I think this is working as designed.  You can restore
the previous behaviour either with `git rebase --no-fork-point` or with
`git rebase @{u}`.

The change is designed to help users recover from an upstream rebase, as
described in the "DISCUSSION ON FORK-POINT MODE" section of
git-merge-base(1) and makes `git rebase` match the behaviour of
`git pull --rebase` so that:

git fetch &&
git rebase

really is equivalent to:

git pull --rebase
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html