Re: git submodule vs GIT_WORK_TREE

2 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: git submodule vs GIT_WORK_TREE

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:54:12

Junio C Hamano [off-list ref] writes:
quoted
quoted
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.

Re: git submodule vs GIT_WORK_TREE

From: Richard Hartmann <hidden>
Date: 2016-06-15 22:54:12

First of all, thanks for your detailed analysis; it cleared things up
for me quite a bit.

I am not sure if this would work in all cases, but let's assume there
is a new GIT_WORK_ROOT which will always point to the top level of a
given repository (it would stay the same for submodules, as well).

As for storage of .git, GIT_DIR_ROOT would always point to a directory
where git data is stored and GIT_DIR_NAME to the relative path within
GIT_DIR_ROOT. Admittedly, this may be rather specific to vcsh, but I
don't see any other (reliable) option to support submodules.


Thanks,
Richard
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help