70

我有两个或多个项目(我们称它们为ProjectFooProjectBar)有一些我放在submodule中的公共代码

我的理解是,如果我从ProjectFoo中提交对子模块的更改,它将位于一个分离的头中,只有所有ProjectFoo克隆可以看到:

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(56f21fb0...) $ git push
Everything up-to-date

那可能是因为master分支没有改变。我可能会做类似的事情,git checkout master && git merge Everything up-to-date但这看起来很丑陋。可能git reset --hard master会做同样的事情,但看起来更丑陋。

如何让项目共享一个公共代码,使用它的项目中更新?换句话说,提交到该子模块应该更新使用相同子模块的所有各种存储库(存储库,而不仅仅是克隆)。

- - 编辑 - -

显然,我签出的存储库被搞砸了。它应该从一开始就这样工作(在这个例子中的ProjectFoo上):

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(master) $ git push
....
   fbfdd71..0acce63  master -> master
(master) $ cd ..
(master) $ git add ProjectFooBarCommoneSubmodule
(master) $ git commit -m "Submodule update."

然后从其他项目(例如ProjectBar )中获得更改:

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git pull

将更新到最新的通用代码。git checkout master如果它位于分离的头部,则可能需要A。

4

6 回答 6

77

简短的回答:

cd ProjectFooBarCommoneSubmodule
git checkout master
<Do your editing>
git commit --all -m "Lots of fixes"
git push submodule_origin master
cd ..

git add ProjectFooBarCommoneSubmodule
git commit -m "Bumped up the revision of ProjectFooBarCommoneSubmodule"
git push origin master

较长的一个:

Git子模块是一种依赖机制,其中主项目(比如A)在子项目(比如B)中定义了一个指定的修订版,它将用于构建项目A。为了使工具有用,行为必须是可预测的从 A:s 的角度来看。依赖关系不能更改,除非有人决定将更改合并到项目 A。如果项目 B:s 更改自动导入,则可能会发生各种令人讨厌的事情,其中​​编译错误可能是最好的错误,因为 A 会立即注意到失败。这就是为什么 B:s 的头部保持分离状态。

B 的状态存储在 A 中(签出git submodule status),并且必须在 A 中完成并提交修订更改,以使其生效。这就是上面示例中发生的情况,A 更改了存储在 repo 中的修订号,并将版本提升到最新版本。该过程也必须在其他主仓库中重复,因此没有自动“使用主”开关 AFAIK。

顺便提一句。关于子模块的Git 书籍章节子模块手册页包含许多关于子模块的有用信息,包括正常使用和典型陷阱。值得一试。


编辑:我会尝试更好地解释这一点

我冒昧地在我的 github 帐户上创建了示例项目。提交是无意义的并且包含垃圾,但设置应该没问题。请检查它以跟随。

ProjectFoo 和 ProjectBar 共享公共子模块中的代码。

ProjectFooBarCommoneSubmodule:master 是6850e4e4c1fac49de398

在 ProjectFoo 中:

git submodule status

-6850e4e4c1fac49de39890703f21486ca04b87a0 常见

在项目栏中:

git submodule status

-6850e4e4c1fac49de39890703f21486ca04b87a0 常见

所以两者都指向同一个修订版,对吧?这里的诀窍是看到,ProjectFoo 和 ProjectBar 指向修订版(6850e4e4c1fac49de39890703f21486ca04b87a0)而不是分支(主),尽管它们是同一件事。第一个是分离的头,另一个是命名的分支。

如果您想对 ProjectFooBarCommoneSubmodule 进行一些修复,您可以转到例如 ProjectFoo 中的子目录,然后选择分支而不是修订

git checkout master 
<Do your coding and pushing here>

然后上一个目录,检查 git 子模块状态。它应该告诉你,你现在不同步了。例如

git submodule status

+e24bd2bf45d52171a63b67ac05cd4be0ac965f60 通用(heads/master-1-ge24bd2b)

现在你可以做一个 git add,设置对这个特定提交的引用(ge24bd...),做一个提交,然后子模块引用指向这个修订,它也恰好是 ProjectFooBarCommoneSubmodule 上的主。

现在您还需要更新 ProjectBar 中的引用。转到 ProjectBar/common,然后执行 git fetch origin(这是一个快进合并),执行

git checkout master 
cd ..
git add common
git commit -m "Bumped up the revision"
git push origin master # to publish the revision bump to everybody else

因此,与任何 git 存储库一样,您不需要在一个分离的头上工作。您可以在 master 上工作,也可以创建一个命名分支。无论哪种方式,请确保上游包含 ProjectFooBarCommoneSubmodule 更改,否则如果 ProjectFoo 和 ProjectBar 引用不存在的内容,您将破坏它们。希望这能更好地解释它

于 2010-08-28T21:27:38.507 回答
4

submodulegit push origin HEAD:master

于 2016-04-14T11:43:03.210 回答
2

我只是做:

git submodule foreach git push -u origin master

于 2017-07-07T00:18:22.133 回答
1

如果您想一次提交并推送所有子模块,请执行以下操作:

git submodule foreach 'git commit -a' ;
git submodule foreach 'git push --all' ;
git commit -a && \
git push --all --recurse-submodules=on-demand
于 2016-11-03T13:09:36.233 回答
1

注意:

git submodule foreach 'git commit -a'

如果其中一个子模块不包含要执行的提交,则将失败。

要摆脱这种情况,您必须将命令结果强制为 0。

git submodule foreach "git commit -am 'your comment' || echo ' '"

通过使用 echo piped,您可以强制整个命令返回 0 并继续在其他子模块上执行 commit 命令

于 2018-05-17T15:25:06.767 回答
0

要将分离的 HEAD 中的更改合并到 master 中,请运行:

git rebase HEAD master

然后结帐大师(-f用于强制):

git checkout master

如果您有多个子模块要处理,请使用:git submodule foreach,例如

git submodule foreach git pull origin master -r
于 2017-01-14T01:13:07.070 回答