简体   繁体   English

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

[英]How to see which commit a git submodule points at

As far as I understand, if you add a submodule in git then, the main repo contains a pointer to a certain commit of the submodule.据我了解,如果你在 git 中添加一个子模块,那么主仓库包含一个指向子模块某个提交的指针。

Is there any way to see to which commit the main repo points at for a specific submodule, without checking out the code of the submodule?有没有办法查看特定子模块的主仓库指向哪个提交,而不检查子模块的代码?

As the other answers explain, you can use two commands:正如其他答案所解释的,您可以使用两个命令:

  • git submodule status , or git submodule status ,或
  • git ls-tree HEAD , taking only the lines where the second column is commit (if you have awk you can use git ls-tree HEAD | awk '$2 == "commit"' ). git ls-tree HEAD ,只取第二列commit的行(如果你有 awk,你可以使用git ls-tree HEAD | awk '$2 == "commit"' )。

However, these commands give different results!但是,这些命令给出不同的结果!

What's the difference?有什么不同?

  • git submodule status always reports the current status (as the name suggests), that is, the commit that is currently checked-out. git submodule status总是报告当前状态(顾名思义),即当前签出的提交。 The hash that you see here is the same that you'd see by going into the submodule's directory 1 and checking the latest commit (with git log or git rev-parse HEAD )您在此处看到的哈希与您通过进入子模块的目录1并检查最新提交(使用git loggit rev-parse HEAD )看到的相同
  • git ls-tree HEAD shows the target status , which is not necessarily the current one. git ls-tree HEAD显示目标状态,不一定是当前状态。 If you want to update your submodules so that they correspond to the specified version, you have to use git submodule update .如果要更新子模块以使其与指定版本相对应,则必须使用git submodule update

What can cause the current and target status to differ?什么会导致当前状态和目标状态不同?

The typical situation in which they differ is when you git checkout another branch/tag/commit, or you use git pull to update your current branch.它们不同的典型情况是当您git checkout另一个分支/标签/提交时,或者您使用git pull来更新您当前的分支。 Both these commands will cause HEAD to be updated to the corresponding commit.这两个命令都会导致HEAD更新为相应的提交。 Now, if this commit specifies that your submodule has to use a different version, git submodule status will still show the old one, but the target shown by git ls-tree HEAD will already be the new one.现在,如果此提交指定您的子模块必须使用不同的版本, git submodule status仍将显示旧版本,但git ls-tree HEAD显示的目标已经是新版本。

Is there a simpler way of noticing that they are out of sync?有没有更简单的方法来注意到它们不同步?

Check the output of git submodule status .检查git submodule status的输出。 As the manual explains , if there's a + before the hash, it means that the currently checked-out version and the target one are different. 正如手册所解释的那样,如果哈希之前有一个+ ,则表示当前签出的版本和目标版本不同。

How do I bring them back in sync?如何使它们恢复同步?

By running git submodule update : the new submodule will be loaded, and both commands will indicate the same commit.通过运行git submodule update :将加载新的子模块,并且两个命令将指示相同的提交。

Example例子

For example, let's say that in our repo we have a submodule called base .例如,假设在我们的 repo 中有一个名为base的子模块。
The output of git submodule status is (notice the + ): git submodule status的输出是(注意+ ):

+059ca6c4940813aa956e8668cb0af27efa189b22 base (release-1.2) +059ca6c4940813aa956e8668cb0af27efa189b22 基础(1.2 版)

And the output of git ls-tree HEAD is git ls-tree HEAD的输出是

160000 commit fbc447ef9468def36cf4089094d6960cc51618b3 base 160000 提交 fbc447ef9468def36cf4089094d6960cc51618b3 基础

As we can see, the hashes are different.正如我们所看到的,哈希值是不同的。 In fact, the + had already informed us.事实上, +已经通知我们了。

Now, if we type git submodule update , it says:现在,如果我们输入git submodule update ,它会说:

Submodule path 'base': checked out 'fbc447ef9468def36cf4089094d6960cc51618b3'子模块路径'base':签出'fbc447ef9468def36cf4089094d6960cc51618b3'

And now all the commands we can use ( git submodule status , git ls-tree HEAD , and git log from inside base ) indicate fbc447ef9468def36cf4089094d6960cc51618b3 , and there's no + in front of it in the output of git submodule status .现在我们可以使用的所有命令( git submodule statusgit ls-tree HEADgit log from inside base )都表示fbc447ef9468def36cf4089094d6960cc51618b3 ,并且在git submodule status的输出中前面没有+ If we run git submodule update again, nothing happens, as everything is already up to date, and there isn't even any output.如果我们再次运行git submodule update ,什么都不会发生,因为一切都已经是最新的,甚至没有任何输出。


1 : You have to be careful when you check the commit of a submodule, because it's tricky: to find the last commit that was made in submodule base you can't use git log base , you have to enter that directory ( cd base ) and then run git log from there. 1 :检查子模块的提交时必须小心,因为它很棘手:要找到在子模块base中进行的最后一次提交,您不能使用git log base ,您必须进入该目录( cd base )然后从那里运行git log The reason is that the first command lists the commits of the "main" repository which set a new version of the submodule, and these commits are completely independent from those that were made inside the submodule.原因是第一个命令列出了设置子模块新版本的“主”存储库的提交,这些提交完全独立于子模块内部的提交。

更直接的命令是:

git submodule status

Sure;当然; there are several ways:有几种方法:

  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>

The first is easiest by far for checking a single submodule.第一个是迄今为止检查单个子模块最简单的方法。

The second/third is easiest if you want to check several submodules contained in the same directory, but you don't want to recurse into any other subdirectories that are not submodules.如果要检查同一目录中包含的多个子模块,第二个/第三个是最简单的,但您不想递归到任何其他不是子模块的子目录。 (The : syntax uses the top level of the repository as its reference point by default, rather than your current working directory, so be sure to include the ./ prefix if you're way in the depths of your repo right now.) :语法默认使用存储库的顶层作为其参考点,而不是您当前的工作目录,因此如果您现在正处于 repo 的深处,请务必包含./前缀。)

The fourth is easiest if you have a lot of submodules, and only submodules, in a single directory.如果您在一个目录中有很多子模块,并且只有子模块,那么第四个是最简单的。

Examples:例子:

  • git ls-tree HEAD src/thirdparty/libfoo shows the submodule and nothing else. git ls-tree HEAD src/thirdparty/libfoo显示子模块,仅此而已。
  • git ls-tree HEAD:src/thirdparty gives you everything directly below src/thirdparty , including your submodule src/thirdparty/libfoo . git ls-tree HEAD:src/thirdparty为您提供src/thirdparty /thirdparty 正下方的所有内容,包括您的子模块src/thirdparty/libfoo
  • git ls-tree -r HEAD src/thirdparty gives you everything directly below src/thirdparty , including your submodule src/thirdparty/libfoo , but will also recurse into src/thirdparty/docs which is actually a regular directory in your repo. git ls-tree -r HEAD src/thirdparty为您提供src/thirdparty /thirdparty 正下方的所有内容,包括您的子模块src/thirdparty/libfoo ,但也会递归到src/thirdparty/docs这实际上是您的回购中的常规目录。
  • git ls-tree -r HEAD lists absolutely everything in your repo, including submodules. git ls-tree -r HEAD绝对列出你的 repo 中的所有内容,包括子模块。

Submodules will show up as type commit (as opposed to the usual blob or tree ).子模块将显示为类型commit (而不是通常的blobtree )。

Pardon for lurking, but I believe the answer to the original question is likely to be:请原谅潜伏,但我相信原始问题的答案很可能是:

git submodule status --cached

"git submodule status" tells you which commit is checked out "--cached" tells you which commit a "git submodule update" would checkout. “git submodule status”告诉你哪个提交被签出“--cached”告诉你哪个提交“git submodule update”会签出。

I'm not sure when --cached was added to git.我不确定 --cached 何时添加到 git。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM