rebase -i: For fixup commands without squashes, do not start editor
authorMichael Haggerty <mhagger@alum.mit.edu>
Thu, 14 Jan 2010 05:54:55 +0000 (06:54 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 14 Jan 2010 08:27:57 +0000 (00:27 -0800)
If the "rebase -i" commands include a series of fixup commands without
any squash commands, then commit the combined commit using the commit
message of the corresponding "pick" without starting up the
commit-message editor.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-rebase--interactive.sh
t/t3404-rebase-interactive.sh

index d8c3c9aac9ecfcc34aac151760520a961f63ce91..1569a7ad915988cfc14be71eb550debcd134f864 100755 (executable)
@@ -65,6 +65,13 @@ MSG="$DOTEST"/message
 # updated.  It is deleted just before the combined commit is made.
 SQUASH_MSG="$DOTEST"/message-squash
 
+# If the current series of squash/fixups has not yet included a squash
+# command, then this file exists and holds the commit message of the
+# original "pick" commit.  (If the series ends without a "squash"
+# command, then this can be used as the commit message of the combined
+# commit without opening the editor.)
+FIXUP_MSG="$DOTEST"/message-fixup
+
 # $REWRITTEN is the name of a directory containing files for each
 # commit that is reachable by at least one merge base of $HEAD and
 # $UPSTREAM. They are not necessarily rewritten, but their children
@@ -358,7 +365,7 @@ nth_string () {
        esac
 }
 
-update_squash_message () {
+update_squash_messages () {
        if test -f "$SQUASH_MSG"; then
                mv "$SQUASH_MSG" "$SQUASH_MSG".bak || exit
                COUNT=$(($(sed -n \
@@ -371,16 +378,18 @@ update_squash_message () {
                        }' <"$SQUASH_MSG".bak
                } >$SQUASH_MSG
        else
+               commit_message HEAD > "$FIXUP_MSG" || die "Cannot write $FIXUP_MSG"
                COUNT=2
                {
                        echo "# This is a combination of 2 commits."
                        echo "# The first commit's message is:"
                        echo
-                       commit_message HEAD
+                       cat "$FIXUP_MSG"
                } >$SQUASH_MSG
        fi
        case $1 in
        squash)
+               rm -f "$FIXUP_MSG"
                echo
                echo "# This is the $(nth_string $COUNT) commit message:"
                echo
@@ -455,7 +464,7 @@ do_next () {
                        die "Cannot '$squash_style' without a previous commit"
 
                mark_action_done
-               update_squash_message $squash_style $sha1
+               update_squash_messages $squash_style $sha1
                failed=f
                author_script=$(get_author_ident_from_commit HEAD)
                echo "$author_script" > "$AUTHOR_SCRIPT"
@@ -464,34 +473,52 @@ do_next () {
                pick_one -n $sha1 || failed=t
                case "$(peek_next_command)" in
                squash|s|fixup|f)
-                       USE_OUTPUT=output
-                       cp "$SQUASH_MSG" "$MSG" || exit
-                       MSG_OPT=-F
-                       EDIT_OR_FILE="$MSG"
+                       # This is an intermediate commit; its message will only be
+                       # used in case of trouble.  So use the long version:
+                       if test $failed = f
+                       then
+                               do_with_author output git commit --no-verify -F "$SQUASH_MSG" ||
+                                       failed=t
+                       fi
+                       if test $failed = t
+                       then
+                               cp "$SQUASH_MSG" "$MSG" || exit
+                               # After any kind of hiccup, prevent committing without
+                               # opening the commit message editor:
+                               rm -f "$FIXUP_MSG"
+                               cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
+                               warn
+                               warn "Could not apply $sha1... $rest"
+                               die_with_patch $sha1 ""
+                       fi
                        ;;
                *)
-                       USE_OUTPUT=
-                       MSG_OPT=
-                       EDIT_OR_FILE=-e
-                       cp "$SQUASH_MSG" "$MSG" || exit
-                       mv "$SQUASH_MSG" "$GIT_DIR"/SQUASH_MSG || exit
-                       rm -f "$GIT_DIR"/MERGE_MSG || exit
+                       # This is the final command of this squash/fixup group
+                       if test $failed = f
+                       then
+                               if test -f "$FIXUP_MSG"
+                               then
+                                       do_with_author git commit --no-verify -F "$FIXUP_MSG" ||
+                                               failed=t
+                               else
+                                       cp "$SQUASH_MSG" "$GIT_DIR"/SQUASH_MSG || exit
+                                       rm -f "$GIT_DIR"/MERGE_MSG
+                                       do_with_author git commit --no-verify -e ||
+                                               failed=t
+                               fi
+                       fi
+                       rm -f "$FIXUP_MSG"
+                       if test $failed = t
+                       then
+                               mv "$SQUASH_MSG" "$MSG" || exit
+                               cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
+                               warn
+                               warn "Could not apply $sha1... $rest"
+                               die_with_patch $sha1 ""
+                       fi
+                       rm -f "$SQUASH_MSG"
                        ;;
                esac
-               if test $failed = f
-               then
-                       # This is like --amend, but with a different message
-                       do_with_author $USE_OUTPUT git commit --no-verify \
-                               $MSG_OPT "$EDIT_OR_FILE" ||
-                               failed=t
-               fi
-               if test $failed = t
-               then
-                       cp "$MSG" "$GIT_DIR"/MERGE_MSG
-                       warn
-                       warn "Could not apply $sha1... $rest"
-                       die_with_patch $sha1 ""
-               fi
                ;;
        *)
                warn "Unknown command: $command $sha1 $rest"
index 05117091eb173ad84a4308229b8282278bb401c9..175a86c2cb0ef8b3d59718dd79096c5624547ad2 100755 (executable)
@@ -237,14 +237,13 @@ 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' '
+test_expect_success 'multi-fixup does not fire up editor' '
        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" \
-               EXPECT_HEADER_COUNT=4 \
+       FAKE_COMMIT_AMEND="NEVER" 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) &&
+       test 0 = $(git show | grep NEVER | wc -l) &&
        git checkout to-be-rebased &&
        git branch -D multi-fixup
 '