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@xxxxxxxxx> Date: Wed, 17 Jun 2009 09:33:19 -0700 Subject: Re: git rebase --interactive squash/squish/fold/rollup Message-ID: <7vvdmurfao.fsf@xxxxxxxxxxxxxxxxxxxxxxxx> and further explained in From: Junio C Hamano <gitster@xxxxxxxxx> Date: Thu, 18 Jun 2009 00:54:47 -0700 Subject: Re: [PATCH] rebase -i: auto-squash commits Message-ID: <7vws7ayo1k.fsf@xxxxxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Nanako Shiraishi <nanako3@xxxxxxxxxxx> --- 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/ -- 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