git子模块更新

dee*_*lue 233 git git-submodules

我不清楚以下是什么意思(来自git submodule update docs):

...将使子模块HEAD分离,除非--rebase--merge指定...

怎么--rebase/ --merge改变事情?

我的主要用例是有一堆中央存储库,我将通过子模块嵌入到其他存储库中.我希望能够改进这些中央回购,直接在他们的原始位置,或从他们的嵌入回购(通过子模块使用它们的那些).

  • 从这些子模块中,我可以创建分支/修改并使用推/拉,就像我在常规回购中一样,或者有什么需要谨慎的吗?
  • 我如何将子模块引用的提交从say(tagged)1.0提升到1.1(即使原始repo的头部已经是2.0),或者选择使用哪个分支的提交?

Von*_*onC 295

这个GitPro页面确实很好地总结了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
Run Code Online (Sandbox Code Playgroud)

见" git submodule update --remotevsgit pull ".

MindTooth答案说明了手动更新(没有本地配置):

git submodule -q foreach git pull -q origin master
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,这将改变子模块引用(gitlink,父repo索引中特殊条目),并且您将需要添加,提交和推送来自主 repo的所述引用.
下次您将克隆该父repo时,它将填充子模块以反映这些新的SHA1引用.

本答案的其余部分详细介绍了经典的子模块功能(引用固定提交,这是子模块概念背后的所有要点).


要避免此问题,请在使用git checkout -b work或等效工作的子模块目录中创建分支.当您第二次执行子模块更新时,它仍将恢复您的工作,但至少您有一个指针可以返回.

切换带有子模块的分支也很棘手.如果您创建一个新分支,在那里添加一个子模块,然后切换回没有该子模块的分支,您仍然将子模块目录作为未跟踪的目录:


那么,回答你的问题:

我可以创建分支/修改并使用推/拉,就像我在常规回购中一样,或者有什么需要谨慎的吗?

您可以创建分支并推送修改.

警告(来自Git子模块教程):在将更改发布(推送)到引用它的超级项目之前,始终发布(推送)子模块更改.如果您忘记发布子模块更改,则其他人将无法克隆存储库.

我如何将子模块引用的提交从say(tagged)1.0推进到1.1(即使原始repo的头部已经是2.0)

" 了解子模块 " 页面可以提供帮助

Git子模块使用两个移动部件实现:

  • .gitmodules文件
  • 一种特殊的树对象.

这些一起对特定存储库的特定修订进行三角测量,该存储库被检出到项目中的特定位置.


git子模块页面

您无法从主项目中修改子模块的内容

100%正确:您无法修改子模块,只能参考其中一个提交.

这就是为什么当您从主项目中修改子模块时,您:

  • 需要提交并推送的子模块(向上游模块),和
  • 然后进入你的主项目,然后重新提交(为了让主项目引用你刚创建和推送的新子模块提交)

子模块使您可以进行基于 组件的方法开发,其中主项目仅引用其他组件的特定提交(此处"声明为子模块的其他Git存储库").

子模块是另一个Git存储库的标记(提交),它不受主项目开发周期的约束:它("其他"Git存储库)可以独立发展.
主要项目取决于其他任何需要提交的回购.

但是,如果您想方便地直接从主项目修改其中一个子模块,Git允许您这样做,前提是您首先将这些子模块修改发布到其原始Git仓库,然后提交您的主项目引用所述子模块的版本.

但主要的想法仍然是:引用以下特定组件:

  • 有自己的生命周期
  • 有自己的标签集
  • 有自己的发展

您在主项目中引用的特定提交列表定义了您的配置(这就是Configuration Management的全部内容,仅仅是版本控制系统)

如果一个组件真的可以与你的主项目同时开发(因为对主项目的任何修改都涉及修改子目录,反之亦然),那么它将不再是一个"子模块",而是一个子树合并(也在将遗留代码库从cvs转移到分布式存储库的问题中提出),将两个Git 仓库的历史链接在一起.

这有助于理解Git子模块的真实性质吗?

  • 哇.对那些主要是那么简单的事情的解释应该足以吓唬任何一个新人只是坚持他们的svn:externals.;-) (71认同)
  • @conny:但是,正如我在"[为什么git子模块与svn externals不兼容?]中详细说明的那样?"(http://stackoverflow.com/questions/3131912/why-are-git-submodules-incompatible-with-svn-externals/ 3132221#3132221)",子模块*基本*不同,与`svn:externals`不兼容. (2认同)
  • 抱歉,为了回答我自己的问题,我将 cd'ing 收集到子模块中并 git checkout a sha,或者 git pull/fetch 就可以了。然后在本地存储库中提交更新。 (2认同)
  • @hced:你也可以使用`git submodule foreach`一次命中所有子模块 (2认同)
  • .. 仍然没有得到它。网上有没有更简单的解释? (2认同)
  • @IulianOnofrei 我编辑了答案以使该选项更加明显。 (2认同)
  • @IulianOnofrei 不,我不会删除那个答案!这个答案的重点是指出子模块实际上是什么。但是,是的,如果您在使用 git 命令后盲目地复制粘贴,而没有意识到自己在做什么,那么 MindTooh 的答案就是适合您的答案。 (2认同)

Min*_*oth 132

要更新每个子模块,可以调用以下命令.(根据回购.)

git submodule -q foreach git pull -q origin master
Run Code Online (Sandbox Code Playgroud)

您可以删除-q选项以遵循整个过程.

  • 如果您只是从根运行`git submodule update --init --recursive`,它将递归获取所有这些并初始化它们(如果它们尚未完成). (14认同)
  • @SamSoffes完全有不同的用途.更新子模块将检查它们当前**指向的提交的子模块(不一定是最新的提交).上述答案中的解决方案将每个子模块的提交更新为来自origin/master的最新HEAD. (10认同)
  • 我的新方法:`git submodule update --rebase --remote` (7认同)

rob*_*spb 19

要解决--rebase vs --merge选项:

假设您有超级回购A和子模块B,并希望在子模块B中做一些工作.您已完成作业并且在调用后知道

--rebase

你处于无HEAD状态,所以你在这一点上所做的任何提交很难回复.所以,你已经开始在子模块B中的新分支上工作了

cd B
git checkout -b bestIdeaForBEver
<do work>
Run Code Online (Sandbox Code Playgroud)

与此同时,项目A中的其他人已经确定最新和最好的B版本确实是应得的.出于习惯,您可以合并最近的更改并更新子模块.

<in A>
git merge develop
git submodule update
Run Code Online (Sandbox Code Playgroud)

哦,不!你又回到了无头状态,可能是因为B现在指向与B的新提示或其他提交相关联的SHA.如果只有你:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'
Run Code Online (Sandbox Code Playgroud)

现在,B的最佳创意已经重新定位到新的提交,更重要的是,你仍然在B的开发分支,而不是无头状态!

(--merge会将来自beforeUpdateSHA的更改合并到afterUpdateSHA到您的工作分支,而不是将更改重新定义到afterUpdateSHA.)


Iul*_*rei 5

Git 1.8.2提供了一个新选项--remote,可以实现这种行为.运行

git submodule update --rebase --remote
Run Code Online (Sandbox Code Playgroud)

将从每个子模块的上游获取最新的更改,将它们重新绑定,并检查子模块的最新版本.正如文档所说:

- 远程

此选项仅对update命令有效.不使用超级项目记录的SHA-1来更新子模块,而是使用子模块的远程跟踪分支的状态.

这相当于git pull在每个子模块中运行,这通常正是您想要的.

(从这个答案复制)

  • 我的意思是**它有效**而不是不起作用。相信我,如果更多的人看到这个答案,他们会很高兴,因为**它有效**。对于这样的事情,大多数人只想知道更新 git 子模块的命令,而不是它是如何实现的。 (3认同)
  • 这不是"又一个答案",因为*NO*其他答案都有这个命令(证明我错了).其他答案对我不起作用,这个*评论*没有,所以我决定将其作为答案发布,同时给予原始所有者信用.所以考虑删除你的downvote. (2认同)
  • 但您意识到,每个人都清楚,截至 2018 年,这是实现这一简单任务的正确命令,对吗? (2认同)
  • 几年后,查看这个评论线程 - 一个过度热心的 SO 编辑的完美例子。很高兴答案的OP为自己辩护。哇。 (2认同)

归档时间:

查看次数:

232830 次

最近记录:

6 年,2 月 前