unlink(git_path_squash_msg());
 }
 
-void die_if_checked_out(const char *branch)
+void die_if_checked_out(const char *branch, int ignore_current_worktree)
 {
        const struct worktree *wt;
 
        wt = find_shared_symref("HEAD", branch);
-       if (!wt)
+       if (!wt || (ignore_current_worktree && wt->is_current))
                return;
        skip_prefix(branch, "refs/heads/", &branch);
        die(_("'%s' is already checked out at '%s'"),
 
  * worktree and die (with a message describing its checkout location) if
  * it is.
  */
-extern void die_if_checked_out(const char *branch);
+extern void die_if_checked_out(const char *branch, int ignore_current_worktree);
 
 /*
  * Update all per-worktree HEADs pointing at the old ref to point the new ref.
 
                char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag);
                if (head_ref &&
                    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
-                       die_if_checked_out(new->path);
+                       die_if_checked_out(new->path, 1);
                free(head_ref);
        }
 
 
        if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
                 ref_exists(symref.buf)) { /* it's a branch */
                if (!opts->force)
-                       die_if_checked_out(symref.buf);
+                       die_if_checked_out(symref.buf, 0);
        } else { /* must be a commit */
                commit = lookup_commit_reference_by_name(refname);
                if (!commit)
                if (!opts.force &&
                    !strbuf_check_branch_ref(&symref, opts.new_branch) &&
                    ref_exists(symref.buf))
-                       die_if_checked_out(symref.buf);
+                       die_if_checked_out(symref.buf, 0);
                strbuf_release(&symref);
        }
 
 
 
 . ./test-lib.sh
 
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
 test_expect_success 'setup' '
        test_commit init
 '
        test_cmp init.t swamp2/init.t
 '
 
+test_expect_success 'put a worktree under rebase' '
+       git worktree add under-rebase &&
+       (
+               cd under-rebase &&
+               set_fake_editor &&
+               FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+               git worktree list | grep "under-rebase.*detached HEAD"
+       )
+'
+
+test_expect_success 'add a worktree, checking out a rebased branch' '
+       test_must_fail git worktree add new-rebase under-rebase &&
+       ! test -d new-rebase
+'
+
+test_expect_success 'checking out a rebased branch from another worktree' '
+       git worktree add new-place &&
+       test_must_fail git -C new-place checkout under-rebase
+'
+
+test_expect_success 'not allow to delete a branch under rebase' '
+       (
+               cd under-rebase &&
+               test_must_fail git branch -D under-rebase
+       )
+'
+
+test_expect_success 'check out from current worktree branch ok' '
+       (
+               cd under-rebase &&
+               git checkout under-rebase &&
+               git checkout - &&
+               git rebase --abort
+       )
+'
+
 test_done
 
 #include "strbuf.h"
 #include "worktree.h"
 #include "dir.h"
+#include "wt-status.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
                return git_common_path("worktrees/%s", wt->id);
 }
 
+static int is_worktree_being_rebased(const struct worktree *wt,
+                                    const char *target)
+{
+       struct wt_status_state state;
+       int found_rebase;
+
+       memset(&state, 0, sizeof(state));
+       found_rebase = wt_status_check_rebase(wt, &state) &&
+               ((state.rebase_in_progress ||
+                 state.rebase_interactive_in_progress) &&
+                state.branch &&
+                starts_with(target, "refs/heads/") &&
+                !strcmp(state.branch, target + strlen("refs/heads/")));
+       free(state.branch);
+       free(state.onto);
+       return found_rebase;
+}
+
+/*
+ * note: this function should be able to detect shared symref even if
+ * HEAD is temporarily detached (e.g. in the middle of rebase or
+ * bisect). New commands that do similar things should update this
+ * function as well.
+ */
 const struct worktree *find_shared_symref(const char *symref,
                                          const char *target)
 {
        for (i = 0; worktrees[i]; i++) {
                struct worktree *wt = worktrees[i];
 
+               if (wt->is_detached && !strcmp(symref, "HEAD")) {
+                       if (is_worktree_being_rebased(wt, target)) {
+                               existing = wt;
+                               break;
+                       }
+               }
+
                strbuf_reset(&path);
                strbuf_reset(&sb);
                strbuf_addf(&path, "%s/%s",