rebase: add --allow-empty-message option
authorGenki Sky <sky@genki.is>
Sun, 4 Feb 2018 20:08:13 +0000 (15:08 -0500)
committerJunio C Hamano <gitster@pobox.com>
Wed, 7 Feb 2018 19:26:46 +0000 (11:26 -0800)
This option allows commits with empty commit messages to be rebased,
matching the same option in git-commit and git-cherry-pick. While empty
log messages are frowned upon, sometimes one finds them in older
repositories (e.g. translated from another VCS [0]), or have other
reasons for desiring them. The option is available in git-commit and
git-cherry-pick, so it is natural to make other git tools play nicely
with them. Adding this as an option allows the default to be "give the
user a chance to fix", while not interrupting the user's workflow
otherwise [1].

[0]: https://stackoverflow.com/q/8542304
[1]: https://public-inbox.org/git/7vd33afqjh.fsf@alter.siamese.dyndns.org/

To implement this, add a new --allow-empty-message flag. Then propagate
it to all calls of 'git commit', 'git cherry-pick', and 'git rebase--helper'
within the rebase scripts.

Signed-off-by: Genki Sky <sky@genki.is>
Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-rebase.txt
builtin/rebase--helper.c
git-rebase--am.sh
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase.sh
t/t3405-rebase-malformed.sh
index 8a861c1e0d69eda71fa2eec791e67c136b63b177..d713951b86abaa3fbea48703f87cce5cf0330019 100644 (file)
@@ -244,6 +244,11 @@ leave out at most one of A and B, in which case it defaults to HEAD.
        Keep the commits that do not change anything from its
        parents in the result.
 
+--allow-empty-message::
+       By default, rebasing commits with an empty message will fail.
+       This option overrides that behavior, allowing commits with empty
+       messages to be rebased.
+
 --skip::
        Restart the rebasing process by skipping the current patch.
 
index 7daee544b7b4cf3495355e1c6e597272d7b66440..2090114e9a33cfd7cf289b43883cbad4b984d8bb 100644 (file)
@@ -22,6 +22,8 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
                OPT_BOOL(0, "keep-empty", &keep_empty, N_("keep empty commits")),
+               OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
+                       N_("allow commits with empty messages")),
                OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
                                CONTINUE),
                OPT_CMDMODE(0, "abort", &command, N_("abort rebase"),
index 14c50782e096966b860d49cbaed7658e9f56958f..0f78051792fae93f7966c2a3f9fc670b4fca9188 100644 (file)
@@ -46,6 +46,7 @@ then
        # makes this easy
        git cherry-pick ${gpg_sign_opt:+"$gpg_sign_opt"} --allow-empty \
                $allow_rerere_autoupdate --right-only "$revisions" \
+               $allow_empty_message \
                ${restrict_revision+^$restrict_revision}
        ret=$?
 else
index d47bd29593ad8711448293f3b6bf2e059323ff78..81c5b42875771ab98ca86e718e14a5a393aa1a86 100644 (file)
@@ -281,7 +281,7 @@ pick_one () {
 
        test -d "$rewritten" &&
                pick_one_preserving_merges "$@" && return
-       output eval git cherry-pick $allow_rerere_autoupdate \
+       output eval git cherry-pick $allow_rerere_autoupdate $allow_empty_message \
                        ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
                        "$strategy_args" $empty_args $ff "$@"
 
@@ -406,6 +406,7 @@ pick_one_preserving_merges () {
                        ;;
                *)
                        output eval git cherry-pick $allow_rerere_autoupdate \
+                               $allow_empty_message \
                                ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
                                "$strategy_args" "$@" ||
                                die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")"
@@ -559,7 +560,8 @@ do_next () {
 
                mark_action_done
                do_pick $sha1 "$rest"
-               git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} || {
+               git commit --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} \
+                       $allow_empty_message || {
                        warn "$(eval_gettext "\
 Could not amend commit after successfully picking \$sha1... \$rest
 This is most likely due to an empty commit message, or the pre-commit hook
@@ -607,7 +609,7 @@ you are able to reword the commit.")"
                        # This is an intermediate commit; its message will only be
                        # used in case of trouble.  So use the long version:
                        do_with_author output git commit --amend --no-verify -F "$squash_msg" \
-                               ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+                               ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
                                die_failed_squash $sha1 "$rest"
                        ;;
                *)
@@ -615,13 +617,13 @@ you are able to reword the commit.")"
                        if test -f "$fixup_msg"
                        then
                                do_with_author git commit --amend --no-verify -F "$fixup_msg" \
-                                       ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+                                       ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
                                        die_failed_squash $sha1 "$rest"
                        else
                                cp "$squash_msg" "$GIT_DIR"/SQUASH_MSG || exit
                                rm -f "$GIT_DIR"/MERGE_MSG
                                do_with_author git commit --amend --no-verify -F "$GIT_DIR"/SQUASH_MSG -e \
-                                       ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+                                       ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
                                        die_failed_squash $sha1 "$rest"
                        fi
                        rm -f "$squash_msg" "$fixup_msg"
@@ -754,7 +756,8 @@ case "$action" in
 continue)
        if test ! -d "$rewritten"
        then
-               exec git rebase--helper ${force_rebase:+--no-ff} --continue
+               exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+                       --continue
        fi
        # do we have anything to commit?
        if git diff-index --cached --quiet HEAD --
@@ -794,11 +797,11 @@ In both cases, once you're done, continue with:
 You have uncommitted changes in your working tree. Please commit them
 first and then run 'git rebase --continue' again.")"
                        do_with_author git commit --amend --no-verify -F "$msg" -e \
-                               ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+                               ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
                                die "$(gettext "Could not commit staged changes.")"
                else
                        do_with_author git commit --no-verify -F "$msg" -e \
-                               ${gpg_sign_opt:+"$gpg_sign_opt"} ||
+                               ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message ||
                                die "$(gettext "Could not commit staged changes.")"
                fi
        fi
@@ -817,7 +820,8 @@ skip)
 
        if test ! -d "$rewritten"
        then
-               exec git rebase--helper ${force_rebase:+--no-ff} --continue
+               exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+                       --continue
        fi
        do_rest
        return 0
@@ -1016,7 +1020,8 @@ checkout_onto
 if test -z "$rebase_root" && test ! -d "$rewritten"
 then
        require_clean_work_tree "rebase"
-       exec git rebase--helper ${force_rebase:+--no-ff} --continue
+       exec git rebase--helper ${force_rebase:+--no-ff} $allow_empty_message \
+               --continue
 fi
 do_rest
 
index 06a4723d4db3db74ea17ace60d824e83cdee25e9..1831e589b8c94b3fbcee710c5742b71a3e7e8f9e 100644 (file)
@@ -27,7 +27,8 @@ continue_merge () {
        cmt=$(cat "$state_dir/current")
        if ! git diff-index --quiet --ignore-submodules HEAD --
        then
-               if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} --no-verify -C "$cmt"
+               if ! git commit ${gpg_sign_opt:+"$gpg_sign_opt"} $allow_empty_message \
+                       --no-verify -C "$cmt"
                then
                        echo "Commit failed, please do not call \"git commit\""
                        echo "directly, but instead do one of the following: "
index fd72a35c65b43537b292445b87ffb7e682cc076a..b353c33d417a913c2b356b3c070b1dbbc033f162 100755 (executable)
@@ -24,6 +24,7 @@ m,merge!           use merging strategies to rebase
 i,interactive!     let the user edit the list of commits to rebase
 x,exec=!           add exec lines after each commit of the editable list
 k,keep-empty      preserve empty commits during rebase
+allow-empty-message allow rebasing commits with empty messages
 f,force-rebase!    force rebase even if branch is up to date
 X,strategy-option=! pass the argument through to the merge strategy
 stat!              display a diffstat of what changed upstream
@@ -89,6 +90,7 @@ action=
 preserve_merges=
 autosquash=
 keep_empty=
+allow_empty_message=
 test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 case "$(git config --bool commit.gpgsign)" in
 true)  gpg_sign_opt=-S ;;
@@ -262,6 +264,9 @@ do
        --keep-empty)
                keep_empty=yes
                ;;
+       --allow-empty-message)
+               allow_empty_message=--allow-empty-message
+               ;;
        --preserve-merges)
                preserve_merges=t
                test -z "$interactive_rebase" && interactive_rebase=implied
index ff8c360cd58bc11366ac2cf9e7c0b141e4ac3a39..cb7c6de84abf88bf90ac9716bb24ac91b8f64bf9 100755 (executable)
@@ -3,6 +3,7 @@
 test_description='rebase should handle arbitrary git message'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
 
 cat >F <<\EOF
 This is an example of a commit log message
@@ -25,6 +26,7 @@ test_expect_success setup '
        test_tick &&
        git commit -m "Initial commit" &&
        git branch diff-in-message &&
+       git branch empty-message-merge &&
 
        git checkout -b multi-line-subject &&
        cat F >file2 &&
@@ -45,6 +47,11 @@ test_expect_success setup '
 
        git cat-file commit HEAD | sed -e "1,/^\$/d" >G0 &&
 
+       git checkout empty-message-merge &&
+       echo file3 >file3 &&
+       git add file3 &&
+       git commit --allow-empty-message -m "" &&
+
        git checkout master &&
 
        echo One >file1 &&
@@ -69,4 +76,20 @@ test_expect_success 'rebase commit with diff in message' '
        test_cmp G G0
 '
 
+test_expect_success 'rebase -m commit with empty message' '
+       test_must_fail git rebase -m master empty-message-merge &&
+       git rebase --abort &&
+       git rebase -m --allow-empty-message master empty-message-merge
+'
+
+test_expect_success 'rebase -i commit with empty message' '
+       git checkout diff-in-message &&
+       set_fake_editor &&
+       test_must_fail env FAKE_COMMIT_MESSAGE=" " FAKE_LINES="reword 1" \
+               git rebase -i HEAD^ &&
+       git rebase --abort &&
+       FAKE_COMMIT_MESSAGE=" " FAKE_LINES="reword 1" \
+               git rebase -i --allow-empty-message HEAD^
+'
+
 test_done