Git子模块的工作流程问题



我们的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有什么问题?问题是,每个子模块的新提交比将被覆盖的提交要老。这不是我们想要的,因为存储库上正确地指向41795fc4dde464d633f4c0f01eebb6ab1ad55582a00369bf29f14c761ce71f7b95aa1e9c107fb2edf966744359510656b492ae3091288664cdb1410b,如果我们将这些修改添加到下一次提交中,我们可能会停止这些操作。我不知道为什么它得到了最旧的修订而不是最新的。

我试图自己解决这个问题,但没有成功:

mcfly@future:~/projects/website$ git pull; git submodule foreach git pull

执行最后一个命令是不正确的,因为我们可能会将"网站"的指针更新为每个子模块的最新指针,而我们不希望这样。我们希望保留存储库中的正确修订。

我必须解释的一件事是,我们通常在这个子模块中工作,例如:

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时,每个子模块上的"主"分支都会丢失。

最后,做pushpull和处理子模块的正确方法是什么?

提前感谢

查看git-scm文档并将其传递给您的团队。您所看到的现象在"用子模块克隆项目"一节中有详细描述。

首先,您观察到的初始状态,其中git diff显示了这些提交哈希的意外相反结果,表明您在父repo中合并了子模块更新,但没有在本地运行git submodule update。每次在主项目中删除子模块更改时,都必须运行git submodule update。为什么?子模块的指针,即父存储库认为是vendor/auth的状态,实际上不是子模块存储库vendor/authHEAD提交。在您了解git是如何跟踪子模块状态之前,这会有点令人困惑。同样,git-scm文档值得一读。

其次,git submodule update通过设计放弃了子模块上的master分支。查看这些文档的"子模块问题"部分。手册页,正如git经常出现的情况一样,告诉我们需要知道的:

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.

每次无参数地发出git submodule update时,都会将子模块置于"分离的HEAD"状态。

那么,如何在不出现这些问题的情况下处理子模块呢?首先,问问你自己和你的团队:我们真的需要他们吗?在某些情况下,子模块是一个强大而有用的功能,但它们更多地是为第三方库设计的,而不是分裂成子存储库的活动项目。你当然可以这样使用它们,但管理开销可能会迅速超过你所获得的任何好处。除非你的存储库很大,或者你的子模块是完全模块化的,否则值得问"我们用一个存储库会更好吗?"即使答案是"不",也要检查子树合并,这对你的用例来说可能更成功。

如果你仍然想使用子模块,请查看上面链接的文档,以及SO和其他网站上关于子模块工作流的许多问题和答案。它们应该帮助你实现一个更理智的过程。

最新更新