Skip to content

Commit

Permalink
Add a command "fixup" to rebase --interactive
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Haggerty authored and Junio C Hamano committed Dec 7, 2009
1 parent 163f392 commit 0205e72
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 18 deletions.
13 changes: 8 additions & 5 deletions Documentation/git-rebase.txt
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the
command "pick" with the command "reword".

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
commits had different authors, it will attribute the squashed commit to
the author of the first commit.
"pick" for the second and subsequent commits with "squash" or "fixup".
If the commits had different authors, the folded commit will be
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
when a command fails due to merge errors. When you are done editing
Expand Down Expand Up @@ -512,8 +515,8 @@ Easy case: The changes are literally the same.::
Hard case: The changes are not the same.::

This happens if the 'subsystem' rebase had conflicts, or used
`\--interactive` to omit, edit, or squash commits; or if the
upstream used one of `commit \--amend`, `reset`, or
`\--interactive` to omit, edit, squash, or fixup commits; or
if the upstream used one of `commit \--amend`, `reset`, or
`filter-branch`.


Expand Down
45 changes: 35 additions & 10 deletions git-rebase--interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,10 @@ nth_string () {

make_squash_message () {
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))
echo "# This is a combination of $COUNT commits."
sed -e 1d -e '2,/^./{
Expand All @@ -315,10 +318,23 @@ make_squash_message () {
echo
git cat-file commit HEAD | sed -e '1,/^$/d'
fi
echo
echo "# This is the $(nth_string $COUNT) commit message:"
echo
git cat-file commit $1 | sed -e '1,/^$/d'
case $1 in
squash)
echo
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 () {
Expand Down Expand Up @@ -367,20 +383,28 @@ do_next () {
warn
exit 0
;;
squash|s)
comment_for_reflog squash
squash|s|fixup|f)
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" ||
die "Cannot 'squash' without a previous commit"
die "Cannot '$squash_style' without a previous commit"

mark_action_done
make_squash_message $sha1 > "$MSG"
make_squash_message $squash_style $sha1 > "$MSG"
failed=f
author_script=$(get_author_ident_from_commit HEAD)
output git reset --soft HEAD^
pick_one -n $sha1 || failed=t
case "$(peek_next_command)" in
squash|s)
squash|s|fixup|f)
USE_OUTPUT=output
MSG_OPT=-F
EDIT_OR_FILE="$MSG"
Expand Down Expand Up @@ -768,6 +792,7 @@ first and then run 'git rebase --continue' again."
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# 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.
# However, if you remove everything, the rebase will be aborted.
Expand Down
7 changes: 4 additions & 3 deletions t/lib-rebase.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
#
# "[<lineno1>] [<lineno2>]..."
#
# If a line number is prefixed with "squash", "edit", or "reword", the
# respective line's command will be replaced with the specified one.
# If a line number is prefixed with "squash", "fixup", "edit", or
# "reword", the respective line's command will be replaced with the
# specified one.

set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
Expand All @@ -32,7 +33,7 @@ cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
squash|edit|reword)
squash|fixup|edit|reword)
action="$line";;
*)
echo sed -n "${line}s/^pick/$action/p"
Expand Down
30 changes: 30 additions & 0 deletions t/t3404-rebase-interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,36 @@ test_expect_success 'multi-squash only fires up editor once' '
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' '
for n in one two three four
do
Expand Down

0 comments on commit 0205e72

Please sign in to comment.