Skip to content

Commit 810382e

Browse files
sunshinecogitster
authored andcommitted
worktree: make "move" refuse to move atop missing registered worktree
"git worktree add" takes special care to avoid creating a new worktree at a location already registered to an existing worktree even if that worktree is missing (which can happen, for instance, if the worktree resides on removable media). "git worktree move", however, is not so careful when validating the destination location and will happily move the source worktree atop the location of a missing worktree. This leads to the anomalous situation of multiple worktrees being associated with the same path, which is expressly forbidden by design. For example: $ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz] $ git worktree remove ../bar fatal: validation failed, cannot remove working tree: '.../bar' does not point back to '.git/worktrees/bar' Fix this shortcoming by enhancing "git worktree move" to perform the same additional validation of the destination directory as done by "git worktree add". While at it, add a test to verify that "git worktree move" won't move a worktree atop an existing (non-worktree) path -- a restriction which has always been in place but was never tested. Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d179af6 commit 810382e

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

Documentation/git-worktree.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ OPTIONS
126126
locked working tree path, specify `--force` twice.
127127
+
128128
`move` refuses to move a locked working tree unless `--force` is specified
129-
twice.
129+
twice. If the destination is already assigned to some other working tree but is
130+
missing (for instance, if `<new-path>` was deleted manually), then `--force`
131+
allows the move to proceed; use --force twice if the destination is locked.
130132
+
131133
`remove` refuses to remove an unclean working tree unless `--force` is used.
132134
To remove a locked working tree, specify `--force` twice.

builtin/worktree.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -860,8 +860,7 @@ static int move_worktree(int ac, const char **av, const char *prefix)
860860
strbuf_trim_trailing_dir_sep(&dst);
861861
strbuf_addstr(&dst, sep);
862862
}
863-
if (file_exists(dst.buf))
864-
die(_("target '%s' already exists"), dst.buf);
863+
check_candidate_path(dst.buf, force, worktrees, "move");
865864

866865
validate_no_submodules(wt);
867866

t/t2403-worktree-move.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ test_expect_success 'move locked worktree (force)' '
112112
git worktree move --force --force flump ploof
113113
'
114114

115+
test_expect_success 'refuse to move worktree atop existing path' '
116+
>bobble &&
117+
git worktree add --detach beeble &&
118+
test_must_fail git worktree move beeble bobble
119+
'
120+
121+
test_expect_success 'move atop existing but missing worktree' '
122+
git worktree add --detach gnoo &&
123+
git worktree add --detach pneu &&
124+
rm -fr pneu &&
125+
test_must_fail git worktree move gnoo pneu &&
126+
git worktree move --force gnoo pneu &&
127+
128+
git worktree add --detach nu &&
129+
git worktree lock nu &&
130+
rm -fr nu &&
131+
test_must_fail git worktree move pneu nu &&
132+
test_must_fail git worktree --force move pneu nu &&
133+
git worktree move --force --force pneu nu
134+
'
135+
115136
test_expect_success 'move a repo with uninitialized submodule' '
116137
git init withsub &&
117138
(

0 commit comments

Comments
 (0)