[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git
Subject:    Re: git submodule vs GIT_WORK_TREE
From:       Junio C Hamano <gitster () pobox ! com>
Date:       2012-06-29 21:03:15
Message-ID: 7vvci93k6k.fsf () alter ! siamese ! dyndns ! org
[Download RAW message or body]

Junio C Hamano <gitster@pobox.com> 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@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic