[PATCH 1/1] Add --first-parent support to interactive rebase.
From: Björn Steinbrink <hidden>
Date: 2016-06-15 22:43:45
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
By default, rebase will take all commits from the branch that is to be
rebased which are missing in upstream. The new --first-parent option
allows to just follow the first parent and thus completely ignore
merges.
Additionally, when used together with --preserve-merges (which is the
more useful use-case) it will no longer rebase the commits from the
merged-in branches, but instead redo the merge with the original
parents.
That means that:
---H------I topicB
/ \ \
| D---E---F--G topicA
|/
A---B---C master
does no longer become:
-H'--------I'
/ \ \
D'---E'---F'---G' topicA
/
A---B---C master
\
H---I topicB
but instead:
A---B---C master
\ \
\ D'---E'---F'---G' topicA
\ / /
---------H---------I topicB
Signed-off-by: Björn Steinbrink <redacted>
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e4326d3..0b5f4b6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt@@ -10,7 +10,7 @@ SYNOPSIS [verse] 'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge] [-C<n>] [ --whitespace=<option>] [-p | --preserve-merges] - [--onto <newbase>] <upstream> [<branch>] + [--first-parent] [--onto <newbase>] <upstream> [<branch>] 'git-rebase' --continue | --skip | --abort DESCRIPTION
@@ -166,6 +166,52 @@ This is useful if F and G were flawed in some way, or should not be part of topicA. Note that the argument to --onto and the <upstream> parameter can be any valid commit-ish. +If you have a branch that contains merges which you want to preserve, you +can use the --preserve-merges option. By default, this will duplicate all +merged commits on top of <upstream> (or <newbase>) and try to redo the +merges using the new commits. Given this situation: + +------------ + ---H------I topicB + / \ \ + | D---E---F--G topicA + |/ + A---B---C master +------------ + +then the command + + git rebase -i --preserve-merges master topicA + +would result in + +------------ + -H'--------I' + / \ \ + D'---E'---F'---G' topicA + / + A---B---C master + \ + H---I topicB +------------ + +If you pass --first-parent in addition to --preserve-merges, the commits +from the merged-in branches won't be duplicated. + +So the command + + git rebase -i --preserve-merges --first-parent master topicA + +would instead result in + +------------ + A---B---C master + \ \ + \ D'---E'---F'---G' topicA + \ / / + ---------H---------I topicB +------------ + In case of conflict, git-rebase will stop at the first problematic commit and leave conflict markers in the tree. You can use git diff to locate the markers (<<<<<<) and make edits to resolve the conflict. For each
@@ -246,6 +292,13 @@ OPTIONS Instead of ignoring merges, try to recreate them. This option only works in interactive mode. +\--first-parent:: + Only follow the first parent commits in merge commits when looking + for the commits that are to be rebased. This is most useful with -p + as it will cause rebase to recreate the merges against the original + branches instead of rebasing those branches as well. This option + only works in interactive mode. + include::merge-strategies.txt[] NOTES
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index e63e1c9..38b070e 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh@@ -22,6 +22,7 @@ DONE="$DOTEST"/done MSG="$DOTEST"/message SQUASH_MSG="$DOTEST"/message-squash REWRITTEN="$DOTEST"/rewritten +FIRST_PARENT= PRESERVE_MERGES= STRATEGY= VERBOSE=
@@ -143,14 +144,20 @@ pick_one_preserving_merges () { preserve=f new_p=$(cat "$REWRITTEN"/$p) test $p != $new_p && fast_forward=f - case "$new_parents" in - *$new_p*) - ;; # do nothing; that parent is already there - *) - new_parents="$new_parents $new_p" - ;; - esac + elif test t = "$FIRST_PARENT" + then + new_p=$p + else + continue fi + + case "$new_parents" in + *$new_p*) + ;; # do nothing; that parent is already there + *) + new_parents="$new_parents $new_p" + ;; + esac done case $fast_forward in t)
@@ -412,6 +419,9 @@ do -p|--preserve-merges) PRESERVE_MERGES=t ;; + --first-parent) + FIRST_PARENT=t + ;; -i|--interactive) # yeah, we know ;;
@@ -481,6 +491,10 @@ do else MERGES_OPTION=--no-merges fi + if test t = "$FIRST_PARENT" + then + MERGES_OPTION="--first-parent $MERGES_OPTION" + fi SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM) SHORTHEAD=$(git rev-parse --short $HEAD)
--
1.5.3.4.456.g072a