rebase: add --quit to cleanup rebase, leave everything else untouched

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>

Nguyễn Thái Ngọc Duy committed Nov 12, 2016 at 09:00 UTC 9512177b68263085fef84cdbd45ecdee7bfe2377
4 files changed +37 -4
Documentation/git-rebase.txt
+6 -1
@@ -12,7 +12,7 @@ SYNOPSIS
12 [<upstream> [<branch>]]
13 'git rebase' [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
14 --root [<branch>]
15 -'git rebase' --continue | --skip | --abort | --edit-todo
15 +'git rebase' --continue | --skip | --abort | --quit | --edit-todo
16
17 DESCRIPTION
18 -----------
@@ -252,6 +252,11 @@ leave out at most one of A and B, in which case it defaults to HEAD.
252 will be reset to where it was when the rebase operation was
253 started.
254
255 +--quit::
256 + Abort the rebase operation but HEAD is not reset back to the
257 + original branch. The index and working tree are also left
258 + unchanged as a result.
259 +
260 --keep-empty::
261 Keep the commits that do not change anything from its
262 parents in the result.
contrib/completion/git-completion.bash
+2 -2
@@ -1670,10 +1670,10 @@ _git_rebase ()
1670 {
1671 local dir="$(__gitdir)"
1672 if [ -f "$dir"/rebase-merge/interactive ]; then
1673 - __gitcomp "--continue --skip --abort --edit-todo"
1673 + __gitcomp "--continue --skip --abort --quit --edit-todo"
1674 return
1675 elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
1676 - __gitcomp "--continue --skip --abort"
1676 + __gitcomp "--continue --skip --abort --quit"
1677 return
1678 fi
1679 __git_complete_strategy && return
git-rebase.sh
+5 -1
@@ -43,6 +43,7 @@ continue! continue
43 abort! abort and check out the original branch
44 skip! skip current patch and continue
45 edit-todo! edit the todo list during an interactive rebase
46 +quit! abort but keep HEAD where it is
47 "
48 . git-sh-setup
49 . git-sh-i18n
@@ -239,7 +240,7 @@ do
240 --verify)
241 ok_to_skip_pre_rebase=
242 ;;
242 - --continue|--skip|--abort|--edit-todo)
243 + --continue|--skip|--abort|--quit|--edit-todo)
244 test $total_argc -eq 2 || usage
245 action=${1##--}
246 ;;
@@ -402,6 +403,9 @@ abort)
403 finish_rebase
404 exit
405 ;;
406 +quit)
407 + exec rm -rf "$state_dir"
408 + ;;
409 edit-todo)
410 run_specific_rebase
411 ;;
t/t3407-rebase-abort.sh
+24
@@ -99,4 +99,28 @@ testrebase() {
99 testrebase "" .git/rebase-apply
100 testrebase " --merge" .git/rebase-merge
101
102 +test_expect_success 'rebase --quit' '
103 + cd "$work_dir" &&
104 + # Clean up the state from the previous one
105 + git reset --hard pre-rebase &&
106 + test_must_fail git rebase master &&
107 + test_path_is_dir .git/rebase-apply &&
108 + head_before=$(git rev-parse HEAD) &&
109 + git rebase --quit &&
110 + test $(git rev-parse HEAD) = $head_before &&
111 + test ! -d .git/rebase-apply
112 +'
113 +
114 +test_expect_success 'rebase --merge --quit' '
115 + cd "$work_dir" &&
116 + # Clean up the state from the previous one
117 + git reset --hard pre-rebase &&
118 + test_must_fail git rebase --merge master &&
119 + test_path_is_dir .git/rebase-merge &&
120 + head_before=$(git rev-parse HEAD) &&
121 + git rebase --quit &&
122 + test $(git rev-parse HEAD) = $head_before &&
123 + test ! -d .git/rebase-merge
124 +'
125 +
126 test_done