From: "Gabriel.Scherer" <gabriel.scherer@xxxxxxxx> rebase can currently fail if the branch to rebase is checked out in another worktree, and there is no way for users to override this error. We add support for the '--ignore-other-worktrees' option of 'checkout'. Signed-off-by: Gabriel Scherer <gabriel.scherer@xxxxxxxx> --- Documentation/git-rebase.adoc | 6 ++++++ builtin/rebase.c | 11 ++++++++++- t/t3400-rebase.sh | 4 +++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index 005caf6164..b703d4056e 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -305,6 +305,12 @@ see the `--empty` flag. + See also INCOMPATIBLE OPTIONS below. +--ignore-other-worktrees:: + By default, `git rebase` refuses when the branch to rebase is + already checked out or otherwise in use by another + worktree. With this option, other worktrees are ignored and + the rebase proceeds anyway. + --reapply-cherry-picks:: --no-reapply-cherry-picks:: Reapply all clean cherry-picks of any upstream commit instead diff --git a/builtin/rebase.c b/builtin/rebase.c index 3c85768d29..7a57ebd852 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -128,6 +128,7 @@ struct rebase_options { struct strbuf git_format_patch_opt; int reschedule_failed_exec; int reapply_cherry_picks; + int ignore_other_worktrees; int fork_point; int update_refs; int config_autosquash; @@ -146,6 +147,7 @@ struct rebase_options { .git_format_patch_opt = STRBUF_INIT, \ .fork_point = -1, \ .reapply_cherry_picks = -1, \ + .ignore_other_worktrees = -1, \ .allow_empty_message = 1, \ .autosquash = -1, \ .rebase_merges = -1, \ @@ -1234,6 +1236,8 @@ int cmd_rebase(int argc, N_("automatically re-schedule any `exec` that fails")), OPT_BOOL(0, "reapply-cherry-picks", &options.reapply_cherry_picks, N_("apply all changes, even those already present upstream")), + OPT_BOOL(0, "ignore-other-worktrees", &options.ignore_other_worktrees, + N_("do not check if another worktree is using the branch to rebase")), OPT_END(), }; int i; @@ -1580,6 +1584,10 @@ int cmd_rebase(int argc, (options.flags & REBASE_INTERACTIVE_EXPLICIT); } + if (options.ignore_other_worktrees == -1) { + options.ignore_other_worktrees = 0; + } + if (options.type == REBASE_UNSPECIFIED) { if (!strcmp(options.default_backend, "merge")) options.type = REBASE_MERGE; @@ -1679,7 +1687,8 @@ int cmd_rebase(int argc, strbuf_reset(&buf); strbuf_addf(&buf, "refs/heads/%s", branch_name); if (!refs_read_ref(get_main_ref_store(the_repository), buf.buf, &branch_oid)) { - die_if_checked_out(buf.buf, 1); + if (!options.ignore_other_worktrees) + die_if_checked_out(buf.buf, 1); options.head_name = xstrdup(buf.buf); options.orig_head = lookup_commit_object(the_repository, diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index c0c00fbb7b..08448b4d4e 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -407,7 +407,9 @@ test_expect_success 'switch to branch checked out elsewhere fails' ' # we test in both worktrees to ensure that works # as expected with "first" and "next" worktrees test_must_fail git -C wt1 rebase shared shared && - test_must_fail git -C wt2 rebase shared shared + test_must_fail git -C wt2 rebase shared shared && + # with --ignore-other-worktrees the rebase succeeds + git -C wt1 rebase --ignore-other-worktrees shared shared ' test_expect_success 'switch to branch not checked out' ' -- 2.51.0