Skip to content
  • John Keeping's avatar
    rebase: omit patch-identical commits with --fork-point · 1e0dacdb
    John Keeping authored and Junio C Hamano's avatar Junio C Hamano committed
    
    
    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: default avatarTed Felix <ted@tedfelix.com>
    Signed-off-by: default avatarJohn Keeping <john@keeping.me.uk>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    1e0dacdb