Using a separate git-worktree, why can I not check out the same branch as in the main working copy? If I try, I get the error:
fatal: 'mybranch' is already checked out at '/path/to/repo'
I can see that if I check in from one worktree, the other would end up in a detached HEAD state
Actually, it wouldn't, and that's the problem!
Each work-tree has its own
HEAD, and its own index (aka staging-area or cache). All share the actual underlying repository, and the underlying branch tip files such as
Suppose, then, that two different work-trees (I'll make them both separate from the main repo just so that there's no obvious "preferred" one) both have
HEAD pointing to
mybranch, and you make a commit from one of the two work-trees:
repo$ cd ../worktree1 worktree1$ ... hack away ... worktree1$ git add bar1 bar2 && git commit -m 'foo some bars'
What happens now is the usual: Git writes the index to one or more trees, writes a new commit using the new tree and whatever commit
mybranch resolves to as its parent commit, and updates
mybranch to point to the new commit. The index for
worktree1 now matches the new commit. Now we do this:
worktree1$ cd ../worktree2 worktree2$ ... modify unrelated file, not bar1 or bar2 ... worktree2$ git add unrelated && git commit -m 'unrelated change'
What happens now is that Git writes the index ... wait, the index? Which index? Well, the index—the index in
worktree2. Which does not have files modified and added from
worktree1. (It does have the two
bar files, unless they're totally new, but it has the old versions.) OK, so Git writes the index into one or more trees, writes a new commit using the new tree and whatever commit
mybranch resolves to as its parent, and updates
mybranch to point to the new commit.
The commit chain now looks like this:
1 is the commit made in
2 is the commit made in
worktree2. The name
mybranch, in both work-trees, points to commit
2. The name
HEAD, in both work-trees, contains
ref: refs/heads/mybranch. The index files in the two work trees are different, of course.
The contents for commit
1 are whatever is in the index in
worktree1. It has the changes you made to
The contents for commit
2 are whatever is in the index in
worktree2. It has the changes you made in
unrelated, but it does not have the changes made in files
bar2. In effect, the commit you made in
worktree2 reverted the two files!
If you're willing to have one or both work-trees be in "detached HEAD" state, you can check them out that way, with
git checkout --detach mybranch or
git checkout refs/heads/mybranch. Now at least one of them will have
HEAD pointing directly to a commit, rather than to the branch name, and Git should permit the two work-trees to have the same commit checked out.