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>
Kevin Ballard committed
Nov 4, 2010 at 15:36 UTC
68d5d03bc49a073be3b0e14b22d30d70e7ae686d
2 files changed
+64
-7
git-rebase--interactive.sh
+33
-7
@@ -675,9 +675,27 @@ get_saved_options () {
675
# comes immediately after the former, and change "pick" to
676
# "fixup"/"squash".
677
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"
699
test -s "$1.sq" || return
700
701
used=
@@ -693,12 +711,20 @@ rearrange_squash () {
711
case " $used" in
712
*" $squash "*) continue ;;
713
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
725
printf '%s\n' "$action $squash $action! $msg"
726
used="$used$squash "
700
- ;;
701
- esac
727
+ fi
728
done <"$1.sq"
729
done >"$1.rearranged" <"$1"
730
cat "$1.rearranged" >"$1"
t/t3415-rebase-autosquash.sh
+31
@@ -136,5 +136,36 @@ test_expect_success 'auto squash that matches a commit after the squash' '
136
test 1 = $(git cat-file commit HEAD | grep third | wc -l) &&
137
test 1 = $(git cat-file commit HEAD^ | grep third | wc -l)
138
'
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
+'
170
171
test_done