mirror of
https://github.com/git/git
synced 2024-08-24 18:26:02 +00:00
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>
This commit is contained in:
parent
0205e72f08
commit
f59baa502f
|
@ -308,6 +308,16 @@ which makes little sense.
|
|||
root commits will be rewritten to have <newbase> as parent
|
||||
instead.
|
||||
|
||||
--autosquash::
|
||||
When the commit log message begins with "squash! ..." (or
|
||||
"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 quashing come right after the
|
||||
commit to be modified, and change the action of the moved
|
||||
commit from `pick` to `squash` (or `fixup`).
|
||||
+
|
||||
This option is only valid when '--interactive' option is used.
|
||||
|
||||
include::merge-strategies.txt[]
|
||||
|
||||
NOTES
|
||||
|
|
|
@ -28,6 +28,7 @@ abort abort rebasing process and restore original branch
|
|||
skip skip current patch and continue rebasing process
|
||||
no-verify override pre-rebase hook from stopping the operation
|
||||
root rebase all reachable commmits up to the root(s)
|
||||
autosquash move commits that begin with squash!/fixup! under -i
|
||||
"
|
||||
|
||||
. git-sh-setup
|
||||
|
@ -46,6 +47,7 @@ ONTO=
|
|||
VERBOSE=
|
||||
OK_TO_SKIP_PRE_REBASE=
|
||||
REBASE_ROOT=
|
||||
AUTOSQUASH=
|
||||
|
||||
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
|
||||
mark the corrected paths with 'git add <paths>', and
|
||||
|
@ -519,6 +521,37 @@ get_saved_options () {
|
|||
test -f "$DOTEST"/rebase-root && REBASE_ROOT=t
|
||||
}
|
||||
|
||||
# Rearrange the todo list that has both "pick sha1 msg" and
|
||||
# "pick sha1 fixup!/squash! msg" appears in it so that the latter
|
||||
# comes immediately after the former, and change "pick" to
|
||||
# "fixup"/"squash".
|
||||
rearrange_squash () {
|
||||
sed -n -e 's/^pick \([0-9a-f]*\) \(squash\)! /\1 \2 /p' \
|
||||
-e 's/^pick \([0-9a-f]*\) \(fixup\)! /\1 \2 /p' \
|
||||
"$1" >"$1.sq"
|
||||
test -s "$1.sq" || return
|
||||
|
||||
used=
|
||||
while read pick sha1 message
|
||||
do
|
||||
case " $used" in
|
||||
*" $sha1 "*) continue ;;
|
||||
esac
|
||||
echo "$pick $sha1 $message"
|
||||
while read squash action msg
|
||||
do
|
||||
case "$message" in
|
||||
"$msg"*)
|
||||
echo "$action $squash $action! $msg"
|
||||
used="$used$squash "
|
||||
;;
|
||||
esac
|
||||
done <"$1.sq"
|
||||
done >"$1.rearranged" <"$1"
|
||||
cat "$1.rearranged" >"$1"
|
||||
rm -f "$1.sq" "$1.rearranged"
|
||||
}
|
||||
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
|
@ -624,6 +657,9 @@ first and then run 'git rebase --continue' again."
|
|||
--root)
|
||||
REBASE_ROOT=t
|
||||
;;
|
||||
--autosquash)
|
||||
AUTOSQUASH=t
|
||||
;;
|
||||
--onto)
|
||||
shift
|
||||
ONTO=$(git rev-parse --verify "$1") ||
|
||||
|
@ -783,6 +819,7 @@ first and then run 'git rebase --continue' again."
|
|||
fi
|
||||
|
||||
test -s "$TODO" || echo noop >> "$TODO"
|
||||
test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
|
||||
cat >> "$TODO" << EOF
|
||||
|
||||
# Rebase $SHORTREVISIONS onto $SHORTONTO
|
||||
|
|
73
t/t3415-rebase-autosquash.sh
Executable file
73
t/t3415-rebase-autosquash.sh
Executable file
|
@ -0,0 +1,73 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='auto squash'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
echo 0 >file0 &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m "initial commit" &&
|
||||
echo 0 >file1 &&
|
||||
echo 2 >file2 &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m "first commit" &&
|
||||
echo 3 >file3 &&
|
||||
git add . &&
|
||||
test_tick &&
|
||||
git commit -m "second commit" &&
|
||||
git tag base
|
||||
'
|
||||
|
||||
test_expect_success 'auto fixup' '
|
||||
git reset --hard base &&
|
||||
echo 1 >file1 &&
|
||||
git add -u &&
|
||||
test_tick &&
|
||||
git commit -m "fixup! first"
|
||||
|
||||
git tag final-fixup &&
|
||||
test_tick &&
|
||||
git rebase --autosquash -i HEAD^^^ &&
|
||||
git log --oneline >actual &&
|
||||
test 3 = $(wc -l <actual) &&
|
||||
git diff --exit-code final-fixup &&
|
||||
test 1 = "$(git cat-file blob HEAD^:file1)" &&
|
||||
test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
|
||||
'
|
||||
|
||||
test_expect_success 'auto squash' '
|
||||
git reset --hard base &&
|
||||
echo 1 >file1 &&
|
||||
git add -u &&
|
||||
test_tick &&
|
||||
git commit -m "squash! first"
|
||||
|
||||
git tag final-squash &&
|
||||
test_tick &&
|
||||
git rebase --autosquash -i HEAD^^^ &&
|
||||
git log --oneline >actual &&
|
||||
test 3 = $(wc -l <actual) &&
|
||||
git diff --exit-code final-squash &&
|
||||
test 1 = "$(git cat-file blob HEAD^:file1)" &&
|
||||
test 2 = $(git cat-file commit HEAD^ | grep first | wc -l)
|
||||
'
|
||||
|
||||
test_expect_success 'misspelled auto squash' '
|
||||
git reset --hard base &&
|
||||
echo 1 >file1 &&
|
||||
git add -u &&
|
||||
test_tick &&
|
||||
git commit -m "squash! forst"
|
||||
git tag final-missquash &&
|
||||
test_tick &&
|
||||
git rebase --autosquash -i HEAD^^^ &&
|
||||
git log --oneline >actual &&
|
||||
test 4 = $(wc -l <actual) &&
|
||||
git diff --exit-code final-missquash &&
|
||||
test 0 = $(git rev-list final-missquash...HEAD | wc -l)
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in a new issue