git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Björn Steinbrink <b.steinbrink@gmx.de>
Date
Oct 31, 2007, 02:21 UTC
Message-ID
<1193797309-1161-1-git-send-email-B.Steinbrink@gmx.de>

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@gmx.de>
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
Next: Johannes Schindelin
Message 1 of 18 in “Add --first-parent support to interactive rebase.”
  1. 1/1 Add --first-parent support to interactive rebase.Björn Steinbrink, Oct 31, 2007
  2. Johannes SchindelinOct 31, 2007
  3. Björn SteinbrinkOct 31, 2007
  4. Johannes SchindelinOct 31, 2007
  5. Wincent ColaiutaOct 31, 2007
  6. Junio C HamanoOct 31, 2007
  7. Björn SteinbrinkOct 31, 2007
  8. Dmitry PotapovOct 31, 2007
  9. Karl HasselströmOct 31, 2007
  10. Dmitry PotapovOct 31, 2007
  11. Jeff KingOct 31, 2007
  12. Björn SteinbrinkOct 31, 2007
  13. Junio C HamanoOct 31, 2007
  14. Jeff KingOct 31, 2007
  15. Junio C HamanoOct 31, 2007
  16. Jeff KingNov 1, 2007
  17. Junio C HamanoNov 1, 2007
  18. Jeff KingNov 1, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.