mirror of
https://github.com/git/git.git
synced 2024-11-27 03:53:55 +08:00
Merge branch 'pw/rebase-autostash-fix'
"git rebase --autostash" failed to resurrect the autostashed changes when the command gets aborted after giving back control asking for hlep in conflict resolution. * pw/rebase-autostash-fix: rebase: apply and cleanup autostash when rebase fails to start
This commit is contained in:
commit
2b800ec45e
@ -527,6 +527,23 @@ static int rebase_write_basic_state(struct rebase_options *opts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cleanup_autostash(struct rebase_options *opts)
|
||||
{
|
||||
int ret;
|
||||
struct strbuf dir = STRBUF_INIT;
|
||||
const char *path = state_dir_path("autostash", opts);
|
||||
|
||||
if (!file_exists(path))
|
||||
return 0;
|
||||
ret = apply_autostash(path);
|
||||
strbuf_addstr(&dir, opts->state_dir);
|
||||
if (remove_dir_recursively(&dir, 0))
|
||||
ret = error_errno(_("could not remove '%s'"), opts->state_dir);
|
||||
strbuf_release(&dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int finish_rebase(struct rebase_options *opts)
|
||||
{
|
||||
struct strbuf dir = STRBUF_INIT;
|
||||
@ -1727,7 +1744,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
||||
if (require_clean_work_tree(the_repository, "rebase",
|
||||
_("Please commit or stash them."), 1, 1)) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
goto cleanup_autostash;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1750,7 +1767,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
||||
if (options.switch_to) {
|
||||
ret = checkout_up_to_date(&options);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
goto cleanup_autostash;
|
||||
}
|
||||
|
||||
if (!(options.flags & REBASE_NO_QUIET))
|
||||
@ -1776,8 +1793,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
||||
/* If a hook exists, give it a chance to interrupt*/
|
||||
if (!ok_to_skip_pre_rebase &&
|
||||
run_hooks_l(the_repository, "pre-rebase", options.upstream_arg,
|
||||
argc ? argv[0] : NULL, NULL))
|
||||
die(_("The pre-rebase hook refused to rebase."));
|
||||
argc ? argv[0] : NULL, NULL)) {
|
||||
ret = error(_("The pre-rebase hook refused to rebase."));
|
||||
goto cleanup_autostash;
|
||||
}
|
||||
|
||||
if (options.flags & REBASE_DIFFSTAT) {
|
||||
struct diff_options opts;
|
||||
@ -1822,9 +1841,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
||||
RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
|
||||
ropts.head_msg = msg.buf;
|
||||
ropts.default_reflog_action = options.reflog_action;
|
||||
if (reset_head(the_repository, &ropts))
|
||||
die(_("Could not detach HEAD"));
|
||||
strbuf_release(&msg);
|
||||
if (reset_head(the_repository, &ropts)) {
|
||||
ret = error(_("Could not detach HEAD"));
|
||||
goto cleanup_autostash;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the onto is a proper descendant of the tip of the branch, then
|
||||
@ -1852,9 +1872,14 @@ run_rebase:
|
||||
|
||||
cleanup:
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&msg);
|
||||
strbuf_release(&revisions);
|
||||
rebase_options_release(&options);
|
||||
free(squash_onto_name);
|
||||
free(keep_base_onto_name);
|
||||
return !!ret;
|
||||
|
||||
cleanup_autostash:
|
||||
ret |= !!cleanup_autostash(&options);
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -145,7 +145,9 @@ test_expect_success 'Show verbose error when HEAD could not be detached' '
|
||||
test_when_finished "rm -f B" &&
|
||||
test_must_fail git rebase topic 2>output.err >output.out &&
|
||||
test_grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
|
||||
test_grep B output.err
|
||||
test_grep B output.err &&
|
||||
test_must_fail git rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err
|
||||
'
|
||||
|
||||
test_expect_success 'fail when upstream arg is missing and not on branch' '
|
||||
@ -428,7 +430,9 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' '
|
||||
git checkout main &&
|
||||
git worktree add wt &&
|
||||
test_must_fail git -C wt rebase main main 2>err &&
|
||||
test_grep "already used by worktree at" err
|
||||
test_grep "already used by worktree at" err &&
|
||||
test_must_fail git -C wt rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err
|
||||
'
|
||||
|
||||
test_expect_success 'rebase when inside worktree subdirectory' '
|
||||
|
@ -110,7 +110,9 @@ test_expect_success 'pre-rebase hook stops rebase (1)' '
|
||||
git reset --hard side &&
|
||||
test_must_fail git rebase main &&
|
||||
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
|
||||
test 0 = $(git rev-list HEAD...side | wc -l)
|
||||
test 0 = $(git rev-list HEAD...side | wc -l) &&
|
||||
test_must_fail git rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err
|
||||
'
|
||||
|
||||
test_expect_success 'pre-rebase hook stops rebase (2)' '
|
||||
|
@ -82,6 +82,46 @@ testrebase () {
|
||||
type=$1
|
||||
dotest=$2
|
||||
|
||||
test_expect_success "rebase$type: restore autostash when pre-rebase hook fails" '
|
||||
git checkout -f feature-branch &&
|
||||
test_hook pre-rebase <<-\EOF &&
|
||||
exit 1
|
||||
EOF
|
||||
|
||||
echo changed >file0 &&
|
||||
test_must_fail git rebase $type --autostash -f HEAD^ &&
|
||||
test_must_fail git rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err &&
|
||||
echo changed >expect &&
|
||||
test_cmp expect file0
|
||||
'
|
||||
|
||||
test_expect_success "rebase$type: restore autostash when checkout onto fails" '
|
||||
git checkout -f --detach feature-branch &&
|
||||
echo uncommitted-content >file0 &&
|
||||
echo untracked >file4 &&
|
||||
test_when_finished "rm file4" &&
|
||||
test_must_fail git rebase $type --autostash \
|
||||
unrelated-onto-branch &&
|
||||
test_must_fail git rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err &&
|
||||
echo uncommitted-content >expect &&
|
||||
test_cmp expect file0
|
||||
'
|
||||
|
||||
test_expect_success "rebase$type: restore autostash when branch checkout fails" '
|
||||
git checkout -f unrelated-onto-branch^ &&
|
||||
echo uncommitted-content >file0 &&
|
||||
echo untracked >file4 &&
|
||||
test_when_finished "rm file4" &&
|
||||
test_must_fail git rebase $type --autostash HEAD \
|
||||
unrelated-onto-branch &&
|
||||
test_must_fail git rebase --quit 2>err &&
|
||||
test_grep "no rebase in progress" err &&
|
||||
echo uncommitted-content >expect &&
|
||||
test_cmp expect file0
|
||||
'
|
||||
|
||||
test_expect_success "rebase$type: dirty worktree, --no-autostash" '
|
||||
test_config rebase.autostash true &&
|
||||
git reset --hard &&
|
||||
|
Loading…
Reference in New Issue
Block a user