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 <B.Steinbrink@xxxxxx> 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 - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html