[PATCH 1/1] Add --first-parent support to interactive rebase.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux