git submodule update
我不清楚以下是什么意思(来自git子模块更新文档):
...will make the submodules HEAD be detached, unless
--rebase or--merge is specified...
我的主要用例是拥有一组中央回购协议,我将通过子模块将其嵌入到其他回购协议中。我希望能够改进这些中央回购,无论是直接在它们的原始位置,还是从它们的嵌入回购(通过子模块使用它们的回购)中。
- 从这些子模块中,我可以创建分支/修改并像在常规回购中那样使用推/拉,还是需要注意一些事情?
- 我如何将子模块引用的提交从say(taged)1.0推进到1.1(即使原始回购的头已经在2.0),或者选择使用哪个分支的提交?
这个Gitpro页面很好地总结了Git子模块更新的结果。
When you run
git submodule update , it checks out the specific version of the project, but not within a branch. This is called having a detached head — it means the HEAD file points directly to a commit, not to a symbolic reference.
The issue is that you generally don’t want to work in a detached head environment, because it’s easy to lose changes.
If you do an initial submodule update, commit in that submodule directory without creating a branch to work in, and then run git submodule update again from the superproject without committing in the meantime, Git will overwrite your changes without telling you. Technically you won’t lose the work, but you won’t have a branch pointing to it, so it will be somewhat difficult to retrieve.
注:2013年3月:
如"最新Git子模块跟踪"中所述,现在的子模块(Git1.8.2)可以跟踪分支。
1 2 3 4 5 6 7 | # 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 |
见"
Mindtoth的答案说明了手动更新(无本地配置):
1 | git submodule -q foreach git pull -q origin master |
在这两种情况下,这将更改子模块引用(gitlink,父repo索引中的一个特殊条目),您需要从主repo添加、提交和推送所述引用。下次克隆父repo时,它将填充子模块以反映这些新的sha1引用。
这个答案的其余部分详细介绍了经典的子模块特性(引用了固定提交,这是子模块概念背后的所有要点)。
To avoid this issue, create a branch when you work in a submodule directory with git checkout -b work or something equivalent. When you do the submodule update a second time, it will still revert your work, but at least you have a pointer to get back to.
Switching branches with submodules in them can also be tricky. If you create a new branch, add a submodule there, and then switch back to a branch without that submodule, you still have the submodule directory as an untracked directory:
所以,要回答你的问题:
can I create branches/modifications and use push/pull just like I would in regular repos, or are there things to be cautious about?
您可以创建一个分支并推送修改。
警告(来自git子模块教程):在发布(push)引用子模块的父项目的更改之前,始终发布(push)子模块更改。如果忘记发布子模块更改,其他人将无法克隆存储库。
how would I advance the submodule referenced commit from say (tagged) 1.0 to 1.1 (even though the head of the original repo is already at 2.0)
"了解子模块"页面有助于
Git submodules are implemented using two moving parts:
- the
.gitmodules file and- a special kind of tree object.
它们一起对特定存储库的特定修订进行三角测量,该存储库将签出到项目中的特定位置。
从Git子模块页
you cannot modify the contents of the submodule from within the main project
100%正确:不能修改子模块,只能引用它的一个提交。
这就是为什么当您在主项目中修改子模块时,您:
- 需要在子模块内提交和推送(到上游模块),以及
- 然后进入主项目,重新提交(为了使主项目引用刚才创建和推送的新子模块commit)
子模块使您能够进行基于组件的方法开发,其中主项目只涉及其他组件的特定提交(这里是"声明为子模块的其他Git存储库")。
子模块是另一个Git存储库的标记(提交),该存储库不受主项目开发周期的约束:它("其他"Git repo)可以独立发展。主要项目是从其他回购协议中选择所需的任何承诺。
但是,如果您想在方便的情况下直接从主项目中修改其中一个子模块,Git允许您这样做,前提是您首先将这些子模块修改发布到其原始Git repo,然后提交主项目引用该子模块的新版本。
但主要的想法仍然是:引用特定的组件,这些组件:
- 拥有自己的生命周期
- 有自己的标签
- 有自己的发展
您在主项目中引用的特定提交列表定义了您的配置(这就是配置管理的全部内容,仅限于版本控制系统)。
如果一个组件确实可以与主项目同时开发(因为对主项目的任何修改都将涉及修改子目录,反之亦然),那么它将不再是一个"子模块",而是一个子树合并(也出现在将遗留代码库从cvs传输到分布式存储库的问题中),linki两个git回购的历史。
这有助于理解git子模块的真正性质吗?
要更新每个子模块,可以调用以下命令。(在回购的根部。)
1 | git submodule -q foreach git pull -q origin master |
您可以删除-q选项来执行整个过程。
要解决--rebase vs--merge选项:
假设你有super repo A和submodule B,想在submodule B中做些工作,你已经完成了作业,打电话后知道了
您处于无头状态,因此此时所做的任何承诺都很难恢复。所以,你已经开始在子模块B中开发一个新的分支。
1 2 3 | cd B git checkout -b bestIdeaForBEver <do work> |
同时,项目A中的其他人已经决定,B的最新和最好的版本确实是A应得的。出于习惯,您将最新的更改合并下来并更新子模块。
1 2 3 | <in A> git merge develop git submodule update |
哦,不!您又回到了无头状态,可能是因为B现在指向了与B的新提示或其他提交相关联的sha。如果你有:
1 2 3 4 5 | 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提供了一个新的选项
1 | git submodule update --rebase --remote |
将从每个子模块的上游获取最新的更改,重新调整它们的位置,并查看子模块的最新版本。正如文件所说:
--remote
This option is only valid for the update command. Instead of using the superproject’s recorded SHA-1 to update the submodule, use the status of the submodule’s remote-tracking branch.
这相当于在每个子模块中运行
(复制自此答案)