如何查看git子模块指向哪个提交

gev0vcfq  于 2023-10-14  发布在  Git
关注(0)|答案(6)|浏览(128)

据我所知,如果你在git中添加一个子模块,那么主repo包含一个指向子模块的某个提交的指针。
有没有办法在不检查子模块代码的情况下,查看主代码库指向特定子模块的哪个提交?

7uhlpewt

7uhlpewt1#

正如其他答案所解释的,您可以使用两个命令:

  • git submodule status,或
  • git ls-tree HEAD,只取第二列为commit的行(如果你有awk,你可以使用git ls-tree HEAD | awk '$2 == "commit"')。

但是,这些命令给出的结果给予不同!

有什么区别?

  • git submodule status总是报告 * 当前 * 状态(顾名思义),即当前已 checkout 的提交。您在这里看到的散列与您进入子模块的目录1并检查最新提交(使用git loggit rev-parse HEAD)时看到的散列相同。
  • git ls-tree HEAD显示 * 目标 * 状态,不一定是当前状态。如果你想更新你的子模块,使它们对应于指定的版本,你必须使用git submodule update
    什么会导致当前状态和目标状态不同?

它们不同的典型情况是,当您git checkout另一个分支/标记/提交时,或者您使用git pull更新当前分支时。这两个命令都将导致HEAD更新到相应的提交。现在,如果这个提交指定你的子模块必须使用不同的版本,git submodule status仍然会显示旧版本,但是git ls-tree HEAD显示的目标已经是新版本了。

有没有更简单的方法来注意它们不同步?

检查git submodule status的输出。正如手册所解释的,如果在哈希之前有一个+,这意味着当前 checkout 的版本和目标版本是不同的。

如何使它们恢复同步?

运行git submodule update:新的子模块将被加载,并且两个命令将指示相同的提交。

示例

例如,假设在我们的repo中有一个名为base的子模块。
git submodule status的输出是(注意+):
+059ca6c4940813aa956e8668cb0af27efa189b22基础版(1.2版)
git ls-tree HEAD的输出是
提交fbc 447 ef 9468 def 36 cf 4089094 d 6960 cc 51618 b3基
正如我们所看到的,哈希是不同的。事实上,+已经通知了我们。
现在,如果我们输入git submodule update,它会说:
子模块路径'base':已 checkout 'fbc 447 ef 9468 def 36 cf 4089094 d 6960 cc 51618 b3'
现在我们可以使用的所有命令(base内部的git submodule statusgit ls-tree HEADgit log)都表示fbc447ef9468def36cf4089094d6960cc51618b3,在git submodule status的输出中,它前面没有+。如果我们再次运行git submodule update,什么也不会发生,因为一切都已经是最新的,甚至没有任何输出。
1:检查子模块的提交时必须小心,因为这很棘手:要查找子模块base中的最后一次提交,您不能使用git log base,您必须进入该目录(cd base),然后从那里运行git log。原因是第一个命令列出了“主”仓库的提交,这些提交设置了子模块的新版本,并且这些提交完全独立于子模块内部的提交。

t40tm48m

t40tm48m2#

一个更直接的命令是:
git submodule status

7tofc5zh

7tofc5zh3#

当然;有几种方法:

  1. git ls-tree <commit> <relative path to submodule>
  2. git ls-tree <commit>:<absolute path to parent of submodule>
  3. git ls-tree <commit>:./<relative path to parent of submodule>
  4. git ls-tree -r <commit> <relative path to parent of submodule>
    第一种方法对于检查单个子模块来说是最简单的。
    第二个/第三个是最简单的,如果你想检查同一个目录中包含的几个子模块,但你不想递归到任何其他不是子模块的子目录。(默认情况下,:语法使用存储库的顶层作为其引用点,而不是您当前的工作目录,因此如果您现在正在深入存储库,请确保包含./前缀。
    如果在一个目录中有很多子模块,并且只有子模块,那么第四种方法最简单。
    示例如下:
  • git ls-tree HEAD src/thirdparty/libfoo只显示子模块。
  • git ls-tree HEAD:src/thirdparty提供了src/thirdparty下面的所有内容,包括子模块src/thirdparty/libfoo
  • git ls-tree -r HEAD src/thirdparty提供了src/thirdparty下面的所有内容,包括子模块src/thirdparty/libfoo,但也会递归到src/thirdparty/docs,它实际上是repo中的一个常规目录。
  • git ls-tree -r HEAD列出了你的代码库中的所有内容,包括子模块。

子模块将显示为类型commit(而不是通常的blobtree)。

lx0bsm1f

lx0bsm1f4#

原谅我的潜伏,但我相信最初问题的答案可能是:

git submodule status --cached

“git submodule status”告诉你哪个提交被 checkout ,“--cached”告诉你哪个提交“git submodule update”会被 checkout 。
我不知道--cached是什么时候被添加到git的。

kkbh8khc

kkbh8khc5#

git ls-tree -r <submodule-commitID-of-interest> <submodule-path> | awk '{print $3}'

这里有一个bash行来打印子模块的repo commit ID,最后10个子模块的commit ID指向:

git --no-pager log -10 --pretty="%H" <submodule-path> | while read i; do git ls-tree -r $I <submodule-path> | awk '{print $3}'; done
u0njafvf

u0njafvf6#

accepted answer返回一个4列输出,其中包含子模块gitlink指向的提交。这对于验证所指向的路径确实是一个子模块很有用,例如当用户在脚本中提供输入时。为此,请验证第二列是否等于“commit“,例如:使用awk
但是,如果不需要此检查,则可以使用以下方法之一生成一个更简单的输出,该输出仅包含子模块提交,而没有其他内容:

git rev-parse HEAD:./<relative-path>
git rev-parse HEAD:<repository-path>

其中<relative-path>是子模块相对于shell工作目录的路径,<repository-path>是子模块相对于存储库根目录的路径。可以使用任何分支名称、提交散列或其他有效的修订描述(参见man git rev-parse)来代替HEAD

相关问题