git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 6/9] worktree: teach 'add' to respect --force for registered but missing path

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Aug 28, 2018, 21:20 UTC
Message-ID
<20180828212026.21989-7-sunshine@sunshineco.com>
In-Reply-To
<20180828212026.21989-1-sunshine@sunshineco.com>

For safety, "git worktree add <path>" will refuse to add a new worktree at <path> if <path> is already associated with a worktree entry, even if <path> is missing (for instance, has been deleted or resides on non-mounted removable media or network share). The typical way to re-create a worktree at <path> in such a situation is either to prune all "broken" entries ("git worktree prune") or to selectively remove the worktree entry manually ("git worktree remove <path>").

However, neither of these approaches ("prune" nor "remove") is especially convenient, and they may be unsuitable for scripting when a tool merely wants to re-use a worktree if it exists or create it from scratch if it doesn't (much as a tool might use "mkdir -p" to re-use or create a directory).

Therefore, teach 'add' to respect --force as a convenient way to re-use a path already associated with a worktree entry if the path is non-existent. For a locked worktree, require --force to be specified twice.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
---
 Documentation/git-worktree.txt |  8 ++++++--
 builtin/worktree.c             | 10 ++++++++--
 t/t2025-worktree-add.sh        | 13 ++++++++++++-
 3 files changed, 26 insertions(+), 5 deletions(-)
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
 	`<commit-ish>` 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 `<path>` is already assigned to some
+	working tree but is missing (for instance, if `<path>` 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 <new-branch>::
 -B <new-branch>::
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
-- 
2.19.0.rc1.350.ge57e33dbd1
Previous: Eric SunshineNext: Jeff King
Message 8 of 28 in “worktree: fix bugs and broaden --force applicability”
  1. 0/9 worktree: fix bugs and broaden --force applicabilityEric Sunshine, Aug 28, 2018
  2. 1/9 worktree: don't die() in library function find_worktree()Eric Sunshine, Aug 28, 2018
  3. 2/9 worktree: move delete_git_dir() earlier in file for upcoming new callersEric Sunshine, Aug 28, 2018
  4. 4/9 worktree: prepare for more checks of whether path can become worktreeEric Sunshine, Aug 28, 2018
  5. 3/9 worktree: generalize delete_git_dir() to reduce code duplicationEric Sunshine, Aug 28, 2018
  6. Jeff KingAug 30, 2018
  7. Eric SunshineAug 30, 2018
  8. 6/9 worktree: teach 'add' to respect --force for registered but missing pathEric Sunshine, Aug 28, 2018
  9. Jeff KingAug 30, 2018
  10. Eric SunshineAug 30, 2018
  11. 8/9 worktree: teach 'remove' to override lock when --force given twiceEric Sunshine, Aug 28, 2018
  12. Jeff KingAug 30, 2018
  13. Eric SunshineAug 30, 2018
  14. 9/9 worktree: delete .git/worktrees if empty after 'remove'Eric Sunshine, Aug 28, 2018
  15. 7/9 worktree: teach 'move' to override lock when --force given twiceEric Sunshine, Aug 28, 2018
  16. Jeff KingAug 30, 2018
  17. Eric SunshineAug 30, 2018
  18. 5/9 worktree: disallow adding same path multiple timesEric Sunshine, Aug 28, 2018
  19. Jeff KingAug 30, 2018
  20. Eric SunshineAug 30, 2018
  21. Jeff KingAug 30, 2018
  22. Eric SunshineAug 30, 2018
  23. Eric SunshineAug 30, 2018
  24. Jeff KingAug 30, 2018
  25. Junio C HamanoAug 30, 2018
  26. Ramsay JonesAug 30, 2018
  27. Jeff KingAug 31, 2018
  28. Ramsay JonesAug 31, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.