git 子模块有 "new commits" 当我结帐 master

git submodule has "new commits" when I checkout master

我有一个名为 Helpers 的子模块。当我使用 --recursive 克隆我的主项目时,Helpers 子模块处于分离头状态(正如所有教程所说的那样)。如果我现在 'git status' 在主项目目录中,一切都是干净的。如果我 'cd Helpers; git checkout master',除了我现在在一个我可以承诺的命名分支上,我不希望有任何改变。但是,如果我 'cd ..; git status' 不做任何其他事情,我会看到

 modified:   Helpers (new commits)

为什么它认为有新的提交?子模块应该仍处于更新时的同一点(在本例中为克隆),不是吗?

如果您的子模块的 HEAD 与父存储库索引中指定的提交不匹配,那么 git 会给您 "new commits" 消息。您可以通过 运行 git ls-tree:

检查索引中指定了哪个提交
$ git ls-tree master:<path_to_folder_containing_my_submodule>
160000 commit ba9d11670daf5109a52e5a2b01bca8a344897338  my_submodule

当您执行递归 git 克隆时,git 将获取最新的,然后将 HEAD 指向指定的提交。如果指定的提交与远程 master 中的最新提交不匹配,则克隆时 master 将不等于 HEAD

执行递归克隆后检查的另一种方法是 cd 进入子模块,然后使用 git log:

$ git log --decorate --all
commit 6a75034cc78fc637e2437bba9f5834835f56bd8f (origin/master, origin/HEAD, master)
...
commit ba9d11670daf5109a52e5a2b01bca8a344897338 (HEAD)

如果 HEADmaster 指向相同的提交,那么您可以检出 master 并且您不会在父仓库中看到 "new commits" 消息。

可能发生的情况是您的子模块的 master 不是您持有的仓库想要的版本。

将你的子模块设置为持有仓库想要的版本:

holding/ $ git submodule update

检查子模块所需的 SHA1:

holding/ $ git submodule        # (1)
<list of all submodules, with the desired SHA1>

检查你的子模块的 master 是什么:

holding/ $ cd sub
holding/sub $ git checkout master
holding/sub $ git log -1     # (2)

(2)处的SHA1和你在(1)处看到的一样吗?如果没有,那是你的问题。子模块的 master 发生了一些变化,但是这些新的变化没有包含在 holding repo 中。

holding repo 保留 SHA1 作为要使用的子模块版本的参考。如果子模块的仓库有进一步的开发,持有的仓库仍然保持相同的版本,它不会自动更新子模块。

如果你签出子模块的更新版本(例如 master)然后返回到持有仓库,git status 会告诉你你已经签出子模块中的新提交.当前子模块提交的 更改 可以在您的控股仓库中提交。这将更新哪个版本的子模块将与此持有提交一起使用。


如果你想继续在子模块上工作,从持有仓库想要的版本开始,你将需要创建一个新分支。 master 反映子模块回购中的进一步发展,因此您要么从 master 开始工作(并包括此进一步发展和您的新工作),要么从 holding 所指的分离头创建一个新分支.

如果您要通过保持在分离头上强制执行 master,那么在分离头和 master 之间创建的提交(进一步开发)会发生什么情况?他们会迷路的。下次将移动的 master 推到 origin 时会发生什么?会发生冲突,因为您的本地 master 会与 origin 不同。