最近我们的Git存储库遇到了很多问题。我们是git子模块的用户,我们的应用程序之间共有4个共享存储库。
例如,存储库'网站'共有3个子模块。
[submodule "vendor/api"]
path = vendor/api
url = git@your.cool.domain.com:api
[submodule "vendor/auth"]
path = vendor/auth
url = git@your.cool.domain.com:auth
[submodule "vendor/tools"]
path = vendor/tools
url = git@your.cool.domain.com:tools
我们已正确检查了我们的主存储库'网站'。现在,我的一位同事做了推动,然后我git pull; git status
:
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: vendor/api (new commits)
# modified: vendor/auth (new commits)
# modified: vendor/tools (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")
mcfly@future:~/projects/website$ git diff
diff --git a/vendor/api b/vendor/api
index 41795fc..b582d80 160000
--- a/vendor/api
+++ b/vendor/api
@@ -1 +1 @@
-Subproject commit 41795fc4dde464d633f4c0f01eebb6ab1ad55582
+Subproject commit b582d802419b0ee7bc3959e7623fec0b94680269
diff --git a/vendor/auth b/vendor/auth
index a00369b..4599a71 160000
--- a/vendor/auth
+++ b/vendor/auth
@@ -1 +1 @@
-Subproject commit a00369bf29f14c761ce71f7b95aa1e9c107fb2ed
+Subproject commit 4599a7179c9b7ca4afa610a15ffa4a8fc6ebf911
diff --git a/vendor/tools b/vendor/tools
index f966744..c678cf6 160000
--- a/vendor/tools
+++ b/vendor/tools
@@ -1 +1 @@
-Subproject commit f966744359510656b492ae3091288664cdb1410b
+Subproject commit c678cf6f599fc450e312f0459ffe74e593f5890f
git diff
的问题是什么?问题是每个子模块的新提交都是OLDER而不是将被覆盖的提交。这不是我们想要的,因为在存储库中正确指向41795fc4dde464d633f4c0f01eebb6ab1ad55582
,a00369bf29f14c761ce71f7b95aa1e9c107fb2ed
和f966744359510656b492ae3091288664cdb1410b
,如果我们将这些修改添加到下一次提交中,我们可能会制造东西。我不知道为什么它会获得最旧版本而不是最新版本。
我试图自己解决这个问题,但没有成功:
mcfly@future:~/projects/website$ git pull; git submodule foreach git pull
执行最后一个命令是不正确的,因为我们可能会更新网站的指针&#39;到每个子模块的最新版本,我们不想要这个。我们希望保留它在存储库中的正确修订。
我要解释的其中一件事我们通常在这个子模块中工作,例如:
mcfly@future:~/projects/website$ cd vendor/api
mcfly@future:~/projects/website/vendor/api$ git checkout master
mcfly@future:~/projects/website/vendor/api$ echo "lorem ipsum" >> example.file
mcfly@future:~/projects/website/vendor/api$ git add example.file; git push
当我们做git submodule update
主人&#39;每个子模块都会丢失分支。
最后,正确处理push
,pull
并使用子模块并且没有遇到所有这些问题的方法是什么?
提前谢谢
答案 0 :(得分:8)
查看git-scm documention并将其传递给您的团队。您所看到的现象在"Cloning a Project with Submodules"部分中有详细描述。
首先,您观察到的初始状态,git diff
显示这些提交哈希的意外相反结果,表示您在父仓库中合并了子模块更新,但未在本地运行git submodule update
。每次下拉主项目中的子模块更改时,都必须运行git submodule update
。为什么?子模块的指针,即父存储库认为是vendor/auth
的状态,实际上并不是子模块存储库HEAD
的{{1}}提交。在您了解git如何跟踪子模块状态之前,这有点令人困惑。同样,git-scm documentation值得一读。
其次,vendor/auth
按设计放弃了子模块上的git submodule update
分支。查看这些文档的"Issues with submodules"部分。手册页通常与git一样,告诉我们需要知道的内容:
master
每次发出update
Update the registered submodules, i.e. clone missing submodules and checkout the commit specified in the index of the containing repository. This will
make the submodules HEAD be detached unless --rebase or --merge is specified or the key submodule.$name.update is set to rebase, merge or none. none
can be overridden by specifying --checkout.
而没有参数时,您的子模块都会处于'分离HEAD
'状态。
那么如何在没有这些问题的情况下使用子模块呢?首先,问问自己和你的团队:我们真的需要它们吗?在某些情况下,子模块是一个功能强大且有用的功能,但它们的设计更多地针对第三方库,而不是主动项目分解为子存储库。你当然可以这样使用它们,但管理开销可能会迅速超过你获得的任何好处。除非您的存储库非常大,或者您的子模块完全是模块化的,否则值得问"Would we be better off with a single repository?"即使答案为“否”,请查看subtree merging,,这可能对您的用例更为成功。
如果您仍想使用子模块,请查看上面链接的the docs,以及SO和其他有关子模块工作流的网站上的许多questions和answers。他们应该帮助你实现一个更健全的过程。