【问题标题】:How to see which commit a git submodule points at如何查看 git 子模块指向哪个提交
【发布时间】:2014-01-06 10:48:00
【问题描述】:

据我所知,如果您在 git 中添加一个子模块,那么它会指向该子模块中的某个提交。

有什么方法可以在不检查的情况下查看子模块指向的提交?

【问题讨论】:

    标签: git git-submodules git-commit


    【解决方案1】:

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

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

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

    有什么区别?

    • git submodule status 总是报告当前状态(顾名思义),即当前签出的提交。您在此处看到的哈希与您通过进入子模块的目录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 的输出。 As the manual explains,如果hash前有+,表示当前签出的版本和目标版本不同。

    如何使它们重新同步?

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

    示例

    例如,假设在我们的 repo 中有一个名为 base 的子模块。
    git submodule status 的输出是(注意+):

    +059ca6c4940813aa956e8668cb0af27efa189b22 基础(1.2 版)

    git ls-tree HEAD 的输出是

    160000 提交 fbc447ef9468def36cf4089094d6960cc51618b3 基数

    正如我们所见,哈希值是不同的。其实+已经通知我们了。

    现在,如果我们输入git submodule update,它会说:

    子模块路径'base':签出'fbc447ef9468def36cf4089094d6960cc51618b3'

    现在我们可以使用的所有命令(git submodule statusgit ls-tree HEADgit log 从内部 base)都指示 fbc447ef9468def36cf4089094d6960cc51618b3,并且在 @ 的输出中它前面没有 + 987654351@。如果我们再次运行git submodule update,什么都不会发生,因为一切都已经是最新的,甚至没有任何输出。


    1:检查子模块的提交时必须小心,因为这很棘手:要找到在子模块base 中进行的最后一次提交,您不能使用@987654354 @,你必须进入那个目录(cd base)然后从那里运行git log。原因是第一个命令列出了设置新版本子模块的“主”存储库的提交,这些提交完全独立于子模块内部的提交。

    【讨论】:

      【解决方案2】:

      更直接的命令是:

      git submodule status

      【讨论】:

      • 这很好,如果您有多个子模块,则需要很长时间
      • @Ivan 我应该将多少个视为“几个”? 10?只是好奇。
      • @antonimmo 当然,它还取决于每个子模块的大小以及我猜你拥有的 kin dof 计算机。就我而言,我有 15 个 100MB 左右的子模块(~7000 个文件)。最多可能需要 2 分钟。
      • 嗯,我没有考虑 repo 大小,但这是有道理的。
      【解决方案3】:

      当然;有几种方法:

      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>

      第一个是迄今为止检查单个子模块最简单的方法。

      如果您想检查同一目录中包含的多个子模块,第二个/第三个是最简单的,但您不想递归到任何其他不是子模块的子目录。 (: 语法默认使用存储库的顶层作为其参考点,而不是您当前的工作目录,因此如果您现在正处于 repo 的深处,请务必包含 ./ 前缀.)

      如果您在一个目录中有很多子模块,并且只有子模块,则第四个最简单。

      例子:

      • 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,这实际上是您回购中的常规目录。
      • git ls-tree -r HEAD 绝对列出了您的 repo 中的所有内容,包括子模块。

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

      【讨论】:

      • 这似乎不起作用(不再起作用了?)。我做了git ls-tree HEAD:some/path(其中一些/路径是一个子模块)并且git输出fatal: not a tree object。我正在使用 git 2.25.0。
      • @mic 你需要使用some,然后。我想我的例子有点难读,但想法是列出子模块的父模块,而不是子模块本身。
      • @mic git ls-tree -r HEAD | grep commit 一点解决办法
      • git ls-tree master <path> 使用 git 2.25.0 为我工作
      • @mic,正如 SColvin 所说——我认为它不再需要冒号
      【解决方案4】:
      git ls-tree -r <submodule-commitID-of-interest> <submodule-path> | awk '{print $3}'
      

      这里有一个bash 行打印子模块的 repo 提交 ID,最后 10 个子模块的提交 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-20
        • 2021-09-21
        • 2012-06-06
        • 2011-06-29
        • 2021-12-07
        • 2010-12-24
        • 2016-09-01
        • 1970-01-01
        相关资源
        最近更新 更多