Add a command "fixup" to rebase --interactive
authorMichael Haggerty <mhagger@alum.mit.edu>
Mon, 7 Dec 2009 09:20:59 +0000 (10:20 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Dec 2009 21:50:57 +0000 (13:50 -0800)
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>
Documentation/git-rebase.txt
git-rebase--interactive.sh
t/lib-rebase.sh
t/t3404-rebase-interactive.sh

index ca5e1e8653be7a1d2b0911ec572ff0a85300ebb9..9b648ece6e6fbd1371cf8802a9a312e2e4473542 100644 (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".
 
 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
@@ -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`.
 
 
index 0bd3bf78b8563f29a24dbc7dcc4ef308b3381157..30de96ee1a3f3d15e07f74f2a1b0775cb8b38bd3 100755 (executable)
@@ -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,/^./{
@@ -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 () {
@@ -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"
@@ -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.
index 62f452c8ea2c2718fff300d39531fbc4c2e6a44a..f4dda02b5ac70f5081f6cf9a35ef6dd8a5c254c3 100644 (file)
@@ -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
@@ -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"
index 778daf419c11fc550d968ef9d5ac780e321ad7cb..ea26115133811e41d2bdc89ea666897a1b00563e 100755 (executable)
@@ -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