git索引包含什么?

时间:2010-11-03 07:20:43

标签: git internal

Git索引究竟包含什么,以及我可以使用什么命令来查看索引的内容?


更新

感谢您的所有答案。我知道索引充当临时区域,提交的内容是索引而不是工作树。我只是对索引对象的内容感到好奇。我想它可能是文件名/目录名列表,SHA-1对,也许是一种虚拟树?

在Git术语中,是否有任何 plumbing 命令可以用来列出索引的内容?

7 个答案:

答案 0 :(得分:142)

Git书中有一篇关于what an index includes的文章:

  

索引是一个二进制文件(通常保存在.git/index中),其中包含一个排序的路径名列表,每个路径名都有权限和blob对象的SHA1; git ls-files可以显示索引的内容:

$ git ls-files --stage
100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0   .gitignore
100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0   .mailmap

Racy git problem提供了有关该结构的更多详细信息:

  

索引是git中最重要的数据结构之一   它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作写入要提交的下一个树对象的临时区域。
  从某种意义上讲,状态是“虚拟的”,它不一定必须与工作树中的文件匹配,而且往往不匹配。


要了解更多信息,请参阅“git/git/Documentation/technical/index-format.txt”:

Git索引文件具有以下格式

  

所有二进制数均按网络字节顺序排列   除非另有说明,否则此处描述版本2

     
      
  • 一个12字节的标头,包括:      
        
    • 4字节签名
        签名为{“D”,“I”,“R”,“C”}(代表“ dircache “)
    •   
    • 4字节版本号
        目前支持的版本是2,3和4。
    •   
    • 32位索引条目数。
    •   
  •   
  • 许多已排序的 index entries
  •   
  • 扩展程序
      扩展名通过签名确定   如果Git不理解它们,可以忽略可选扩展   Git目前支持缓存树并解析撤消扩展。      
        
    • 4字节扩展签名。如果第一个字节为“A”..“Z”,则扩展名是可选的,可以忽略。
    •   
    • 扩展名的32位大小
    •   
    • 扩展数据
    •   
  •   
  • 在此校验和之前的索引文件内容上的160位SHA-1。
  •   

mljrg comments

  

如果索引是准备下一次提交的地方,为什么“git ls-files -s”在提交后不返回任何内容?

因为索引表示正在跟踪的内容,并且在提交之后,正在跟踪的内容与上次提交相同(git diff --cached不返回任何内容)。

所以git ls-files -s列出了所有跟踪的文件(输出中的对象名,模式位和阶段号)。

该列表(被跟踪的元素)使用提交的内容进行初始化 切换分支时,索引内容将重置为刚刚切换到的分支所引用的提交。


Git 2.20(2018年第4季度)增加索引条目抵销表(IEOT)

commit 77ff112commit 3255089commit abb4bb8commit c780b9ccommit 3b1d9e0commit 371ed0dBen Peart (benpeart)(2018年10月10日) 。
commit 252d079查看Nguyễn Thái Ngọc Duy (pclouds)(2018年9月26日) (由Junio C Hamano -- gitster --合并于commit e27bfaa,2018年10月19日)

  

ieot:添加索引条目偏移表(IEOT)扩展名

     

此补丁可以通过添加来解决加载索引的CPU成本问题   索引的其他数据将使我们能够有效地多   线程加载和转换缓存条目。

     

它通过添加一个(可选)索引扩展来实现这一点   索引文件中缓存条目块的偏移表。

     

为了使这个工作适用于V4索引,在写入缓存条目时,它会通过对当前条目进行编码来定期“重置”前缀压缩,就好像前一个条目的路径名完全不同并保存   IEOT中该条目的偏移量   基本上,对于V4索引,它会生成前缀压缩条目块的偏移量。

使用new index.threads config setting,索引加载现在更快。

答案 1 :(得分:58)

逐位分析

我决定做一些测试,以便更好地理解格式并更详细地研究一些领域。

对于Git版本1.8.5.22.3,结果如下:

我已经标记了我不确定/找不到TODO的点数:请随意补充这些点。

正如其他人所提到的,索引存储在.git/index下,而不是标准树对象,其格式为二进制,并记录在:https://github.com/git/git/blob/master/Documentation/technical/index-format.txt

定义索引的主要结构位于cache.h,因为索引是用于创建提交的缓存。

设置

当我们用:

启动测试存储库时
git init
echo a > b
git add b
tree --charset=ascii

.git目录如下所示:

.git/objects/
|-- 78
|   `-- 981922613b2afb6025042ff6bd878ac1994e85
|-- info
`-- pack

如果我们得到唯一对象的内容:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

我们得到a。这表明:

  • index指向文件内容,因为git add b创建了一个blob对象
  • 它将元数据存储在索引文件中,而不是存储在树对象中,因为只有一个对象:blob(在常规Git对象上,blob元数据存储在树上)

高清分析

现在让我们看一下索引本身:

hd .git/index

给出:

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 09 76 e6  |DIRC.... ....T.v.|
00000010  1d 81 6f c6 54 09 76 e6  1d 81 6f c6 00 00 08 05  |..o.T.v. ..o.....|
00000020  00 e4 2e 76 00 00 81 a4  00 00 03 e8 00 00 03 e8  |...v.... ........|
00000030  00 00 00 02 78 98 19 22  61 3b 2a fb 60 25 04 2f  |....x.." a;*.`%./|
00000040  f6 bd 87 8a c1 99 4e 85  00 01 62 00 ee 33 c0 3a  |......N. ..b..3.:|
00000050  be 41 4b 1f d7 1d 33 a9  da d4 93 9a 09 ab 49 94  |.AK...3. ......I.|
00000060

接下来我们将得出结论:

  | 0           | 4            | 8           | C              |
  |-------------|--------------|-------------|----------------|
0 | DIRC        | Version      | File count  | ctime       ...| 0
  | ...         | mtime                      | device         |
2 | inode       | mode         | UID         | GID            | 2
  | File size   | Entry SHA-1                              ...|
4 | ...                        | Flags       | Index SHA-1 ...| 4
  | ...                                                       |

首先是标题,定义于:struct cache_header

  • 44 49 52 43DIRC。 TODO:为什么这有必要?

  • 00 00 00 02:格式版本:2。索引格式随着时间的推移而发展。目前存在最多4个版本。在GitHub上的不同计算机之间进行协作时,索引的格式不应该是一个问题,因为裸存储库不存储索引:它是在克隆时生成的。

  • 00 00 00 01:索引上的文件数:只有一个b

接下来启动由struct cache_entry定义的索引条目列表。这里我们只有一个。它包含:

  • 一堆文件元数据:8字节ctime,8字节mtime,然后是4字节:设备,inode,模式,UID和GID。

    请注意:

      由于我们尚未修改文件,
    • ctimemtime与预期相同(54 09 76 e6 1d 81 6f c6

      第一个字节是EPOCH以十六进制为单位的秒数:

      date --date="@$(printf "%x" "540976e6")"
      

      给出:

      Fri Sep  5 10:40:06 CEST 2014
      

      这是我做这个例子的时候。

      第二个4个字节是纳秒。

    • UID和GID为00 00 03 e8,十六进制为1000:单用户设置的常用值。

    所有这些元数据(大部分都不存在于树对象中)允许Git检查文件是否快速更改而不比较整个内容。

  • 在行30的开头:00 00 00 02:文件大小:2个字节(a的{​​{1}}和\n

  • echo:对条目的先前内容的20字节SHA-1。请注意,根据my experiments with the assume valid flag,此SHA-1中不考虑其后面的标记。

  • 2字节标志:78 98 19 22 ... c1 99 4e 85

    • 1位:假设有效标志。我的调查表明,这个命名不佳的标志是00 01存储其状态的地方:https://stackoverflow.com/a/28657085/895245

    • 1位扩展标志。确定是否存在扩展标志。 对于没有扩展标志的版本2,必须是git update-index --assume-unchanged

    • 合并期间使用的2位阶段标志。阶段记录在0

      • man git-merge:常规文件,不在合并冲突中
      • 0:base
      • 1:我们的
      • 2:他们的

      在合并冲突期间,1-3中的所有阶段都存储在索引中 允许3等操作。

      如果您git checkout --ours,则将阶段0添加到路径的索引中, 而且Git会知道冲突已被标记为已解决。 TODO:检查一下。

    • 将跟随的路径的12位长度:git add:仅限1个字节,因为路径为0 01

  • 2字节扩展标志。只有在"扩展标志"被设置在基本旗帜上。 TODO。

  • b(ASCII 62):可变长度路径。在前面的标志中确定的长度,这里只有1个字节,b

然后是b:1-8个字节的零填充,这样路径将以空值终止,索引将以8个字节的倍数结束。这只发生在索引版本4之前。

没有使用扩展程序。 Git知道这一点,因为文件中没有足够的空间用于校验和。

最后,对索引的内容有一个20字节的校验和00

答案 2 :(得分:12)

Git索引是工作目录和存储库之间的暂存区域。您可以使用索引构建一组要一起提交的更改。创建提交时,提交的内容是此索引中当前的内容,而不是工作目录中的内容。

要查看索引中的内容,请发出命令:

git status

当您运行git status时,您可以看到哪些文件已暂存(当前在您的索引中),哪些文件已修改但尚未暂存,哪些文档完全未跟踪。

您可以阅读this。谷歌搜索引发了许多链接,这应该是相当自给自足的。

答案 3 :(得分:0)

这正是您真正需要的,请使用此命令。

$ binwalk索引

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1717          0x6B5           Unix path: /company/user/user/delete.php
1813          0x715           Unix path: /company/user/user/get.php
1909          0x775           Unix path: /company/user/user/post.php
2005          0x7D5           Unix path: /company/user/user/put.php
3373          0xD2D           Unix path: /urban-airship/channel/channel/post.php
3789          0xECD           Unix path: /urban-airship/named-user/named-user/post.php
3901          0xF3D           Unix path: /user/categories/categories/delete.php
4005          0xFA5           Unix path: /user/categories/categories/get.php
4109          0x100D          Unix path: /user/categories/categories/put.php
4309          0x10D5          Unix path: /user/favorites/favorites/delete.php

答案 4 :(得分:0)

Git索引是一个二进制文件(通常保存在.git/index中),其中包含路径名称的排序列表,每个路径名称均具有权限和blob对象的SHA1;

git ls-files可以向您显示索引的内容。请注意,单词indexstagecache在Git中是同一回事:它们可以互换使用。

enter image description here

Git索引或Git缓存具有3个重要属性:

  1. 索引包含生成单个(唯一确定的)树对象所需的所有信息。
  2. 索引使它定义的树对象与工作树之间可以进行快速比较。
  3. 它可以有效地表示有关不同树对象之间的合并冲突的信息,允许将每个路径名与有关所涉及树的足够信息相关联,从而可以在它们之间创建三向合并。

来源

  1. https://mincong.io/2018/04/28/git-index/
  2. https://medium.com/hackernoon/understanding-git-index-4821a0765cf

答案 5 :(得分:0)

响应@ ciro-santilli-%e9%83%9d%e6%b5%b7%e4%b8%9c%e5%86%a0%e7%8a%b6%e7%97%85%e5% 85%ad%e5%9b%9b%e4%ba%8b%e4%bb%b6%e6%b3%95%e8%bd%ae%e5%8a%9f详细深入查看该指数,分享 TODO 之一的输出。

“如果您使用git add,则将阶段0添加到该路径的索引中,Git会知道该冲突已被标记为已解决。TODO:检查此。”

,更具体地说,是不同的合并阶段。

  • 0:常规文件,不存在合并冲突
  • 1:基础
  • 2:我们的
  • 3:他们的

有关各个阶段的数字表示的详细信息,在这种情况下为冲突文件。

$ git ls-files -s
100644 f72d68f0d10f6efdb8adc8553a1df9c0444a0bec 0       vars/buildComponent.groovy

$ git stash list
stash@{0}: WIP on master: c40172e turn off notifications, temporarily

$ git stash apply
Auto-merging vars/commonUtils.groovy
Auto-merging vars/buildComponent.groovy
CONFLICT (content): Merge conflict in vars/buildComponent.groovy

$ git ls-files -s
100644 bc48727339d36f5d54e14081f8357a0168f4c665 1       vars/buildComponent.groovy
100644 f72d68f0d10f6efdb8adc8553a1df9c0444a0bec 2       vars/buildComponent.groovy
100644 24dd5be1783633bbb049b35fc01e8e88facb20e2 3       vars/buildComponent.groovy

答案 6 :(得分:0)

只是想把 git ls-tree 放在戒指中。

<块引用>

索引是git中最重要的数据结构之一。
它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作写出下一个要提交的树对象的暂存区。
状态是“虚拟的”,因为它不一定必须,而且通常不匹配工作树中的文件。

如果我签出一个特殊的提交,git ls-tree 告诉我应该存在哪些工作文件/对象是真的吗?在 ls-tree 的上下文中我们说的是哪种树?

示例

git ls-tree -r -l HEAD
git ls-tree -r -l commit-hash

顺便说一句:ls-tree 也适用于未经检出 (-n) 克隆的存储库,其中 ls-files 不返回任何内容。

https://stackoverflow.com/a/56242906/2623045

https://stackoverflow.com/a/67567058/2623045