我不清楚以下是什么意思(来自git submodule update docs):
......除非指定
--rebase
或--merge
,否则将使子模块HEAD分离...
--rebase
/ --merge
如何改变事物?
我的主要用例是有一堆中央存储库,我将通过子模块嵌入到其他存储库中。我希望能够改进这些中央回购,直接在他们的原始位置,或从他们的嵌入回购(通过子模块使用它们的那些)。
这个GitPro page很好地总结了git子模块更新的结果
运行
git submodule update
时,它会检出项目的特定版本,但不会检出分支。这称为具有分离的头 - 这意味着HEAD文件直接指向提交,而不是指向符号引用。 问题在于,您通常不希望在分离的头部环境中工作,因为很容易丢失更改。 如果您执行初始子模块更新,请在该子模块目录中提交而不创建要运行的分支,然后再从超级项目再次运行git子模块更新而不提交,Git将在不告知您的情况下覆盖您的更改。从技术上讲,你不会失去工作,但你不会有一个分支指向它,所以它将有点难以检索。
注意2013年3月:
如“git submodule tracking latest”中所述,现在的子模块(git1.8.2)可以跟踪分支。
# add submodule to track master branch
git submodule add -b master [URL to Git repo];
# update your submodule
git submodule update --remote
# or (with rebase)
git submodule update --rebase --remote
见“git submodule update --remote
vs git pull
”。
MindTooth的answer说明了手动更新(没有本地配置):
git submodule -q foreach git pull -q origin master
在这两种情况下,这将改变子模块引用(gitlink,special entry in the parent repo index),并且您将需要添加,提交和推送来自主repo的所述引用。 下次您将克隆该父repo时,它将填充子模块以反映这些新的SHA1引用。
本答案的其余部分详细介绍了经典的子模块功能(引用固定提交,这是子模块概念背后的所有要点)。
要避免此问题,请在使用git checkout -b work或等效工作的子模块目录中创建分支。当您第二次执行子模块更新时,它仍将恢复您的工作,但至少您有一个指针可以返回。
切换带有子模块的分支也很棘手。如果您创建一个新分支,在那里添加一个子模块,然后切换回没有该子模块的分支,您仍然将子模块目录作为未跟踪的目录:
那么,回答你的问题:
我可以创建分支/修改并使用推/拉,就像我在常规回购中一样,或者有什么需要谨慎的吗?
您可以创建分支并推送修改。
警告(来自Git Submodule Tutorial):在将更改发布(推送)到引用它的超级项目之前,始终发布(推送)子模块更改。如果您忘记发布子模块更改,则其他人将无法克隆存储库。
我如何将子模块引用的提交从say(tagged)1.0推进到1.1(即使原始repo的头部已经是2.0)
页面“Understanding Submodules”可以提供帮助
Git子模块使用两个移动部件实现:
.gitmodules
文件和- 一种特殊的树对象。
这些一起对特定存储库的特定修订进行三角测量,该存储库被检出到项目中的特定位置。
您无法从主项目中修改子模块的内容
100%正确:您无法修改子模块,只能参考其中一个提交。
这就是为什么当您从主项目中修改子模块时,您:
子模块使您可以进行component-based approach开发,其中主项目仅引用其他组件的特定提交(此处“声明为子模块的其他Git存储库”)。
子模块是另一个Git存储库的标记(提交),它不受主项目开发周期的约束:它(“其他”Git存储库)可以独立发展。 主要项目取决于其他任何需要提交的回购。
但是,如果您想方便地直接从主项目中修改其中一个子模块,Git允许您这样做,前提是您首先将这些子模块修改发布到其原始Git仓库,然后提交您的主项目引用所述子模块的新版本。
但主要的想法仍然是:引用以下特定组件:
您在主项目中引用的特定提交列表定义了您的configuration(这是配置管理的全部内容,仅仅是Version Control System)
如果一个组件真的可以与你的主项目同时开发(因为对主项目的任何修改都涉及修改子目录,反之亦然),那么它将不再是一个“子模块”,而是一个子树合并(也在问题Transferring legacy code base from cvs to distributed repository中提出),将两个Git repo的历史联系在一起。
这有助于理解Git子模块的真实性质吗?
要更新每个子模块,可以调用以下命令。 (根据回购。)
git submodule -q foreach git pull -q origin master
您可以删除-q选项以遵循整个过程。
要解决--rebase vs --merge选项:
假设您有超级回购A和子模块B,并希望在子模块B中做一些工作。您已完成作业并且在调用后知道
git submodule update
你处于无HEAD状态,所以你在这一点上做的任何提交都很难回复。所以,你已经开始在子模块B中的新分支上工作了
cd B
git checkout -b bestIdeaForBEver
<do work>
与此同时,项目A中的其他人已经确定最新和最好的B版本确实是应得的。出于习惯,您可以合并最近的更改并更新子模块。
<in A>
git merge develop
git submodule update
哦,不!你又回到了无头状态,可能是因为B现在指向与B的新提示或其他提交相关联的SHA。如果只有你:
git merge develop
git submodule update --rebase
Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'
现在B的最佳创意已经重新定位到新的提交,更重要的是,你仍然在B的开发分支上,而不是无头状态!
(--merge会将来自beforeUpdateSHA的更改合并到afterUpdateSHA到您的工作分支,而不是将更改重新定义到afterUpdateSHA。)
Git 1.8.2提供了一个新的选项--remote
,可以实现这种行为。运行
git submodule update --rebase --remote
将从每个子模块的上游获取最新的更改,将它们重新绑定,并检查子模块的最新版本。正如the docs所说:
--remote
此选项仅对update命令有效。不使用超级项目记录的SHA-1来更新子模块,而是使用子模块的远程跟踪分支的状态。
这相当于在每个子模块中运行git pull
,这通常正是您想要的。
(从this answer复制)