When the commit log message begins with "squash to ...", 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. Signed-off-by: Nanako Shiraishi <nanako3@xxxxxxxxxxx> --- Quoting Junio C Hamano <gitster@xxxxxxxxx>: I think you meant --amend, but it often happens to me that after preparing a three-patch series: [1/3] Clean up the surrounding code I will touch [2/3] Lay the groundwork [3/3] Implement a cool new feature I find that there are more clean-up that should have been done in [1/3]. The way "rebase -i" expects me to work is: $ edit ;# more clean-ups $ git commit -a -m 'squash to "clean up"' $ git rebase -i HEAD~5 which will give me pick 1/3 Clean up ... pick 2/3 Lay the groundwork pick 3/3 Implement pick 4/3 squash to "clean up" that I'll change to pick 1/3 Clean up ... squash 4/3 squash to "clean up" pick 2/3 Lay the groundwork pick 3/3 Implement and then I'll need to edit the commit message for the first two combined. How about this patch? It does not let you say 'squash to "clean up"' but other people who are more skillfull than me can enhance such details. git-rebase--interactive.sh | 31 +++++++++++++++++++++++++++++++ t/t3414-rebase-autosquash.sh | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 0 deletions(-) create mode 100755 t/t3414-rebase-autosquash.sh diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index f96d887..0832164 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -482,6 +482,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 squash to msg" 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]*\) squash to /\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 to $msg" + used="$used$squash " + break + ;; + esac + done <"$1.sq" + done <"$1" >"$1.rearranged" + + cat "$1.rearranged" >"$1" +} + while test $# != 0 do case "$1" in @@ -746,6 +776,7 @@ first and then run 'git rebase --continue' again." fi test -s "$TODO" || echo noop >> "$TODO" + 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..ddb0daf --- /dev/null +++ b/t/t3414-rebase-autosquash.sh @@ -0,0 +1,36 @@ +#!/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 "squash to first" + git tag final + test_tick + git rebase -i HEAD^^^ + git log --oneline >actual + test 3 = $(wc -l <actual) && + git diff --exit-code final +' + +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