Add a command "fixup" to rebase --interactive

The command is like "squash", except that it discards the commit message
of the corresponding commit.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Michael Haggerty 2009-12-07 10:20:59 +01:00 committed by Junio C Hamano
parent 163f392590
commit 0205e72f08
4 changed files with 77 additions and 18 deletions

View File

@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the
command "pick" with the command "reword". command "pick" with the command "reword".
If you want to fold two or more commits into one, replace the command If you want to fold two or more commits into one, replace the command
"pick" with "squash" for the second and subsequent commit. If the "pick" for the second and subsequent commits with "squash" or "fixup".
commits had different authors, it will attribute the squashed commit to If the commits had different authors, the folded commit will be
the author of the first commit. attributed to the author of the first commit. The suggested commit
message for the folded commit is the concatenation of the commit
messages of the first commit and of those with the "squash" command,
but omits the commit messages of commits with the "fixup" command.
'git-rebase' will stop when "pick" has been replaced with "edit" or 'git-rebase' will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done editing when a command fails due to merge errors. When you are done editing
@ -512,8 +515,8 @@ Easy case: The changes are literally the same.::
Hard case: The changes are not the same.:: Hard case: The changes are not the same.::
This happens if the 'subsystem' rebase had conflicts, or used This happens if the 'subsystem' rebase had conflicts, or used
`\--interactive` to omit, edit, or squash commits; or if the `\--interactive` to omit, edit, squash, or fixup commits; or
upstream used one of `commit \--amend`, `reset`, or if the upstream used one of `commit \--amend`, `reset`, or
`filter-branch`. `filter-branch`.

View File

@ -302,7 +302,10 @@ nth_string () {
make_squash_message () { make_squash_message () {
if test -f "$SQUASH_MSG"; then if test -f "$SQUASH_MSG"; then
COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \ # We want to be careful about matching only the commit
# message comment lines generated by this function.
# "[snrt][tdh]" matches the nth_string endings.
COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)[snrt][tdh] commit message.*:/\1/p" \
< "$SQUASH_MSG" | sed -ne '$p')+1)) < "$SQUASH_MSG" | sed -ne '$p')+1))
echo "# This is a combination of $COUNT commits." echo "# This is a combination of $COUNT commits."
sed -e 1d -e '2,/^./{ sed -e 1d -e '2,/^./{
@ -315,10 +318,23 @@ make_squash_message () {
echo echo
git cat-file commit HEAD | sed -e '1,/^$/d' git cat-file commit HEAD | sed -e '1,/^$/d'
fi fi
echo case $1 in
echo "# This is the $(nth_string $COUNT) commit message:" squash)
echo echo
git cat-file commit $1 | sed -e '1,/^$/d' echo "# This is the $(nth_string $COUNT) commit message:"
echo
git cat-file commit $2 | sed -e '1,/^$/d'
;;
fixup)
echo
echo "# The $(nth_string $COUNT) commit message will be skipped:"
echo
# Comment the lines of the commit message out using
# "# " rather than "# " to make them less likely to
# confuse the sed regexp above.
git cat-file commit $2 | sed -e '1,/^$/d' -e 's/^/# /'
;;
esac
} }
peek_next_command () { peek_next_command () {
@ -367,20 +383,28 @@ do_next () {
warn warn
exit 0 exit 0
;; ;;
squash|s) squash|s|fixup|f)
comment_for_reflog squash case "$command" in
squash|s)
squash_style=squash
;;
fixup|f)
squash_style=fixup
;;
esac
comment_for_reflog $squash_style
test -f "$DONE" && has_action "$DONE" || test -f "$DONE" && has_action "$DONE" ||
die "Cannot 'squash' without a previous commit" die "Cannot '$squash_style' without a previous commit"
mark_action_done mark_action_done
make_squash_message $sha1 > "$MSG" make_squash_message $squash_style $sha1 > "$MSG"
failed=f failed=f
author_script=$(get_author_ident_from_commit HEAD) author_script=$(get_author_ident_from_commit HEAD)
output git reset --soft HEAD^ output git reset --soft HEAD^
pick_one -n $sha1 || failed=t pick_one -n $sha1 || failed=t
case "$(peek_next_command)" in case "$(peek_next_command)" in
squash|s) squash|s|fixup|f)
USE_OUTPUT=output USE_OUTPUT=output
MSG_OPT=-F MSG_OPT=-F
EDIT_OR_FILE="$MSG" EDIT_OR_FILE="$MSG"
@ -768,6 +792,7 @@ first and then run 'git rebase --continue' again."
# r, reword = use commit, but edit the commit message # r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending # e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit # s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# #
# If you remove a line here THAT COMMIT WILL BE LOST. # If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted. # However, if you remove everything, the rebase will be aborted.

View File

@ -9,8 +9,9 @@
# #
# "[<lineno1>] [<lineno2>]..." # "[<lineno1>] [<lineno2>]..."
# #
# If a line number is prefixed with "squash", "edit", or "reword", the # If a line number is prefixed with "squash", "fixup", "edit", or
# respective line's command will be replaced with the specified one. # "reword", the respective line's command will be replaced with the
# specified one.
set_fake_editor () { set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh echo "#!$SHELL_PATH" >fake-editor.sh
@ -32,7 +33,7 @@ cat "$1".tmp
action=pick action=pick
for line in $FAKE_LINES; do for line in $FAKE_LINES; do
case $line in case $line in
squash|edit|reword) squash|fixup|edit|reword)
action="$line";; action="$line";;
*) *)
echo sed -n "${line}s/^pick/$action/p" echo sed -n "${line}s/^pick/$action/p"

View File

@ -235,6 +235,36 @@ test_expect_success 'multi-squash only fires up editor once' '
test 1 = $(git show | grep ONCE | wc -l) test 1 = $(git show | grep ONCE | wc -l)
' '
test_expect_success 'multi-fixup only fires up editor once' '
git checkout -b multi-fixup E &&
base=$(git rev-parse HEAD~4) &&
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \
git rebase -i $base &&
test $base = $(git rev-parse HEAD^) &&
test 1 = $(git show | grep ONCE | wc -l) &&
git checkout to-be-rebased &&
git branch -D multi-fixup
'
cat > expect-squash-fixup << EOF
B
D
ONCE
EOF
test_expect_success 'squash and fixup generate correct log messages' '
git checkout -b squash-fixup E &&
base=$(git rev-parse HEAD~4) &&
FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \
git rebase -i $base &&
git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup &&
test_cmp expect-squash-fixup actual-squash-fixup &&
git checkout to-be-rebased &&
git branch -D squash-fixup
'
test_expect_success 'squash works as expected' ' test_expect_success 'squash works as expected' '
for n in one two three four for n in one two three four
do do