From 68d5d03bc49a073be3b0e14b22d30d70e7ae686d Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Thu, 4 Nov 2010 15:36:32 -0700 Subject: [PATCH] rebase: teach --autosquash to match on sha1 in addition to message Support lines of the form "fixup! 7a235b" that specify an exact commit in addition to the normal "squash! Old commit message" form. Signed-off-by: Kevin Ballard Signed-off-by: Junio C Hamano --- git-rebase--interactive.sh | 40 +++++++++++++++++++++++++++++------- t/t3415-rebase-autosquash.sh | 31 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 379bbac5eb..c2383bfed5 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -675,9 +675,27 @@ get_saved_options () { # comes immediately after the former, and change "pick" to # "fixup"/"squash". rearrange_squash () { - sed -n -e 's/^pick \([0-9a-f]*\) \(squash\)! /\1 \2 /p' \ - -e 's/^pick \([0-9a-f]*\) \(fixup\)! /\1 \2 /p' \ - "$1" >"$1.sq" + # extract fixup!/squash! lines and resolve any referenced sha1's + while read -r pick sha1 message + do + case "$message" in + "squash! "*|"fixup! "*) + action="${message%%!*}" + rest="${message#*! }" + echo "$sha1 $action $rest" + # if it's a single word, try to resolve to a full sha1 and + # emit a second copy. This allows us to match on both message + # and on sha1 prefix + if test "${rest#* }" = "$rest"; then + fullsha="$(git rev-parse -q --verify "$rest" 2>/dev/null)" + if test -n "$fullsha"; then + # prefix the action to uniquely identify this line as + # intended for full sha1 match + echo "$sha1 +$action $fullsha" + fi + fi + esac + done >"$1.sq" <"$1" test -s "$1.sq" || return used= @@ -693,12 +711,20 @@ rearrange_squash () { case " $used" in *" $squash "*) continue ;; esac - case "$message" in - "$msg"*) + emit=0 + case "$action" in + +*) + action="${action#+}" + # full sha1 prefix test + case "$msg" in "$sha1"*) emit=1;; esac ;; + *) + # message prefix test + case "$message" in "$msg"*) emit=1;; esac ;; + esac + if test $emit = 1; then printf '%s\n' "$action $squash $action! $msg" used="$used$squash " - ;; - esac + fi done <"$1.sq" done >"$1.rearranged" <"$1" cat "$1.rearranged" >"$1" diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 712bbe86b0..ca16b70373 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -136,5 +136,36 @@ test_expect_success 'auto squash that matches a commit after the squash' ' test 1 = $(git cat-file commit HEAD | grep third | wc -l) && test 1 = $(git cat-file commit HEAD^ | grep third | wc -l) ' +test_expect_success 'auto squash that matches a sha1' ' + git reset --hard base && + echo 1 >file1 && + git add -u && + test_tick && + git commit -m "squash! $(git rev-parse --short HEAD^)" && + git tag final-shasquash && + test_tick && + git rebase --autosquash -i HEAD^^^ && + git log --oneline >actual && + test 3 = $(wc -l file1 && + git add -u && + test_tick && + git commit -m "squash! $(git rev-parse --short=11 HEAD^)" && + git tag final-longshasquash && + test_tick && + git rebase --autosquash -i HEAD^^^ && + git log --oneline >actual && + test 3 = $(wc -l