@matheusbsbs / matheus-bagliano / commits / f59baa502f
Fork 0

rebase -i --autosquash: auto-squash commits

Teach a new option, --autosquash, to the interactive rebase. When the commit log message begins with "!fixup ...", 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@lavabit.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nanako Shiraishi committed Dec 8, 2009 at 12:13 UTC f59baa502f49c3f1579a82bc37d2bb3ce9e7b5da
3 files changed +120
Documentation/git-rebase.txt
+10
@@ -308,6 +308,16 @@ which makes little sense.
308 root commits will be rewritten to have <newbase> as parent
309 instead.
310
311 +--autosquash::
312 + When the commit log message begins with "squash! ..." (or
313 + "fixup! ..."), and there is a commit whose title begins with
314 + the same ..., automatically modify the todo list of rebase -i
315 + so that the commit marked for quashing come right after the
316 + commit to be modified, and change the action of the moved
317 + commit from `pick` to `squash` (or `fixup`).
318 ++
319 +This option is only valid when '--interactive' option is used.
320 +
321 include::merge-strategies.txt[]
322
323 NOTES
git-rebase--interactive.sh
+37
@@ -28,6 +28,7 @@ abort abort rebasing process and restore original branch
28 skip skip current patch and continue rebasing process
29 no-verify override pre-rebase hook from stopping the operation
30 root rebase all reachable commmits up to the root(s)
31 +autosquash move commits that begin with squash!/fixup! under -i
32 "
33
34 . git-sh-setup
@@ -46,6 +47,7 @@ ONTO=
47 VERBOSE=
48 OK_TO_SKIP_PRE_REBASE=
49 REBASE_ROOT=
50 +AUTOSQUASH=
51
52 GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
53 mark the corrected paths with 'git add <paths>', and
@@ -519,6 +521,37 @@ get_saved_options () {
521 test -f "$DOTEST"/rebase-root && REBASE_ROOT=t
522 }
523
524 +# Rearrange the todo list that has both "pick sha1 msg" and
525 +# "pick sha1 fixup!/squash! msg" appears in it so that the latter
526 +# comes immediately after the former, and change "pick" to
527 +# "fixup"/"squash".
528 +rearrange_squash () {
529 + sed -n -e 's/^pick \([0-9a-f]*\) \(squash\)! /\1 \2 /p' \
530 + -e 's/^pick \([0-9a-f]*\) \(fixup\)! /\1 \2 /p' \
531 + "$1" >"$1.sq"
532 + test -s "$1.sq" || return
533 +
534 + used=
535 + while read pick sha1 message
536 + do
537 + case " $used" in
538 + *" $sha1 "*) continue ;;
539 + esac
540 + echo "$pick $sha1 $message"
541 + while read squash action msg
542 + do
543 + case "$message" in
544 + "$msg"*)
545 + echo "$action $squash $action! $msg"
546 + used="$used$squash "
547 + ;;
548 + esac
549 + done <"$1.sq"
550 + done >"$1.rearranged" <"$1"
551 + cat "$1.rearranged" >"$1"
552 + rm -f "$1.sq" "$1.rearranged"
553 +}
554 +
555 while test $# != 0
556 do
557 case "$1" in
@@ -624,6 +657,9 @@ first and then run 'git rebase --continue' again."
657 --root)
658 REBASE_ROOT=t
659 ;;
660 + --autosquash)
661 + AUTOSQUASH=t
662 + ;;
663 --onto)
664 shift
665 ONTO=$(git rev-parse --verify "$1") ||
@@ -783,6 +819,7 @@ first and then run 'git rebase --continue' again."
819 fi
820
821 test -s "$TODO" || echo noop >> "$TODO"
822 + test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
823 cat >> "$TODO" << EOF
824
825 # Rebase $SHORTREVISIONS onto $SHORTONTO
t/t3415-rebase-autosquash.sh new
+73
@@ -0,0 +1,73 @@
1 +#!/bin/sh
2 +
3 +test_description='auto squash'
4 +
5 +. ./test-lib.sh
6 +
7 +test_expect_success setup '
8 + echo 0 >file0 &&
9 + git add . &&
10 + test_tick &&
11 + git commit -m "initial commit" &&
12 + echo 0 >file1 &&
13 + echo 2 >file2 &&
14 + git add . &&
15 + test_tick &&
16 + git commit -m "first commit" &&
17 + echo 3 >file3 &&
18 + git add . &&
19 + test_tick &&
20 + git commit -m "second commit" &&
21 + git tag base
22 +'
23 +
24 +test_expect_success 'auto fixup' '
25 + git reset --hard base &&
26 + echo 1 >file1 &&
27 + git add -u &&
28 + test_tick &&
29 + git commit -m "fixup! first"
30 +
31 + git tag final-fixup &&
32 + test_tick &&
33 + git rebase --autosquash -i HEAD^^^ &&
34 + git log --oneline >actual &&
35 + test 3 = $(wc -l <actual) &&
36 + git diff --exit-code final-fixup &&
37 + test 1 = "$(git cat-file blob HEAD^:file1)" &&
38 + test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
39 +'
40 +
41 +test_expect_success 'auto squash' '
42 + git reset --hard base &&
43 + echo 1 >file1 &&
44 + git add -u &&
45 + test_tick &&
46 + git commit -m "squash! first"
47 +
48 + git tag final-squash &&
49 + test_tick &&
50 + git rebase --autosquash -i HEAD^^^ &&
51 + git log --oneline >actual &&
52 + test 3 = $(wc -l <actual) &&
53 + git diff --exit-code final-squash &&
54 + test 1 = "$(git cat-file blob HEAD^:file1)" &&
55 + test 2 = $(git cat-file commit HEAD^ | grep first | wc -l)
56 +'
57 +
58 +test_expect_success 'misspelled auto squash' '
59 + git reset --hard base &&
60 + echo 1 >file1 &&
61 + git add -u &&
62 + test_tick &&
63 + git commit -m "squash! forst"
64 + git tag final-missquash &&
65 + test_tick &&
66 + git rebase --autosquash -i HEAD^^^ &&
67 + git log --oneline >actual &&
68 + test 4 = $(wc -l <actual) &&
69 + git diff --exit-code final-missquash &&
70 + test 0 = $(git rev-list final-missquash...HEAD | wc -l)
71 +'
72 +
73 +test_done