Skip to content

Commit 68d5d03

Browse files
lilyballgitster
authored andcommitted
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 <kevin@sb.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent d3d7a42 commit 68d5d03

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

git-rebase--interactive.sh

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -675,9 +675,27 @@ get_saved_options () {
675675
# comes immediately after the former, and change "pick" to
676676
# "fixup"/"squash".
677677
rearrange_squash () {
678-
sed -n -e 's/^pick \([0-9a-f]*\) \(squash\)! /\1 \2 /p' \
679-
-e 's/^pick \([0-9a-f]*\) \(fixup\)! /\1 \2 /p' \
680-
"$1" >"$1.sq"
678+
# extract fixup!/squash! lines and resolve any referenced sha1's
679+
while read -r pick sha1 message
680+
do
681+
case "$message" in
682+
"squash! "*|"fixup! "*)
683+
action="${message%%!*}"
684+
rest="${message#*! }"
685+
echo "$sha1 $action $rest"
686+
# if it's a single word, try to resolve to a full sha1 and
687+
# emit a second copy. This allows us to match on both message
688+
# and on sha1 prefix
689+
if test "${rest#* }" = "$rest"; then
690+
fullsha="$(git rev-parse -q --verify "$rest" 2>/dev/null)"
691+
if test -n "$fullsha"; then
692+
# prefix the action to uniquely identify this line as
693+
# intended for full sha1 match
694+
echo "$sha1 +$action $fullsha"
695+
fi
696+
fi
697+
esac
698+
done >"$1.sq" <"$1"
681699
test -s "$1.sq" || return
682700

683701
used=
@@ -693,12 +711,20 @@ rearrange_squash () {
693711
case " $used" in
694712
*" $squash "*) continue ;;
695713
esac
696-
case "$message" in
697-
"$msg"*)
714+
emit=0
715+
case "$action" in
716+
+*)
717+
action="${action#+}"
718+
# full sha1 prefix test
719+
case "$msg" in "$sha1"*) emit=1;; esac ;;
720+
*)
721+
# message prefix test
722+
case "$message" in "$msg"*) emit=1;; esac ;;
723+
esac
724+
if test $emit = 1; then
698725
printf '%s\n' "$action $squash $action! $msg"
699726
used="$used$squash "
700-
;;
701-
esac
727+
fi
702728
done <"$1.sq"
703729
done >"$1.rearranged" <"$1"
704730
cat "$1.rearranged" >"$1"

t/t3415-rebase-autosquash.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,36 @@ test_expect_success 'auto squash that matches a commit after the squash' '
136136
test 1 = $(git cat-file commit HEAD | grep third | wc -l) &&
137137
test 1 = $(git cat-file commit HEAD^ | grep third | wc -l)
138138
'
139+
test_expect_success 'auto squash that matches a sha1' '
140+
git reset --hard base &&
141+
echo 1 >file1 &&
142+
git add -u &&
143+
test_tick &&
144+
git commit -m "squash! $(git rev-parse --short HEAD^)" &&
145+
git tag final-shasquash &&
146+
test_tick &&
147+
git rebase --autosquash -i HEAD^^^ &&
148+
git log --oneline >actual &&
149+
test 3 = $(wc -l <actual) &&
150+
git diff --exit-code final-shasquash &&
151+
test 1 = "$(git cat-file blob HEAD^:file1)" &&
152+
test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
153+
'
154+
155+
test_expect_success 'auto squash that matches longer sha1' '
156+
git reset --hard base &&
157+
echo 1 >file1 &&
158+
git add -u &&
159+
test_tick &&
160+
git commit -m "squash! $(git rev-parse --short=11 HEAD^)" &&
161+
git tag final-longshasquash &&
162+
test_tick &&
163+
git rebase --autosquash -i HEAD^^^ &&
164+
git log --oneline >actual &&
165+
test 3 = $(wc -l <actual) &&
166+
git diff --exit-code final-longshasquash &&
167+
test 1 = "$(git cat-file blob HEAD^:file1)" &&
168+
test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
169+
'
139170

140171
test_done

0 commit comments

Comments
 (0)