From 1e0dacdbdb751caa5936b6d1510f5e8db4d1ed5f Mon Sep 17 00:00:00 2001 From: John Keeping Date: Wed, 16 Jul 2014 20:23:49 +0100 Subject: rebase: omit patch-identical commits with --fork-point When the `--fork-point` argument was added to `git rebase`, we changed the value of $upstream to be the fork point instead of the point from which we want to rebase. When $orig_head..$upstream is empty this does not change the behaviour, but when there are new changes in the upstream we are no longer checking if any of them are patch-identical with changes in $upstream..$orig_head. Fix this by introducing a new variable to hold the fork point and using this to restrict the range as an extra (negative) revision argument so that the set of desired revisions becomes (in fork-point mode): git rev-list --cherry-pick --right-only \ $upstream...$orig_head ^$fork_point This allows us to correctly handle the scenario where we have the following topology: C --- D --- E <- dev / B <- master@{1} / o --- B' --- C* --- D* <- master where: - B' is a fixed-up version of B that is not patch-identical with B; - C* and D* are patch-identical to C and D respectively and conflict textually if applied in the wrong order; - E depends textually on D. The correct result of `git rebase master dev` is that B is identified as the fork-point of dev and master, so that C, D, E are the commits that need to be replayed onto master; but C and D are patch-identical with C* and D* and so can be dropped, so that the end result is: o --- B' --- C* --- D* --- E <- dev If the fork-point is not identified, then picking B onto a branch containing B' results in a conflict and if the patch-identical commits are not correctly identified then picking C onto a branch containing D (or equivalently D*) results in a conflict. This change allows us to handle both of these cases, where previously we either identified the fork-point (with `--fork-point`) but not the patch-identical commits *or* (with `--no-fork-point`) identified the patch-identical commits but not the fact that master had been rewritten. Reported-by: Ted Felix Signed-off-by: John Keeping Signed-off-by: Junio C Hamano --- git-rebase--am.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'git-rebase--am.sh') diff --git a/git-rebase--am.sh b/git-rebase--am.sh index 902bf2d96..f92373233 100644 --- a/git-rebase--am.sh +++ b/git-rebase--am.sh @@ -45,14 +45,16 @@ then # itself well to recording empty patches. fortunately, cherry-pick # makes this easy git cherry-pick ${gpg_sign_opt:+"$gpg_sign_opt"} --allow-empty \ - --right-only "$revisions" + --right-only "$revisions" \ + ${restrict_revision+^$restrict_revision} ret=$? else rm -f "$GIT_DIR/rebased-patches" git format-patch -k --stdout --full-index --cherry-pick --right-only \ --src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \ - "$revisions" >"$GIT_DIR/rebased-patches" + "$revisions" ${restrict_revision+^$restrict_revision} \ + >"$GIT_DIR/rebased-patches" ret=$? if test 0 != $ret -- cgit v1.2.1