问题
I recently discovered the git worktree command:
The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc.
But the docs also indicate
… the support for submodules is incomplete. It is NOT recommended to make multiple checkouts of a superproject.
without further explanation as to what goes wrong.
Can someone enlighten me about the problems to expect? For example, will I be fine if I use the separate worktrees generated this way only for changes that do not affect the submodules?
回答1:
Commit a83a66a is quite clear about that:
git-submodule.sh
expects$GIT_DIR/config
to be per-worktree, at least for thesubmodule.* part
.
Here I think we have two options:
- either update
config.c
to also read$GIT_DIR/config.worktree
(which is per worktree) in addition to$GIT_DIR/config
(shared) and store worktree-specific vars in the new place,- or update
git-submodule.sh
to read/writesubmodule.*
directly from$GIT_DIR/config.submodule
(per worktree).These take time to address properly. Meanwhile, make a note to the user that they should not use multiple worktrees in submodule context.
More generally, where to put those submodules?
There are a couple options:
- You may want to keep
$SUB
repos elsewhere (perhaps in a central place) outside$SUPER
. This is also true for nested submodules where a superproject may be a submodule of another superproject.- You may want to keep all
$SUB
repos in$SUPER/modules
(or some other place in$SUPER
)- We could even push it further and merge all
$SUB
repos into$SUPER
instead of storing them separately. But that would at least require ref namespace enabled.
This commit was an answer to commit df56607.
From a git user point of view, that means a git submodule update --init --recursive
does not know exactly where to checkout the submodules.
Are they duplicated across all worktrees, or are they centralized somewhere? This isn't formally specified yet.
A year later (and with git 2.9), clacke adds in the comments
the confusion has been resolved, but not in an optimal manner.
Submodules work fine now as far as I can see, but each worktree has its own set of submodule repos (undermotherrepo.git/worktree/<worktreename>/modules/<submodule>
), so if you have a submodule that's big, you are facing some serious disk usage.
Git aliases to handle submodules in subtrees:
- https://gitlab.com/clacke/gists/blob/0c4a0b6e10f7fbf15127339750a6ff490d9aa3c8/.config/git/config#L11
- https://gitlab.com/clacke/gists/blob/0c4a0b6e10f7fbf15127339750a6ff490d9aa3c8/.config/git/config#L12
The alias git wtas
expects that git wta
is defined globally, or at least for all the repos involved. No warranty included. Your favorite pet may catch a painful infection if your path names have spaces in them.
It expects a structure in your repo like the one in a non-bare repo with submodules initiated, so if you have a bare repo, you'll have to mimic that setup. A submodule with the name (not path) foo
goes in <your-.git-directory>/modules/foo
(not .../foo.git
). It will not crash if some module is not present in the repo, it just skips it.
There is room for improvement. It does not handle submodules within submodules, it only goes one level down. It may work to just change the submodule git wta
call to a git wtas
call, but I haven't verified this yet.
-- clacke
See also git worktree move (with Git 2.17+, Q2 2018).
Actually, before Git 2.21 (Q1 2019), "git worktree remove
" and "git worktree move
" refused to work when there is a submodule involved.
This has been loosened to ignore uninitialized submodules.
See commit 00a6d4d (05 Jan 2019) by Nguyễn Thái Ngọc Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit 726f89c, 18 Jan 2019)
worktree
: allow to (re)move worktrees with uninitialized submodulesUninitialized submodules have nothing valuable for us to be worried about. They are just SHA-1.
Let "worktree remove
" and "worktree move
" continue in this case so that people can still use multiple worktrees on repos with optional submodules that are never populated, likesha1collisiondetection
ingit.git
when checked out bydoc-diff
script.Note that for "
worktree remove
", it is possible that a user initializes a submodule (*
), makes some commits (but not push), then deinitializes it.
At that point, the submodule is unpopulated, but the precious new commits are still in:$GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule>
directory and we should not allow removing the worktree or we lose those commits forever.
The new directory check is added to prevent this.(
*
) yes they are screwed anyway by doing this since "git submodule
" would addsubmodule.*
in$GIT_COMMON_DIR/config
, which is shared across multiple worktrees.
But it does not mean we let them be screwed even more.
来源:https://stackoverflow.com/questions/31871888/what-goes-wrong-when-using-git-worktree-with-git-submodules