Skip to content

Commit f60a7b7

Browse files
tgummerergitster
authored andcommitted
worktree: teach "add" to check out existing branches
Currently 'git worktree add <path>' creates a new branch named after the basename of the path by default. If a branch with that name already exists, the command refuses to do anything, unless the '--force' option is given. However we can do a little better than that, and check the branch out if it is not checked out anywhere else. This will help users who just want to check an existing branch out into a new worktree, and save a few keystrokes. As the current behaviour is to simply 'die()' when a branch with the name of the basename of the path already exists, there are no backwards compatibility worries here. We will still 'die()' if the branch is checked out in another worktree, unless the --force flag is passed. Helped-by: Eric Sunshine <[email protected]> Signed-off-by: Thomas Gummerer <[email protected]> Reviewed-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6427f87 commit f60a7b7

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

Documentation/git-worktree.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ $ git worktree add --track -b <branch> <path> <remote>/<branch>
6161
------------
6262
+
6363
If `<commit-ish>` is omitted and neither `-b` nor `-B` nor `--detach` used,
64-
then, as a convenience, a new branch based at HEAD is created automatically,
65-
as if `-b $(basename <path>)` was specified.
64+
then, as a convenience, the new worktree is associated with a branch
65+
(call it `<branch>`) named after `$(basename <path>)`. If `<branch>`
66+
doesn't exist, a new branch based on HEAD is automatically created as
67+
if `-b <branch>` was given. If `<branch>` does exist, it will be
68+
checked out in the new worktree, if it's not checked out anywhere
69+
else, otherwise the command will refuse to create the worktree (unless
70+
`--force` is used).
6671

6772
list::
6873

builtin/worktree.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,17 @@ static const char *dwim_branch(const char *path, const char **new_branch)
391391
{
392392
int n;
393393
const char *s = worktree_basename(path, &n);
394-
*new_branch = xstrndup(s, n);
395-
UNLEAK(*new_branch);
394+
const char *branchname = xstrndup(s, n);
395+
struct strbuf ref = STRBUF_INIT;
396+
397+
UNLEAK(branchname);
398+
if (!strbuf_check_branch_ref(&ref, branchname) &&
399+
ref_exists(ref.buf)) {
400+
strbuf_release(&ref);
401+
return branchname;
402+
}
403+
404+
*new_branch = branchname;
396405
if (guess_remote) {
397406
struct object_id oid;
398407
const char *remote =

t/t2025-worktree-add.sh

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,25 @@ test_expect_success '"add" with <branch> omitted' '
198198
test_cmp_rev HEAD bat
199199
'
200200

201-
test_expect_success '"add" auto-vivify does not clobber existing branch' '
202-
test_commit c1 &&
203-
test_commit c2 &&
204-
git branch precious HEAD~1 &&
205-
test_must_fail git worktree add precious &&
206-
test_cmp_rev HEAD~1 precious &&
207-
test_path_is_missing precious
201+
test_expect_success '"add" checks out existing branch of dwimd name' '
202+
git branch dwim HEAD~1 &&
203+
git worktree add dwim &&
204+
test_cmp_rev HEAD~1 dwim &&
205+
(
206+
cd dwim &&
207+
test_cmp_rev HEAD dwim
208+
)
209+
'
210+
211+
test_expect_success '"add <path>" dwim fails with checked out branch' '
212+
git checkout -b test-branch &&
213+
test_must_fail git worktree add test-branch &&
214+
test_path_is_missing test-branch
215+
'
216+
217+
test_expect_success '"add --force" with existing dwimd name doesnt die' '
218+
git checkout test-branch &&
219+
git worktree add --force test-branch
208220
'
209221

210222
test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '

0 commit comments

Comments
 (0)