diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 29a5b7e252..8537692f05 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -120,8 +120,12 @@ OPTIONS --force:: By default, `add` refuses to create a new working tree when `` is a branch name and is already checked out by - another working tree and `remove` refuses to remove an unclean - working tree. This option overrides these safeguards. + another working tree, or if `` is already assigned to some + working tree but is missing (for instance, if `` was deleted + manually). This option overrides these safeguards. To add a missing but + locked working tree path, specify `--force` twice. ++ +`remove` refuses to remove an unclean working tree unless `--force` is used. -b :: -B :: diff --git a/builtin/worktree.c b/builtin/worktree.c index 1122f27b5f..3eb2f89b0f 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -241,10 +241,16 @@ static void validate_worktree_add(const char *path, const struct add_opts *opts) goto done; locked = !!is_worktree_locked(wt); + if ((!locked && opts->force) || (locked && opts->force > 1)) { + if (delete_git_dir(wt->id)) + die(_("unable to re-add worktree '%s'"), path); + goto done; + } + if (locked) - die(_("'%s' is a missing but locked worktree;\nuse 'unlock' and 'prune' or 'remove' to clear"), path); + die(_("'%s' is a missing but locked worktree;\nuse 'add -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), path); else - die(_("'%s' is a missing but already registered worktree;\nuse 'prune' or 'remove' to clear"), path); + die(_("'%s' is a missing but already registered worktree;\nuse 'add -f' to override, or 'prune' or 'remove' to clear"), path); done: free_worktrees(worktrees); diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh index 67fccc6591..286bba35d8 100755 --- a/t/t2025-worktree-add.sh +++ b/t/t2025-worktree-add.sh @@ -556,7 +556,18 @@ test_expect_success '"add" an existing but missing worktree' ' git worktree add --detach pneu && test_must_fail git worktree add --detach pneu && rm -fr pneu && - test_must_fail git worktree add --detach pneu + test_must_fail git worktree add --detach pneu && + git worktree add --force --detach pneu +' + +test_expect_success '"add" an existing locked but missing worktree' ' + git worktree add --detach gnoo && + git worktree lock gnoo && + test_when_finished "git worktree unlock gnoo || :" && + rm -fr gnoo && + test_must_fail git worktree add --detach gnoo && + test_must_fail git worktree add --force --detach gnoo && + git worktree add --force --force --detach gnoo ' test_done