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
 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
 
 '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
 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`.
 
 
        `filter-branch`.
 
 
index 0bd3bf78b8563f29a24dbc7dcc4ef308b3381157..30de96ee1a3f3d15e07f74f2a1b0775cb8b38bd3 100755 (executable)
@@ -302,7 +302,10 @@ nth_string () {
 
 make_squash_message () {
        if test -f "$SQUASH_MSG"; then
 
 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,/^./{
                        < "$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
                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 () {
 }
 
 peek_next_command () {
@@ -367,20 +383,28 @@ do_next () {
                warn
                exit 0
                ;;
                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" ||
 
                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
                author_script=$(get_author_ident_from_commit HEAD)
                output git reset --soft HEAD^
                pick_one -n $sha1 || failed=t
                case "$(peek_next_command)" in
                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"
                        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
 #  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.
 #
 # 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>]..."
 #
 #
 #      "[<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
 
 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
 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"
                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 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
 test_expect_success 'squash works as expected' '
        for n in one two three four
        do