]> granicus.if.org Git - git/commitdiff
rebase: add --quit to cleanup rebase, leave everything else untouched
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sat, 12 Nov 2016 02:00:41 +0000 (09:00 +0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 11 Dec 2016 21:51:41 +0000 (13:51 -0800)
There are occasions when you decide to abort an in-progress rebase and
move on to do something else but you forget to do "git rebase --abort"
first. Or the rebase has been in progress for so long you forgot about
it. By the time you realize that (e.g. by starting another rebase)
it's already too late to retrace your steps. The solution is normally

    rm -r .git/<some rebase dir>

and continue with your life. But there could be two different
directories for <some rebase dir> (and it obviously requires some
knowledge of how rebase works), and the ".git" part could be much
longer if you are not at top-dir, or in a linked worktree. And
"rm -r" is very dangerous to do in .git, a mistake in there could
destroy object database or other important data.

Provide "git rebase --quit" for this use case, mimicking a precedent
that is "git cherry-pick --quit".

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-rebase.txt
contrib/completion/git-completion.bash
git-rebase.sh
t/t3407-rebase-abort.sh

index 6ed610a031eeec7320adbbb4a627dc4997499e56..f89245818f6c3f3d5f42e4c754f939038f65767b 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
        [<upstream> [<branch>]]
 'git rebase' [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
        --root [<branch>]
-'git rebase' --continue | --skip | --abort | --edit-todo
+'git rebase' --continue | --skip | --abort | --quit | --edit-todo
 
 DESCRIPTION
 -----------
@@ -252,6 +252,11 @@ leave out at most one of A and B, in which case it defaults to HEAD.
        will be reset to where it was when the rebase operation was
        started.
 
+--quit::
+       Abort the rebase operation but HEAD is not reset back to the
+       original branch. The index and working tree are also left
+       unchanged as a result.
+
 --keep-empty::
        Keep the commits that do not change anything from its
        parents in the result.
index e3918c87e3adf32a9d7a4f0320c92c497376b9b5..2c134f8d9098d793e2a6025e557cc08ecaaaf118 100644 (file)
@@ -1670,10 +1670,10 @@ _git_rebase ()
 {
        local dir="$(__gitdir)"
        if [ -f "$dir"/rebase-merge/interactive ]; then
-               __gitcomp "--continue --skip --abort --edit-todo"
+               __gitcomp "--continue --skip --abort --quit --edit-todo"
                return
        elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
-               __gitcomp "--continue --skip --abort"
+               __gitcomp "--continue --skip --abort --quit"
                return
        fi
        __git_complete_strategy && return
index cf60c4390870ef28cff08b6a173a435d41e2d470..c62b17863e2132da5d1e78697fb3b8feb3629a60 100755 (executable)
@@ -43,6 +43,7 @@ continue!          continue
 abort!             abort and check out the original branch
 skip!              skip current patch and continue
 edit-todo!         edit the todo list during an interactive rebase
+quit!              abort but keep HEAD where it is
 "
 . git-sh-setup
 . git-sh-i18n
@@ -239,7 +240,7 @@ do
        --verify)
                ok_to_skip_pre_rebase=
                ;;
-       --continue|--skip|--abort|--edit-todo)
+       --continue|--skip|--abort|--quit|--edit-todo)
                test $total_argc -eq 2 || usage
                action=${1##--}
                ;;
@@ -402,6 +403,9 @@ abort)
        finish_rebase
        exit
        ;;
+quit)
+       exec rm -rf "$state_dir"
+       ;;
 edit-todo)
        run_specific_rebase
        ;;
index a6a6c40a98512b190f8610391aa153a294e4b5cb..910f2182843476edf878bfc42f34d868c70d8cf5 100755 (executable)
@@ -99,4 +99,28 @@ testrebase() {
 testrebase "" .git/rebase-apply
 testrebase " --merge" .git/rebase-merge
 
+test_expect_success 'rebase --quit' '
+       cd "$work_dir" &&
+       # Clean up the state from the previous one
+       git reset --hard pre-rebase &&
+       test_must_fail git rebase master &&
+       test_path_is_dir .git/rebase-apply &&
+       head_before=$(git rev-parse HEAD) &&
+       git rebase --quit &&
+       test $(git rev-parse HEAD) = $head_before &&
+       test ! -d .git/rebase-apply
+'
+
+test_expect_success 'rebase --merge --quit' '
+       cd "$work_dir" &&
+       # Clean up the state from the previous one
+       git reset --hard pre-rebase &&
+       test_must_fail git rebase --merge master &&
+       test_path_is_dir .git/rebase-merge &&
+       head_before=$(git rev-parse HEAD) &&
+       git rebase --quit &&
+       test $(git rev-parse HEAD) = $head_before &&
+       test ! -d .git/rebase-merge
+'
+
 test_done