Skip to content

Commit cea20f2

Browse files
committed
Merge branch 'ns/rebase-auto-squash'
* ns/rebase-auto-squash: rebase -i --autosquash: auto-squash commits Conflicts: git-rebase--interactive.sh
2 parents cc6b41c + f59baa5 commit cea20f2

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

Documentation/git-rebase.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,16 @@ which makes little sense.
308308
root commits will be rewritten to have <newbase> as parent
309309
instead.
310310

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+
311321
include::merge-strategies.txt[]
312322

313323
NOTES

git-rebase--interactive.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ abort abort rebasing process and restore original branch
2828
skip skip current patch and continue rebasing process
2929
no-verify override pre-rebase hook from stopping the operation
3030
root rebase all reachable commmits up to the root(s)
31+
autosquash move commits that begin with squash!/fixup! under -i
3132
"
3233

3334
. git-sh-setup
@@ -46,6 +47,7 @@ ONTO=
4647
VERBOSE=
4748
OK_TO_SKIP_PRE_REBASE=
4849
REBASE_ROOT=
50+
AUTOSQUASH=
4951

5052
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
5153
mark the corrected paths with 'git add <paths>', and
@@ -519,6 +521,37 @@ get_saved_options () {
519521
test -f "$DOTEST"/rebase-root && REBASE_ROOT=t
520522
}
521523

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+
522555
LF='
523556
'
524557
parse_onto () {
@@ -643,6 +676,9 @@ first and then run 'git rebase --continue' again."
643676
--root)
644677
REBASE_ROOT=t
645678
;;
679+
--autosquash)
680+
AUTOSQUASH=t
681+
;;
646682
--onto)
647683
shift
648684
ONTO=$(parse_onto "$1") ||
@@ -802,6 +838,7 @@ first and then run 'git rebase --continue' again."
802838
fi
803839

804840
test -s "$TODO" || echo noop >> "$TODO"
841+
test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
805842
cat >> "$TODO" << EOF
806843
807844
# Rebase $SHORTREVISIONS onto $SHORTONTO

t/t3415-rebase-autosquash.sh

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)