Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 22c5b13

Browse files
Andrew Pimlottgitster
authored andcommitted
rebase -i: handle fixup! fixup! in --autosquash
In rebase -i --autosquash, ignore all "fixup! " or "squash! " after the first. This supports the case when a git commit --fixup/--squash referred to an earlier fixup/squash instead of the original commit (whether intentionally, as when the user expressly meant to note that the commit fixes an earlier fixup; or inadvertently, as when the user meant to refer to the original commit with :/msg; or out of laziness, as when the user could remember how to refer to the fixup but not the original). In the todo list, the full commit message is preserved, in case it provides useful cues to the user. A test helper set_cat_todo_editor is introduced to check this. Helped-by: Thomas Rast <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Andrew Pimlott <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9832cb9 commit 22c5b13

File tree

4 files changed

+94
-6
lines changed

4 files changed

+94
-6
lines changed

Documentation/git-rebase.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,9 @@ squash/fixup series.
389389
the same ..., automatically modify the todo list of rebase -i
390390
so that the commit marked for squashing comes right after the
391391
commit to be modified, and change the action of the moved
392-
commit from `pick` to `squash` (or `fixup`).
392+
commit from `pick` to `squash` (or `fixup`). Ignores subsequent
393+
"fixup! " or "squash! " after the first, in case you referred to an
394+
earlier fixup/squash with `git commit --fixup/--squash`.
393395
+
394396
This option is only valid when the '--interactive' option is used.
395397
+

git-rebase--interactive.sh

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -689,8 +689,22 @@ rearrange_squash () {
689689
case "$message" in
690690
"squash! "*|"fixup! "*)
691691
action="${message%%!*}"
692-
rest="${message#*! }"
693-
echo "$sha1 $action $rest"
692+
rest=$message
693+
prefix=
694+
# skip all squash! or fixup! (but save for later)
695+
while :
696+
do
697+
case "$rest" in
698+
"squash! "*|"fixup! "*)
699+
prefix="$prefix${rest%%!*},"
700+
rest="${rest#*! }"
701+
;;
702+
*)
703+
break
704+
;;
705+
esac
706+
done
707+
echo "$sha1 $action $prefix $rest"
694708
# if it's a single word, try to resolve to a full sha1 and
695709
# emit a second copy. This allows us to match on both message
696710
# and on sha1 prefix
@@ -699,7 +713,7 @@ rearrange_squash () {
699713
if test -n "$fullsha"; then
700714
# prefix the action to uniquely identify this line as
701715
# intended for full sha1 match
702-
echo "$sha1 +$action $fullsha"
716+
echo "$sha1 +$action $prefix $fullsha"
703717
fi
704718
fi
705719
esac
@@ -714,7 +728,7 @@ rearrange_squash () {
714728
esac
715729
printf '%s\n' "$pick $sha1 $message"
716730
used="$used$sha1 "
717-
while read -r squash action msg_content
731+
while read -r squash action msg_prefix msg_content
718732
do
719733
case " $used" in
720734
*" $squash "*) continue ;;
@@ -730,7 +744,8 @@ rearrange_squash () {
730744
case "$message" in "$msg_content"*) emit=1;; esac ;;
731745
esac
732746
if test $emit = 1; then
733-
printf '%s\n' "$action $squash $action! $msg_content"
747+
real_prefix=$(echo "$msg_prefix" | sed "s/,/! /g")
748+
printf '%s\n' "$action $squash ${real_prefix}$msg_content"
734749
used="$used$squash "
735750
fi
736751
done <"$1.sq"

t/lib-rebase.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ EOF
6666
chmod a+x fake-editor.sh
6767
}
6868

69+
# After set_cat_todo_editor, rebase -i will write the todo list (ignoring
70+
# blank lines and comments) to stdout, and exit failure (so you should run
71+
# it with test_must_fail). This can be used to verify the expected user
72+
# experience, for todo list changes that do not affect the outcome of
73+
# rebase; or as an extra check in addition to checking the outcome.
74+
75+
set_cat_todo_editor () {
76+
write_script fake-editor.sh <<-\EOF
77+
grep "^[^#]" "$1"
78+
exit 1
79+
EOF
80+
test_set_editor "$(pwd)/fake-editor.sh"
81+
}
82+
6983
# checks that the revisions in "$2" represent a linear range with the
7084
# subjects in "$1"
7185
test_linear_range () {

t/t3415-rebase-autosquash.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ test_description='auto squash'
44

55
. ./test-lib.sh
66

7+
. "$TEST_DIRECTORY"/lib-rebase.sh
8+
79
test_expect_success setup '
810
echo 0 >file0 &&
911
git add . &&
@@ -193,4 +195,59 @@ test_expect_success 'use commit --squash' '
193195
test_auto_commit_flags squash 2
194196
'
195197

198+
test_auto_fixup_fixup () {
199+
git reset --hard base &&
200+
echo 1 >file1 &&
201+
git add -u &&
202+
test_tick &&
203+
git commit -m "$1! first" &&
204+
echo 2 >file1 &&
205+
git add -u &&
206+
test_tick &&
207+
git commit -m "$1! $2! first" &&
208+
git tag "final-$1-$2" &&
209+
test_tick &&
210+
(
211+
set_cat_todo_editor &&
212+
test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
213+
cat >expected <<-EOF &&
214+
pick $(git rev-parse --short HEAD^^^) first commit
215+
$1 $(git rev-parse --short HEAD^) $1! first
216+
$1 $(git rev-parse --short HEAD) $1! $2! first
217+
pick $(git rev-parse --short HEAD^^) second commit
218+
EOF
219+
test_cmp expected actual
220+
) &&
221+
git rebase --autosquash -i HEAD^^^^ &&
222+
git log --oneline >actual &&
223+
test_line_count = 3 actual
224+
git diff --exit-code "final-$1-$2" &&
225+
test 2 = "$(git cat-file blob HEAD^:file1)" &&
226+
if test "$1" = "fixup"
227+
then
228+
test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
229+
elif test "$1" = "squash"
230+
then
231+
test 3 = $(git cat-file commit HEAD^ | grep first | wc -l)
232+
else
233+
false
234+
fi
235+
}
236+
237+
test_expect_success 'fixup! fixup!' '
238+
test_auto_fixup_fixup fixup fixup
239+
'
240+
241+
test_expect_success 'fixup! squash!' '
242+
test_auto_fixup_fixup fixup squash
243+
'
244+
245+
test_expect_success 'squash! squash!' '
246+
test_auto_fixup_fixup squash squash
247+
'
248+
249+
test_expect_success 'squash! fixup!' '
250+
test_auto_fixup_fixup squash fixup
251+
'
252+
196253
test_done

0 commit comments

Comments
 (0)