On Sat, 2016-10-08 at 19:30 -0500, Michael Tutty wrote:
> Hey all,
> I'm working on some server-side software to do a merge. By using git
> worktree it's possible to check out a given branch for a bare repo and
> merge another branch into it. It's very fast, even with large
> repositories.
> 
> The only exception seems to be merging to master. When I do git
> worktree add /tmp/path/to/worktree master I get an error:
> 
> [fatal: 'master' is already checked out at '/path/to/bare/repo']
> 
> But this is clearly not true, git worktree list gives:
> 
> [/path/to/bare/repo (bare)]
> 
> ...and of course, there is no work tree at that path, just the bare
> repo files you'd expect.

The worktree code treats the base repo as a worktree, even if it's
bare. For the purpose of being able to do a checkout of the main branch
of a bare repo, this patch should do:

diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 4bcc335..b618d6b 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -138,6 +138,14 @@ test_expect_success 'checkout from a bare repo without 
"add"' '
        )
 '
 
+test_expect_success '"add" default branch of a bare repo' '
+       (
+               git clone --bare . bare2 &&
+               cd bare2 &&
+               git worktree add ../there3 master
+       )
+'
+
 test_expect_success 'checkout with grafts' '
        test_when_finished rm .git/info/grafts &&
        test_commit abc &&
diff --git a/worktree.c b/worktree.c
index 5acfe4c..35e95b7 100644
--- a/worktree.c
+++ b/worktree.c
@@ -345,6 +345,8 @@ const struct worktree *find_shared_symref(const char 
*symref,
 
        for (i = 0; worktrees[i]; i++) {
                struct worktree *wt = worktrees[i];
+               if(wt->is_bare)
+                       continue;
 
                if (wt->is_detached && !strcmp(symref, "HEAD")) {
                        if (is_worktree_being_rebased(wt, target)) {


But I'm wondering why the worktree code does this. A bare repo isn't a
worktree and I think it shouldn't treat it as one. A patch that rips
out this feature and updates the tests to match would look like this:


diff --git a/builtin/worktree.c b/builtin/worktree.c
index 5c4854d..3600530 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -382,15 +382,11 @@ static int add(int ac, const char **av, const char 
*prefix)
 static void show_worktree_porcelain(struct worktree *wt)
 {
        printf("worktree %s\n", wt->path);
-       if (wt->is_bare)
-               printf("bare\n");
-       else {
-               printf("HEAD %s\n", sha1_to_hex(wt->head_sha1));
-               if (wt->is_detached)
-                       printf("detached\n");
-               else
-                       printf("branch %s\n", wt->head_ref);
-       }
+       printf("HEAD %s\n", sha1_to_hex(wt->head_sha1));
+       if (wt->is_detached)
+               printf("detached\n");
+       else
+               printf("branch %s\n", wt->head_ref);
        printf("\n");
 }
 
@@ -401,16 +397,12 @@ static void show_worktree(struct worktree *wt, int 
path_maxlen, int abbrev_len)
        int path_adj = cur_path_len - utf8_strwidth(wt->path);
 
        strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path);
-       if (wt->is_bare)
-               strbuf_addstr(&sb, "(bare)");
-       else {
-               strbuf_addf(&sb, "%-*s ", abbrev_len,
-                               find_unique_abbrev(wt->head_sha1, 
DEFAULT_ABBREV));
-               if (!wt->is_detached)
-                       strbuf_addf(&sb, "[%s]", 
shorten_unambiguous_ref(wt->head_ref, 0));
-               else
-                       strbuf_addstr(&sb, "(detached HEAD)");
-       }
+       strbuf_addf(&sb, "%-*s ", abbrev_len,
+                       find_unique_abbrev(wt->head_sha1, DEFAULT_ABBREV));
+       if (!wt->is_detached)
+               strbuf_addf(&sb, "[%s]", shorten_unambiguous_ref(wt->head_ref, 
0));
+       else
+               strbuf_addstr(&sb, "(detached HEAD)");
        printf("%s\n", sb.buf);
 
        strbuf_release(&sb);
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 4bcc335..b618d6b 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -138,6 +138,14 @@ test_expect_success 'checkout from a bare repo without 
"add"' '
        )
 '
 
+test_expect_success '"add" default branch of a bare repo' '
+       (
+               git clone --bare . bare2 &&
+               cd bare2 &&
+               git worktree add ../there3 master
+       )
+'
+
 test_expect_success 'checkout with grafts' '
        test_when_finished rm .git/info/grafts &&
        test_commit abc &&
diff --git a/t/t2027-worktree-list.sh b/t/t2027-worktree-list.sh
index 1b1b65a..842e9d9 100755
--- a/t/t2027-worktree-list.sh
+++ b/t/t2027-worktree-list.sh
@@ -62,9 +62,8 @@ test_expect_success 'bare repo setup' '
 
 test_expect_success '"list" all worktrees from bare main' '
        test_when_finished "rm -rf there && git -C bare1 worktree prune" &&
-       git -C bare1 worktree add --detach ../there master &&
-       echo "$(pwd)/bare1 (bare)" >expect &&
-       echo "$(git -C there rev-parse --show-toplevel) $(git -C there 
rev-parse --short HEAD) (detached HEAD)" >>expect &&
+       git -C bare1 worktree add ../there master &&
+       echo "$(git -C there rev-parse --show-toplevel) $(git -C there 
rev-parse --short HEAD) [master]" >expect &&
        git -C bare1 worktree list | sed "s/  */ /g" >actual &&
        test_cmp expect actual
 '
@@ -72,10 +71,7 @@ test_expect_success '"list" all worktrees from bare main' '
 test_expect_success '"list" all worktrees --porcelain from bare main' '
        test_when_finished "rm -rf there && git -C bare1 worktree prune" &&
        git -C bare1 worktree add --detach ../there master &&
-       echo "worktree $(pwd)/bare1" >expect &&
-       echo "bare" >>expect &&
-       echo >>expect &&
-       echo "worktree $(git -C there rev-parse --show-toplevel)" >>expect &&
+       echo "worktree $(git -C there rev-parse --show-toplevel)" >expect &&
        echo "HEAD $(git -C there rev-parse HEAD)" >>expect &&
        echo "detached" >>expect &&
        echo >>expect &&
@@ -85,9 +81,8 @@ test_expect_success '"list" all worktrees --porcelain from 
bare main' '
 
 test_expect_success '"list" all worktrees from linked with a bare main' '
        test_when_finished "rm -rf there && git -C bare1 worktree prune" &&
-       git -C bare1 worktree add --detach ../there master &&
-       echo "$(pwd)/bare1 (bare)" >expect &&
-       echo "$(git -C there rev-parse --show-toplevel) $(git -C there 
rev-parse --short HEAD) (detached HEAD)" >>expect &&
+       git -C bare1 worktree add ../there master &&
+       echo "$(git -C there rev-parse --show-toplevel) $(git -C there 
rev-parse --short HEAD) [master]" >expect &&
        git -C there worktree list | sed "s/  */ /g" >actual &&
        test_cmp expect actual
 '
diff --git a/worktree.c b/worktree.c
index 5acfe4c..d4dbaab 100644
--- a/worktree.c
+++ b/worktree.c
@@ -84,7 +84,7 @@ static struct worktree *get_main_worktree(void)
        strbuf_add_absolute_path(&worktree_path, get_git_common_dir());
        is_bare = !strbuf_strip_suffix(&worktree_path, "/.git");
        if (is_bare)
-               strbuf_strip_suffix(&worktree_path, "/.");
+               goto done;
 
        strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
 
@@ -94,7 +94,6 @@ static struct worktree *get_main_worktree(void)
        worktree = xmalloc(sizeof(struct worktree));
        worktree->path = strbuf_detach(&worktree_path, NULL);
        worktree->id = NULL;
-       worktree->is_bare = is_bare;
        worktree->head_ref = NULL;
        worktree->is_detached = is_detached;
        worktree->is_current = 0;
@@ -141,7 +140,6 @@ static struct worktree *get_linked_worktree(const char *id)
        worktree = xmalloc(sizeof(struct worktree));
        worktree->path = strbuf_detach(&worktree_path, NULL);
        worktree->id = xstrdup(id);
-       worktree->is_bare = 0;
        worktree->head_ref = NULL;
        worktree->is_detached = is_detached;
        worktree->is_current = 0;
diff --git a/worktree.h b/worktree.h
index 90e1311..04a75e8 100644
--- a/worktree.h
+++ b/worktree.h
@@ -8,7 +8,6 @@ struct worktree {
        char *lock_reason;      /* internal use */
        unsigned char head_sha1[20];
        int is_detached;
-       int is_bare;
        int is_current;
        int lock_reason_valid;
 };

Reply via email to