Git子模块中gitlink条目的位置在哪里?

5

我该在哪里查看gitsubmodules(7)中提到的gitlink项?

对于工作目录位于path/to/bar/的子模块,gitlink条目应位于/path/to/bar并包含子模块提交的SHA-1散列值?

$ git submodule status
 139dedcb98fca8fb69d70305709783ff40316cd4 tabulous (0.5.0-2-g139dedc)
 24afe922e6a05891756ecf331f39a1f6743d3d5a vim-repeat (v1.2-9-g24afe92)
 f51a26d3710629d031806305b6c8727189cd1935 vim-surround (v2.1-18-gf51a26d)
$ ls -la tabulous/
total 72
drwxr-xr-x  8 nlykkei  staff   256B Apr  5 17:25 ./
drwxr-xr-x  5 nlykkei  staff   160B Apr  4 12:00 ../
-rw-r--r--  1 nlykkei  staff    67B Apr  4 12:00 .git
-rw-r--r--  1 nlykkei  staff    21B Apr  4 12:00 .gitignore
-rw-r--r--  1 nlykkei  staff    18K Apr  4 12:00 LICENSE
-rw-r--r--  1 nlykkei  staff   5.0K Apr  5 17:25 README.md
drwxr-xr-x  4 nlykkei  staff   128B Apr  5 17:25 doc/
drwxr-xr-x  3 nlykkei  staff    96B Apr  5 17:25 plugin/
$ cat tabulous/.git
gitdir: ../../../../../.git/modules/vim/pack/bundle/start/tabulous

man 7 gitsubmodules:

   ...
   Assuming the submodule has a Git directory at $GIT_DIR/modules/foo/ and a working directory at path/to/bar/, the superproject tracks the submodule via a gitlink entry in
   the tree at path/to/bar and an entry in its .gitmodules file (see gitmodules(5)) of the form submodule.foo.path = path/to/bar.

   The gitlink entry contains the object name of the commit that the superproject expects the submodule's working directory to be at.
2个回答

4

Git以相同的方式记录添加的子模块内容的提交ID和添加的文件内容的blob ID,作为ID列在索引或记录树中。这就是一个gitlink:你的内容在另一个提交中,如果需要,你可以在该路径上检出它。 git submodule 助手命令帮助你查找和管理具有该提交的存储库,但它只是一些辅助命令,方便你使用一到五行代码完成的任务。

git rev-parse @:tabulous      # HEAD commit entry: "the current checkout had this here"
git rev-parse :tabulous       # index entry, "last thing added or checked out here"

git -C tabulous rev-parse HEAD   # what's actually checked out here

当然,您可以按照通常的方式进行任何进一步的检查。对于已跟踪内容的低级版本如下:

git -C tabulous diff-index --quiet --cached @ || echo staged changes in tabulous
git -C tabulous diff-files -q                 || echo unstaged changes in tabulous

我不知道有一个快速的“检查所有未跟踪内容”的单个命令,我认为您仍然需要使用ls-files和一些支架来实现,例如:
stdbuf -oL git -C tabulous git ls-files --exclude-standard -o  | grep -q . \
&& echo untracked, unignored files in tabulous

stdbuf -oL git -C tabulous git ls-files --exclude-standard -oi | grep -q . \
&& echo untracked, ignored files in tabulous

(stdbuf -oL 部分只在非常大的工作树中才有意义,在这种情况下,值得花费击键来避免查找整个缓冲区的名称)

请注意,单独的目录存在于对象数据库中,但不存在于索引中,每当它们包含的任何内容发生更改时,都会写入新的目录对象,这就是索引的作用之一,即避免为每个更改分散新的目录树,但在编写脚本时要保持警觉:如果你的例子中的 "tabulous" 只是一个目录而不是子模块,则它将没有自己的索引条目(因为保持该 ID 最新的更新将是索引存在的无谓开销之一)。


谢谢。文档中说“在path/to/bar路径下的树中有一个gitlink条目”是错误的吗?您对gitlink的解释与此不同。 - Shuzheng
考虑 git ls-tree -rd 的输出:160000 commit 139dedcb98fca8fb69d70305709783ff40316cd4 vim/pack/bundle/start/tabulous。 "commit" 是 "submodule" 的同义词吗?即 git 知道对象 ID 引用了一个子模块,因为它的类型是 "commit"(或者 "commit" 还可以表示其他东西,而不是 "submodule" 吗?) - Shuzheng
无论你如何称呼它,或者是否使用 git submodule 助手都没有关系。该条目是一个提交 ID。这就是 "gitlink" 的含义:一个保存提交 ID 而不是 blob 或嵌套树 ID 的条目。但它仍然是为该路径记录的 ID。这是应该存在的,以使工作树与提交的内容匹配。 - jthill

0

虽然已经过去了一年半,但我碰巧能够回答这个问题 :)

什么是gitlink条目?

基本上,它是超级项目记住子模块提交的记录。

gitlink条目在哪里?

DESCRIPTION:

超级项目通过路径/to/bar的树中的gitlink条目跟踪子模块

它是一个条目,字面意思是列表中的一个项目。

因此,上述提到的tree是超级项目的tree,其中包含gitlink条目。

在Git中,tree是目录的快照(也称为列表)。

查找gitlink条目的简单实验

➜  hustnzj git init super
Initialized empty Git repository in /hustnzj/super/.git/
➜  hustnzj cd super
➜  super git:(main) git init sub
Initialized empty Git repository in /hustnzj/super/sub/.git/
➜  super git:(main) ✗ cd sub
➜  sub git:(main) touch 1
➜  sub git:(main) ✗ git add 1
➜  sub git:(main) ✗ git commit -m 'first'
[main (root-commit) a1a76ac] first
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1
➜  sub git:(main) ..
➜  super git:(main) ✗ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    sub/

nothing added to commit but untracked files present (use "git add" to track)
➜  super git:(main) ✗ git submodule add ./sub sub
Adding existing repo at 'sub' to the index
➜  super git:(main) ✗ git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   .gitmodules
    new file:   sub

➜  super git:(main) ✗ git commit -m 'add submodule'
[main (root-commit) d48efa0] add submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 sub
➜  super git:(main) git cat-file commit main
tree 32d1e97cda3fc75ad358b18a7c938fccc3be2a88
author hustnzj hustnzj@example.com 1663992891 +0800
committer hustnzj hustnzj@example.com 1663992891 +0800

add submodule
➜  super git:(main) git ls-tree 32d1e97
100644 blob c489803d5bdec1755f650854fe7ef5ab7a3ee58d    .gitmodules
160000 commit a1a76ac0bc49478d5bce1b1b598dc6c290c28003  sub

请注意sub条目的160000模式。这是Git中的一种特殊模式,基本上意味着您正在将提交记录为目录条目而不是子目录或文件。
要检查a1a76ac0bc49478d5bce1b1b598dc6c290c28003提交是否为sub子模块的提交:
super git:(main) git -C sub rev-parse HEAD
a1a76ac0bc49478d5bce1b1b598dc6c290c28003

如果你在将子模块添加到超级项目中时注意输出,你应该会看到160000模式。

你可以在这里找到对160000的清晰解释。

160000:Git链接,对象的SHA-1指向另一个存储库中的提交。Git链接只能通过SHA或提交标记来指定。它们用于实现子模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接