Junio C Hamano <gitster@xxxxxxxxx> writes: >>> Declaring that a checked out submodule _must_ have its controlling >>> repository as ".git" at its root level, i.e. it should be accessible >>> without using GIT_WORK_TREE/GIT_DIR at all just like a normal Git >>> repository is, would be a clean way to avoid the issue altogether >>> and it still will allow the top-level superproject to be structured >>> in a funny way to require GIT_WORK_TREE/GIT_DIR to access it, Let's think aloud a bit with a simple example. Imagine there is a directory hierarchy $HOME/a/b with a file $HOME/a/b/c in it. '$HOME/a' is a working tree of a Git managed project. In a normal layout, there is a $HOME/a/.git directory there that houses its Git repository, and everything (recursively) outside $HOME/a/.git in the directory $HOME/a are working tree files of that repository. You can cd $HOME/a git add b/c to add the file at path b/c, and commit the changes to it. You can relocate $HOME/a/.git elsewhere, say $HOME/git/a.git, by exporting GIT_DIR=$HOME/git/a.git as long as you work at the top level of the working tree. When GIT_DIR alone is set this way, you are giving no clue to Git where the top-level of the working tree is (remember, you relocated $HOME/a/.git away so there is no ".git" in the $HOME/a directory), so your $(cwd) will be always taken as the top level of the working tree. It is inconvenient if you want to work in $HOME/a/b. So you can do this: GIT_WORK_TREE=$HOME/a export GIT_WORK_TREE cd $HOME/a/b git add c and everything works again. Or $HOME/a/b may be a separate project, and $HOME/a/.git repository binds that as a submodule. In a normal layout, a $HOME/a/b/.git directory is there that houses its Git repository. 'c' is a file that appears at the top level of that working tree. When you are at the top-level of the superproject's working tree, you see b/ and Git knows it is a submodule, not a subdirectory of the superproject. It cannot allow "git add b/c" to the superproject. And this will continue to work with GIT_DIR/GIT_WORK_TREE when you move $HOME/a/.git elsewhere. What happens if you also moved $HOME/a/b/.git elsewhere? This will still work when you want to work inside the submodule: GIT_WORK_TREE=$HOME/a/b export GIT_WORK_TREE cd $HOME/a/b git add c to record the change to 'c' at the top-level of the working tree of the submodule. *BUT* There is no ".git" in $HOME/a anywhere, so this breaks when you are in the superproject's working tree. There is no longer anything that tells Git that the $HOME/a/b path is a project boundary. You could look at the index to notice b is known as a submodule, but that is not a usable solution in general. You could have done "git rm --cached" it, perhaps because you wanted to do something clever with it, e.g. in preparation to move it, in which case we still would want to treat it as the working tree of a separate Git repository that is not yet (or no longer) connected to the working tree of the $HOME/a/ repository. By the way, without any of the GIT_DIR/GIT_WORK_TREE hack, the following sequence does not work correctly (it is a bug nobody cares about), and we may want to correct it. mkdir -p /var/tmp/x/a/b cd /var/tmp/x/a git init ;# create a/.git git init ;# create a/b/.git >c && git add c ;# a/b/.git knows about c at the toplevel cd .. ;# back at a git add b/c Even though a/b/.git does not yet have a commit and 'b' has not been registered as a submodule to its index, Git run in 'a' should notice that b/c belongs to somebody else, and refuse to grab it. It has enough cue (namely, the presense of a/b/.git and the directory being a proper Git repository) to do so, but it currently does not use that clue. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html