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

[PATCH v2] rebase -i --autosquash: auto-squash commits

From
Nanako Shiraishi <nanako3@lavabit.com>
Date
Jun 18, 2009, 21:55 UTC
Message-ID
<20090619065534.6117@nanako3.lavabit.com>
In-Reply-To
<7vvdmu15j0.fsf@alter.siamese.dyndns.org>

Teach a new option, --autosquash, to the interactive rebase. When the commit log message begins with "!fixup ...", and there is a commit whose title begins with the same ..., automatically modify the todo list of rebase -i so that the commit marked for squashing come right after the commit to be modified, and change the action of the moved commit from pick to squash.

This will help the use case outlined in
    From: Junio C Hamano <gitster@pobox.com>
    Date: Wed, 17 Jun 2009 09:33:19 -0700
    Subject: Re: git rebase --interactive squash/squish/fold/rollup
    Message-ID: <7vvdmurfao.fsf@alter.siamese.dyndns.org>
and further explained in
    From: Junio C Hamano <gitster@pobox.com>
    Date: Thu, 18 Jun 2009 00:54:47 -0700
    Subject: Re: [PATCH] rebase -i: auto-squash commits
    Message-ID: <7vws7ayo1k.fsf@alter.siamese.dyndns.org>
Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
---
Changes from my yesterday's patch are as follows.
 * The feature is disabled by default; the user needs to explicitly ask for it with --autosquash option.
 * Squashing more than one commits to the same commit should work.
 * The commit message must begin with a more magic string "!fixup" instead of "squash to".
 * Commands in the test script are joined with &&.
 * The test examines the content of the file to verify that the commit was correctly squashed.
 * Add documentation.
 Documentation/git-rebase.txt |    9 +++++++++
 git-rebase--interactive.sh   |   35 +++++++++++++++++++++++++++++++++++
 t/t3414-rebase-autosquash.sh |   37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 0 deletions(-)
 create mode 100755 t/t3414-rebase-autosquash.sh
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 26f3b7b..0c2f99e 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -293,6 +293,15 @@ OPTIONS
 	root commits will be rewritten to have <newbase> as parent
 	instead.
 
+--autosquash::
+	When the commit log message begins with "!fixup ...", and there
+	is a commit whose title begins with the same ..., automatically
+	modify the todo list of rebase -i so that the commit marked for
+	squashing come right after the commit to be modified, and change
+	the action of the moved commit from pick to squash.
++
+This option is only valid when '--interactive' option is used.
+
 include::merge-strategies.txt[]
 
 NOTES
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index f96d887..6e223d5 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -28,6 +28,7 @@ abort              abort rebasing process and restore original branch
 skip               skip current patch and continue rebasing process
 no-verify          override pre-rebase hook from stopping the operation
 root               rebase all reachable commmits up to the root(s)
+autosquash         automatically squash commits that begin with !fixup
 "
 
 . git-sh-setup
@@ -46,6 +47,7 @@ ONTO=
 VERBOSE=
 OK_TO_SKIP_PRE_REBASE=
 REBASE_ROOT=
+AUTOSQUASH=
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -482,6 +484,35 @@ get_saved_options () {
 	test -f "$DOTEST"/rebase-root && REBASE_ROOT=t
 }
 
+# Rearrange the todo list that has both "pick sha1 msg" and
+# "pick sha1 !fixup msg" appears in it so that the latter
+# comes immediately after the former, and change "pick" to
+# "squash".
+rearrange_squash () {
+	sed -n -e 's/^pick \([0-9a-f]*\) !fixup /\1 /p' "$1" >"$1.sq"
+	test -s "$1.sq" || return
+
+	used=
+	while read pick sha1 message
+	do
+		case " $used" in
+		*" $sha1 "*) continue ;;
+		esac
+		echo "$pick $sha1 $message"
+		while read squash msg
+		do
+			case "$message" in
+			"$msg"*)
+				echo "squash $squash !fixup $msg"
+				used="$used$squash "
+				;;
+			esac
+		done <"$1.sq"
+	done <"$1" >"$1.rearranged"
+
+	cat "$1.rearranged" >"$1"
+}
+
 while test $# != 0
 do
 	case "$1" in
@@ -587,6 +618,9 @@ first and then run 'git rebase --continue' again."
 	--root)
 		REBASE_ROOT=t
 		;;
+	--autosquash)
+		AUTOSQUASH=t
+		;;
 	--onto)
 		shift
 		ONTO=$(git rev-parse --verify "$1") ||
@@ -746,6 +780,7 @@ first and then run 'git rebase --continue' again."
 		fi
 
 		test -s "$TODO" || echo noop >> "$TODO"
+		test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
 		cat >> "$TODO" << EOF
 
 # Rebase $SHORTREVISIONS onto $SHORTONTO
diff --git a/t/t3414-rebase-autosquash.sh b/t/t3414-rebase-autosquash.sh
new file mode 100755
index 0000000..161cab4
--- /dev/null
+++ b/t/t3414-rebase-autosquash.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='auto squash'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo 0 > file0 &&
+	git add . &&
+	test_tick &&
+	git commit -m "initial commit" &&
+	echo 0 > file1 &&
+	echo 2 > file2 &&
+	git add . &&
+	test_tick &&
+	git commit -m "first commit" &&
+	echo 3 > file3 &&
+	git add . &&
+	test_tick &&
+	git commit -m "second commit"
+'
+
+test_expect_success 'auto squash' '
+	echo 1 > file1 &&
+	git add -u &&
+	test_tick &&
+	git commit -m "!fixup first"
+	git tag final &&
+	test_tick &&
+	git rebase --autosquash -i HEAD^^^ &&
+	git log --oneline >actual &&
+	test 3 = $(wc -l <actual) &&
+	git diff --exit-code final &&
+	test 1 = "$(git cat-file blob HEAD^:file1)"
+'
+
+test_done
-- 
1.6.2.GIT

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
Previous: Junio C HamanoNext: Alex Riesen
Message 35 of 40 in “git rebase --interactive squash/squish/fold/rollup”
  1. MintyJun 17, 2009
  2. John TapsellJun 17, 2009
  3. MintyJun 17, 2009
  4. Junio C HamanoJun 17, 2009
  5. John TapsellJun 17, 2009
  6. Paolo BonziniJun 17, 2009
  7. John KoleszarJun 17, 2009
  8. John TapsellJun 17, 2009
  9. Clemens BuchacherJun 17, 2009
  10. MintyJun 18, 2009
  11. rebase -i: auto-squash commitsNanako Shiraishi, Jun 17, 2009
  12. Johannes SchindelinJun 17, 2009
  13. Re: rebase -i: auto-squash commitsNicolas Sebrecht, Jun 18, 2009
  14. Junio C HamanoJun 18, 2009
  15. Johannes SchindelinJun 18, 2009
  16. Jakub NarebskiJun 18, 2009
  17. Junio C HamanoJun 18, 2009
  18. Johannes SchindelinJun 18, 2009
  19. Teemu LikonenJun 18, 2009
  20. Johannes SchindelinJun 18, 2009
  21. Teemu LikonenJun 18, 2009
  22. Johannes SchindelinJun 18, 2009
  23. Jakub NarebskiJun 18, 2009
  24. John KoleszarJun 18, 2009
  25. Junio C HamanoJun 18, 2009
  26. Johannes SchindelinJun 18, 2009
  27. Michael J GruberJun 18, 2009
  28. Miles BaderJun 19, 2009
  29. Re: rebase -i: auto-squash commitsNicolas Sebrecht, Jun 18, 2009
  30. Matthieu MoyJun 18, 2009
  31. Johannes SchindelinJun 18, 2009
  32. Matthieu MoyJun 18, 2009
  33. Re: rebase -i: auto-squash commitsNicolas Sebrecht, Jun 18, 2009
  34. Junio C HamanoJun 18, 2009
  35. rebase -i --autosquash: auto-squash commitsNanako Shiraishi, Jun 18, 2009
  36. Alex RiesenJun 18, 2009
  37. Wincent ColaiutaJun 19, 2009
  38. Nanako ShiraishiJun 20, 2009
  39. Michael HaggertyJun 18, 2009
  40. Junio C HamanoJun 18, 2009

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.