git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Jörg Sommer" <joerg@alea.gnuu.de>
To: git@vger.kernel.org
Cc: gitster@pobox.com, B.Steinbrink@gmx.de,
	"Jörg Sommer" <joerg@alea.gnuu.de>
Subject: [PATCH 4/4] git-rebase -i: New option to support rebase with merges
Date: Sun, 23 Mar 2008 22:42:42 +0100	[thread overview]
Message-ID: <1206308562-31489-4-git-send-email-joerg@alea.gnuu.de> (raw)
In-Reply-To: <1206308562-31489-3-git-send-email-joerg@alea.gnuu.de>

The option --preserve-merges does not allow to change the order of
commits or squash them. The new option --linear-history does support
this, but doing so it can only look at the commits reachable with through
the first parent of each merge.

Joining merge commits with other commits leads to problems, because git
merge fails with a dirty index (the case “COMMIT squash MERGE”) and
squashing a merge leads to the lost of the parents (case “MERGE squash
COMMIT”). Therefore, I've prohibited these cases.

Signed-off-by: Jörg Sommer <joerg@alea.gnuu.de>
---
 Documentation/git-rebase.txt  |    8 ++++
 git-rebase--interactive.sh    |   27 +++++++++++++++-
 t/t3404-rebase-interactive.sh |   72 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 106 insertions(+), 1 deletions(-)

I had no better idea for a name of this new option. Propositions are
welcome.

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e0412e0..354b6f0 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
 	[-s <strategy> | --strategy=<strategy>]
 	[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
+	[-l | --linear-history]
 	[--onto <newbase>] <upstream> [<branch>]
 'git-rebase' --continue | --skip | --abort
 
@@ -247,6 +248,13 @@ OPTIONS
 	Instead of ignoring merges, try to recreate them.  This option
 	only works in interactive mode.
 
+-l, \--linear-history::
+	Use only commits of the branch they are not merged in, i.e.
+	follow only the first parent of a merge. Merges are part of this
+	list and they will be redone. It's possible to move merges in the
+	history forward and backward, but they can't take part on a join
+	(squash). 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 94c6827..a2a61f8 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -26,9 +26,11 @@ REWRITTEN="$DOTEST"/rewritten
 PRESERVE_MERGES=
 STRATEGY=
 VERBOSE=
+LINEAR_HISTORY=
 test -d "$REWRITTEN" && PRESERVE_MERGES=t
 test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
 test -f "$DOTEST"/verbose && VERBOSE=t
+test -f "$DOTEST"/linear_history && LINEAR_HISTORY=t
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -150,7 +152,18 @@ pick_one () {
 		sha1=$(git rev-parse --short $sha1)
 		output warn Fast forward to $sha1
 	else
-		output git cherry-pick "$@"
+		if test t = "$LINEAR_HISTORY" &&
+			other_parents="$(parents_of_commit $sha1 | cut -s -d' ' -f2-)" &&
+			test -n "$other_parents"
+		then
+			if test a"$1" = a-n
+			then
+				merge_opt=--no-commit
+			fi
+			redo_merge $sha1 $no_commit $other_parents
+		else
+			output git cherry-pick "$@"
+		fi
 	fi
 }
 
@@ -288,6 +301,11 @@ do_next () {
 		has_action "$DONE" ||
 			die "Cannot 'squash' without a previous commit"
 
+		test t = "$LINEAR_HISTORY" &&
+			( test "$(parents_of_commit HEAD |wc -w)" -gt 1 ||
+				 test "$(parents_of_commit $sha1 |wc -w)" -gt 1) &&
+			die "Joining a merge with a commit is not supported"
+
 		mark_action_done
 		make_squash_message $sha1 > "$MSG"
 		case "$(peek_next_command)" in
@@ -459,6 +477,9 @@ do
 	-i|--interactive)
 		# yeah, we know
 		;;
+	-l|--linear-history)
+		LINEAR_HISTORY=t
+		;;
 	''|-h)
 		usage
 		;;
@@ -522,6 +543,10 @@ do
 					die "Could not init rewritten commits"
 			done
 			MERGES_OPTION=
+		elif test t = "$LINEAR_HISTORY"
+		then
+			: > "$DOTEST"/linear_history
+			MERGES_OPTION=--first-parent
 		else
 			MERGES_OPTION=--no-merges
 		fi
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 9cf873f..0476f6a 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -361,4 +361,76 @@ test_expect_success 'rebase with a file named HEAD in worktree' '
 
 '
 
+test_expect_success 'rebase linear history preserves merges' '
+	git tag linear-history-base to-be-preserved~2
+	git checkout -b linear-history linear-history-base &&
+	for i in 1 2 3
+	do
+		test $? -eq 0 &&
+		echo linear history test > lin-h-$i &&
+		git add lin-h-$i &&
+		test_tick &&
+	       	git commit -m "rebase linear history commit $i"
+	done
+	test_tick &&
+	git merge to-be-preserved &&
+	old_head=$(git rev-parse HEAD) &&
+	test_tick &&
+	EXPECT_COUNT=4 FAKE_LINES="2 4 edit 1 3" \
+		git rebase -v -i -l linear-history-base &&
+	EXPECT_COUNT=invalid git rebase --continue &&
+	test "$(git rev-list --parents -1 HEAD~2 | cut -d" " -f3-)" = \
+		"$(git rev-parse to-be-preserved)" &&
+	test "$(git show HEAD~2: | grep ^lin-h- | cut -c7- | tr -d \\012)" = 2 &&
+	test "$(git show HEAD~1: | grep ^lin-h- | cut -c7- | tr -d \\012)" = 12 &&
+	test "$(git cat-file commit HEAD | sed -n "/^tree/{p;q;}")" = \
+		"$(git cat-file commit $old_head | sed -n "/^tree/{p;q;}")"
+'
+
+test_expect_success 'rebase linear history is noop, if base = base' '
+	old_head=$(git rev-parse HEAD) &&
+	test_tick &&
+	EXPECT_COUNT=4 git rebase -v -i -l linear-history-base &&
+	test "$(git rev-parse HEAD)" = $old_head
+'
+
+test_expect_success 'ensure rebase linear history persits across edits' '
+	old_head=$(git rev-parse HEAD) &&
+	test_tick &&
+	EXPECT_COUNT=4 FAKE_LINES="edit 1 2 3 4" \
+		git rebase -v -i -l linear-history-base &&
+	EXPECT_COUNT=invalid git rebase --continue &&
+	test "$(git rev-parse HEAD)" = $old_head
+'
+
+test_str='test_tick &&
+	(
+		outp=$(test_must_fail git rebase -v -i -l HEAD~3 2>&1)
+		rc=$?
+		echo "$outp"
+        	echo "$outp" | grep "^Joining .* not supported\$" >/dev/null &&
+		return $rc
+	) &&
+	git rebase --abort'
+
+test_expect_success 'rebase linear with squashing a merge fails' "
+	export EXPECT_COUNT=3 FAKE_LINES='1 squash 2 3' &&
+	$test_str &&
+	FAKE_LINES='2 squash 1 3' &&
+	$test_str
+"
+
+test_expect_success 'rebase linear history does a fast forward' '
+	old_head=$(git rev-parse HEAD) &&
+	test_tick &&
+	EXPECT_COUNT=4 FAKE_LINES="2 3 4 1" \
+		git rebase -v -i -l linear-history-base &&
+	test "$(git rev-parse HEAD~3)" = "$(git rev-parse to-be-preserved)" &&
+	test "$(git show HEAD~2: | grep ^lin-h- | cut -c7- | tr -d \\012)" = 1 &&
+	test "$(git show HEAD~1: | grep ^lin-h- | cut -c7- | tr -d \\012)" = 13 &&
+	test -z "$(git rev-list --parents -1 HEAD~3 | cut -d" " -f3-)" &&
+	test "$(git cat-file commit HEAD | sed -n "/^tree/{p;q;}")" = \
+		"$(git cat-file commit $old_head | sed -n "/^tree/{p;q;}")"
+'
+
 test_done
-- 
1.5.4.4

  reply	other threads:[~2008-03-23 21:47 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-23 21:42 [PATCH 1/4] Move redo merge code in a function Jörg Sommer
2008-03-23 21:42 ` [PATCH 2/4] Rework redo_merge Jörg Sommer
2008-03-23 21:42   ` [PATCH 3/4] Add a function for get the parents of a commit Jörg Sommer
2008-03-23 21:42     ` Jörg Sommer [this message]
2008-03-23 22:41       ` [PATCH 4/4] git-rebase -i: New option to support rebase with merges Johannes Schindelin
2008-03-24 11:14         ` Jörg Sommer
2008-03-24 13:08           ` Johannes Schindelin
2008-03-24 23:40             ` Jörg Sommer
2008-03-24 18:35           ` Junio C Hamano
2008-03-24 23:30             ` Junio C Hamano
2008-03-25 10:13             ` Jörg Sommer
2008-03-26  8:02               ` Junio C Hamano
2008-04-09 23:58             ` Teach rebase interactive more commands to do better preserve merges Jörg Sommer
2008-04-09 23:58               ` [PATCH/RFC 01/10] Teach rebase interactive the mark command Jörg Sommer
2008-04-09 23:58                 ` [PATCH/RFC 02/10] Teach rebase interactive the reset command Jörg Sommer
2008-04-09 23:58                   ` [PATCH/RFC 03/10] Teach rebase interactive the merge command Jörg Sommer
2008-04-09 23:58                     ` [PATCH/RFC 04/10] Move redo merge code in a function Jörg Sommer
2008-04-09 23:58                       ` [PATCH/RFC 05/10] Rework redo_merge Jörg Sommer
2008-04-09 23:58                         ` [PATCH/RFC 06/10] Unify the lenght of $SHORT* and the commits in the TODO list Jörg Sommer
2008-04-09 23:58                           ` [PATCH/RFC 07/10] fake-editor: output TODO list if unchanged Jörg Sommer
2008-04-09 23:58                             ` [PATCH/RFC 08/10] Don't append default merge message to -m message Jörg Sommer
2008-04-09 23:58                               ` [PATCH/RFC 09/10] Select all lines with fake-editor Jörg Sommer
2008-04-09 23:58                                 ` [PATCH/RFC 10/10] Do rebase with preserve merges with advanced TODO list Jörg Sommer
2008-04-12  0:00                           ` [PATCH/RFC 06/10] Unify the lenght of $SHORT* and the commits in the " Junio C Hamano
2008-04-12  9:13                             ` Jörg Sommer
2008-04-13  6:20                               ` Junio C Hamano
2008-04-13 16:39                                 ` Jörg Sommer
2008-04-14  1:06                                 ` Tarmigan
2008-04-11 23:56                   ` [PATCH/RFC 02/10] Teach rebase interactive the reset command Junio C Hamano
2008-04-12  9:37                     ` Jörg Sommer
2008-04-10  9:33                 ` [PATCH/RFC 01/10] Teach rebase interactive the mark command Mike Ralphson
2008-04-12 10:17                   ` Jörg Sommer
2008-04-11 23:48                 ` Junio C Hamano
2008-04-12 10:11                   ` Jörg Sommer
2008-04-13  3:56                     ` Shawn O. Pearce
2008-04-13 16:50                       ` Jörg Sommer
2008-04-14  6:24                         ` Shawn O. Pearce
2008-04-14  6:54                           ` Junio C Hamano
2008-04-14 10:06                           ` Jörg Sommer
2008-04-14  0:20             ` [PATCH v2 01/13] fake-editor: output TODO list if unchanged Jörg Sommer
2008-04-14  0:20               ` [PATCH v2 02/13] Don't append default merge message to -m message Jörg Sommer
2008-04-14  0:20                 ` [PATCH v2 03/13] Move cleanup code into it's own function Jörg Sommer
2008-04-14  0:21                   ` [PATCH v2 04/13] Teach rebase interactive the mark command Jörg Sommer
2008-04-14  0:21                     ` [PATCH v2 05/13] Teach rebase interactive the reset command Jörg Sommer
2008-04-14  0:21                       ` [PATCH v2 06/13] Move redo merge code in a function Jörg Sommer
2008-04-14  0:21                         ` [PATCH v2 07/13] Teach rebase interactive the merge command Jörg Sommer
2008-04-14  0:21                           ` [PATCH v2 08/13] Unify the lenght of $SHORT* and the commits in the TODO list Jörg Sommer
2008-04-14  0:21                             ` [PATCH v2 09/13] Select all lines with fake-editor Jörg Sommer
2008-04-14  0:21                               ` [PATCH v2 10/13] Do rebase with preserve merges with advanced TODO list Jörg Sommer
2008-04-14  0:21                                 ` [PATCH v2 11/13] Add option --first-parent Jörg Sommer
2008-04-14  0:21                                   ` [PATCH v2 12/13] Teach rebase interactive the tag command Jörg Sommer
2008-04-14  0:21                                     ` [PATCH v2 13/13] Add option --preserve-tags Jörg Sommer
2008-04-22  5:32                     ` [PATCH v2 04/13] Teach rebase interactive the mark command Junio C Hamano
2008-04-22  8:13                       ` Junio C Hamano
2008-04-22  8:52                       ` Johannes Schindelin
2008-04-22  9:55                       ` Jörg Sommer
2008-04-22 10:31                         ` Johannes Schindelin
2008-04-22 16:56                           ` Junio C Hamano
2008-04-22 17:12                             ` Johannes Schindelin
2008-04-29  0:25                               ` Junio C Hamano
2008-04-29  0:39                                 ` Johannes Schindelin
2008-04-29  5:17                                   ` Junio C Hamano
2008-04-29  7:12                                     ` Johannes Sixt
2008-04-29 10:52                                       ` Johannes Schindelin
2008-04-29 21:16                                         ` Junio C Hamano
2008-04-29 21:25                                           ` Johannes Schindelin
2008-04-29 22:23                                             ` Junio C Hamano
2008-04-29 22:55                                               ` Johannes Schindelin
2008-04-29 23:06                                                 ` Junio C Hamano
2008-04-29 23:31                                                   ` Johannes Schindelin
2008-04-30  1:23                                                     ` Junio C Hamano
2008-04-30  6:25                                                       ` Johannes Sixt
2008-04-30  7:10                                                         ` Junio C Hamano
2008-04-30  8:47                                                       ` Johannes Schindelin
2008-04-30  9:19                                                         ` Junio C Hamano
2008-04-30 10:29                                                           ` Johannes Sixt
2008-04-30 11:56                                                           ` Johannes Schindelin
2008-05-01 19:04                                                             ` Junio C Hamano
2008-05-03 12:45                                                               ` Johannes Schindelin
2008-05-03 17:09                                                                 ` Junio C Hamano
2008-05-04  9:38                                                                   ` Johannes Schindelin
2008-05-04 12:52                                                                     ` Jörg Sommer
2008-04-30 13:06                                                         ` Dmitry Potapov
2008-05-01 12:59                                                           ` Johannes Schindelin
2008-04-22 18:04                         ` Junio C Hamano
2008-04-25  9:11                           ` Jörg Sommer
2008-04-25  9:44                             ` [PATCH v2.2] " Jörg Sommer
2008-04-27  6:13                               ` Junio C Hamano
2008-04-27  8:28                                 ` Jörg Sommer
2008-04-14 10:39                   ` [PATCH v2.1] " Jörg Sommer
2008-04-14 23:29                     ` Shawn O. Pearce
2008-04-20 23:44                       ` mark parsing in fast-import Jörg Sommer
2008-04-21  0:26                         ` Shawn O. Pearce
2008-04-21  8:41                           ` Jörg Sommer
2008-04-21 23:59                             ` Shawn O. Pearce
2008-04-22  9:39                               ` Jörg Sommer
2008-04-22 23:15                                 ` Shawn O. Pearce
2008-04-25  9:04                                   ` [PATCH v2] Make mark parsing much more restrictive Jörg Sommer
2008-04-20 16:52                 ` [PATCH v2 02/13] Don't append default merge message to -m message Junio C Hamano
2008-04-21  0:17                   ` Jörg Sommer
2008-04-22  5:27                     ` Junio C Hamano
2008-03-23 22:33     ` [PATCH 3/4] Add a function for get the parents of a commit Johannes Schindelin
2008-03-23 22:29   ` [PATCH 2/4] Rework redo_merge Johannes Schindelin
2008-03-23 22:26 ` [PATCH 1/4] Move redo merge code in a function Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1206308562-31489-4-git-send-email-joerg@alea.gnuu.de \
    --to=joerg@alea.gnuu.de \
    --cc=B.Steinbrink@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).