Currently, if you do: $ git branch zonk origin/master $ git worktree add zonk zonk $ rm -rf zonk $ git branch -d zonk You get the following error: $ git branch -d zonk error: Cannot delete branch 'zonk' checked out at '/home/pjones/devel/kernel.org/git/zonk' It isn't meaningfully checked out, the repo's data is just stale and no longer reflects reality. This makes it so that if nothing is present where a worktree is supposedly checked out, deleting the branch will automatically prune it. Signed-off-by: Peter Jones <pjones@xxxxxxxxxx> --- builtin/branch.c | 2 +- builtin/worktree.c | 14 ++++++++++++++ worktree.h | 6 ++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/builtin/branch.c b/builtin/branch.c index 2ef214632f0..d611f8183b4 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -236,7 +236,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, if (kinds == FILTER_REFS_BRANCHES) { const struct worktree *wt = find_shared_symref("HEAD", name); - if (wt) { + if (wt && prune_worktree_if_missing(wt) < 0) { error(_("Cannot delete branch '%s' " "checked out at '%s'"), bname.buf, wt->path); diff --git a/builtin/worktree.c b/builtin/worktree.c index 4de44f579af..b3ad915c3c3 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -133,6 +133,20 @@ static int prune_worktree(const char *id, struct strbuf *reason) return 0; } +int prune_worktree_if_missing(const struct worktree *wt) +{ + struct strbuf reason = STRBUF_INIT; + + if (access(wt->path, F_OK) >= 0 || + (errno != ENOENT && errno == ENOTDIR)) { + errno = EEXIST; + return -1; + } + + strbuf_addf(&reason, _("Removing worktrees/%s: worktree directory is not present"), wt->id); + return prune_worktree(wt->id, &reason); +} + static void prune_worktrees(void) { struct strbuf reason = STRBUF_INIT; diff --git a/worktree.h b/worktree.h index caecc7a281c..75762c25752 100644 --- a/worktree.h +++ b/worktree.h @@ -132,4 +132,10 @@ void strbuf_worktree_ref(const struct worktree *wt, const char *worktree_ref(const struct worktree *wt, const char *refname); +/* + * Prune a worktree if it is no longer present at the checked out location. + * Returns < 0 if the checkout is there or if pruning fails. + */ +int prune_worktree_if_missing(const struct worktree *wt); + #endif -- 2.23.0