Git子模块追踪远程分支

22

我想使用git子模块将10多个仓库聚合成一个结构,以便于开发。

它应该克隆模块并检出分支。 然而,该模块以分离头状态检出。

git clone git@github.com:org/global-repository.git
git submodule update —init
cd config-framework
git status

$git status
#HEAD detached at b932ab5
nothing to commit, working directory clean

gitmodules文件似乎没问题

$cat .gitmodules 
[submodule "config-framework"]
        path = config-framework
        url = git@github.com:org/config-framework.git
        branch = MY_BRANCH
我们希望默认检出 MY_BRANCH 分支,而不是游离的 HEAD。我们该如何实现?

这就是子模块的工作方式。主项目引用特定的提交,而不是分支。 - twalberg
这个回答解决了你的问题吗?如何在添加Git子模块时指定分支/标签? - Victor Sergienko
3个回答

25

子模块始终分离的 HEAD 模式检出。

这是因为子模块将会检出存储在父仓库的特殊入口在索引中所存储的 SHA1 值

而且,如果你想让子模块跟随在.gitmodules中注册的分支上,需要:

git submodule update --init --remote

--remote参数将会执行git fetch以及检出新的HEAD
但遗憾的是,甚至该检出操作也只会针对某个提交点进行,而非分支(因为子模块默认情况下没有本地分支),所以此时就会回到分离的HEAD模式。
详见“Git 子模块:指定分支/标签”。

你可以尝试(未经测试):

git submodule foreach 'git checkout -b $(git config -f /path/to/parent/repo/.gitmodules --get submodule.$path.branch)'

我利用了 git submodule foreach 具有访问 '$path' 的能力,该路径是子模块目录相对于超级项目的名称。

曾经有人试图在子模块中指定一个分支以便自动检出(Git 2.0的commit 23d25e4)……但它被撤销了(commit d851ffb,2014年4月2日)!


可能很快就会出现,但不是以当前的实现方式。


如果您能在这里回答我的相关问题,我将不胜感激:https://dev59.com/lYPba4cB1Zd3GeqPqlJW。谢谢! - Aleksandr Blekh

1
为了完成这个任务,我总是使用以下命令(在VonCs之前的建议基础上稍作修改):
export top=$(pwd)
git submodule foreach --recursive 'b=$(git config -f ${top}/.gitmodules submodule.${path}.branch); case "${b}" in "") git checkout ${sha1};; *) git checkout ${b}; git pull origin ${b};; esac'

它会递归检查所有子模块,并将它们检出到其“正确”的分支(如果设置了),否则将其检出到最后一次提交的头部。

2
有趣的方法,但我认为现在(Git 2.18+)一个简单的 git submodule update --remote --recursive 就足够了。 - VonC
那种方法的问题是(虽然我还没有在2.18+上测试过),它将更新所有子模块,包括那些没有远程跟踪分支的子模块,如果我理解正确的话。现在,我的子模块结构基本上由一个存档组成(其中所有子模块都被冻结到给定的sha),然后是一些需要跟踪的子模块。当前的子模块系统似乎无法区分这两者。此外,我的方法允许选择性获取...(我知道,我有相当特定的需求;-)) - BartBog
1
我同意。+1。我记得以前在我的一个旧答案中看到过类似的方法:https://dev59.com/pnI-5IYBdhLWcg3wlpeW#18799234。请注意,您可以从更新中排除子模块:https://dev59.com/KmQn5IYBdhLWcg3wkH7U#43441315。 - VonC
1
“也就是说,如果我理解正确,即使它们没有远程跟踪分支,也是如此。”……遗憾的是,是的。两年前我在https://dev59.com/GZjga4cB1Zd3GeqPFh6q#37924157中说明了这一点。 - VonC
啊,我以为还有另一个问题讨论过这个。像往常一样,解释得非常好 :-) - BartBog

1
如果您计划为子模块做出贡献,最好的方法是将其作为普通的git仓库单独检出。您可以使用不同远程分支进行工作。然后将您的子模块指向您想要用于测试的单个远程分支。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接