7

我们最近在使用 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?问题是每个子模块的新提交都比将被覆盖的提交旧。这不是我们想要的,因为在存储库上正确指向41795fc4dde464d633f4c0f01eebb6ab1ad55582a00369bf29f14c761ce71f7b95aa1e9c107fb2ed并且f966744359510656b492ae3091288664cdb1410b如果我们将此修改添加到我们的下一次提交中,我们可能会阻止这些事情。我不知道为什么它得到了最旧的版本而不是最新的版本。

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

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'master'分支时,每个子模块都会丢失。

最后,什么是正确的方法pushpull并且使用子模块并且没有所有这些问题?

先感谢您

4

1 回答 1

11

查看git-scm 文档并将其传递给您的团队。您看到的现象在“使用子模块克隆项目”部分中进行了准确描述。

首先,您观察到的初始状态git diff显示了这些提交哈希的意外相反结果,表明您在父 repo 中合并了子模块更新,但没有在git submodule update本地运行。git submodule update每次在主项目中拉下子模块更改时,您都必须运行。为什么?子模块的指针,即父存储库认为的状态vendor/auth,实际上并不是HEAD子模块存储库的提交vendor/auth。在您了解 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.

HEAD每次发布时,您都会将子模块置于“分离”状态,git submodule update而无需争论。

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

If you'd still like to use submodules, check out the docs linked above, as well as the many questions and answers on SO and other sites about submodule workflows. They should help you achieve a saner process.

于 2012-08-22T15:41:24.273 回答