Git索引到底包含什么,我可以使用什么命令来查看索引的内容?谢谢你的回答。我知道索引充当暂存区,提交的内容在索引中而不是工作树中。我只是好奇索引对象是由什么组成的。我猜它可能是一个文件名/目录名列表,SHA-1对,一种虚拟树?在Git术语中,有没有任何 plumbing 命令可以用来列出索引的内容?
nhn9ugyo1#
Git手册中有一篇关于what an index includes的文章:索引是一个二进制文件(通常保存在.git/index中),其中包含路径名的排序列表,每个路径名都有权限和blob对象的SHA1; git ls-files可以显示索引的内容:
.git/index
git ls-files
$ git ls-files --stage 100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0 .gitignore 100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0 .mailmap
Racy git problem给出了该结构的更多细节:索引是git中最重要的数据结构之一。它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作暂存区以写出要提交的下一个树对象。状态是“虚拟的”,在这个意义上,它不一定必须,并且经常不匹配工作树中的文件。2021年11月:另见Derrick Stolee中的“Make your monorepo feel small with Git’s sparse index”(Microsoft/GitHub)
Git索引是Git中的一个关键数据结构。它充当文件系统中的文件和提交历史之间的"暂存区"。
git add
git commit
git checkout
除了存储暂存的更改之外,索引还存储有关工作目录的文件系统信息。这有助于Git更快地报告更改的文件。要了解更多信息,请参阅。“git/git/blob/master/Documentation/gitformat-index.txt”:
所有二进制数都是按网络字节顺序排列的。
签名为{'D ',' I ',' R ',' C '}(代表“dircache”)
D
I
R
C
dircache
目前支持的版本为2、3和4。
扩展名由签名标识。如果Git不理解可选扩展,则可以忽略它们。Git目前支持缓存树和解析撤销扩展。
A
Z
mljrgcomments:如果索引是准备下一次提交的地方,为什么“git ls-files -s”在提交后不返回任何东西?因为索引代表被跟踪的内容,在提交之后,被跟踪的内容与最后一次提交相同(git diff --cached不返回任何内容)。因此git ls-files -s列出了所有跟踪的文件(输出中的对象名、模式位和阶段号)。该列表(被跟踪的元素的列表)用提交的内容初始化。当你切换分支时,索引内容被重置为你刚刚切换到的分支所引用的提交。Git 2.20(Q4 2018)增加了索引条目偏移表(IET):参见Ben Peart ( benpeart )的commit 77ff112、commit 3255089、commit abb4bb8、commit c780b9c、commit 3b1d9e0、commit 371ed0d(2018年10月10日)。参见commit 252d079(2018年9月26日)by Nguyễn Thái Ngọc Duy ( pclouds )。(由Junio C Hamano -- gitster --合并于commit e27bfaa,2018年10月19日)
git ls-files -s
git diff --cached
benpeart
pclouds
gitster
这个补丁可以通过向索引添加额外的数据来解决加载索引的CPU成本,这将允许我们有效地多线程加载和转换缓存条目。它通过添加一个(可选的)索引扩展来实现这一点,该索引扩展是索引文件中缓存条目块的偏移量表。为了使这适用于V4索引,当写入缓存条目时,它通过对当前条目进行编码来定期“重置”前缀压缩,就好像先前条目的路径名完全不同一样,并将该条目的偏移量保存在IEOT中。基本上,使用V4索引,它会生成前缀压缩条目块的偏移量。使用new index.threads config setting,索引加载现在更快了。因此(of using IEOT),commit 7bd9631清理了Git 2.23(Q3 2019)的read-cache.c load_cache_entries_threaded()函数。参见commit 8373037、commit d713e88、commit d92349d、commit 113c29a、commit c95fc72、commit 7a2a721、commit c016579、commit be27fb7、commit 13a1781、commit 7bd9631、commit 3c1dce8、commit cf7a901、commit d64db5b、commit 76a7bc0(2019年5月9日),作者Jeff King ( peff )。(由Junio C Hamano -- gitster --合并于commit c0e78f7,2019年6月13日)
read-cache.c load_cache_entries_threaded()
peff
load_cache_entries_threaded()函数接受一个它不使用的src_offset参数。自77ff112(read-cache:在工作线程上加载缓存条目,2018 - 10 - 10,Git v2.20.0-rc0)。在邮件列表上挖掘,该参数是earlier iteration of the series的一部分,但当代码切换到使用IEOT扩展时就变得不必要了。在Git 2.29(2020年第4季度)中,格式描述调整为最近的SHA-256工作。参见commit 8afa50a,commit 0756e61,commit 123712b,commit 5b6422a(2020年8月15日)by Martin Ågren ( none )。(由Junio C Hamano -- gitster --合并到commit 74a395c,2020年8月19日)
load_cache_entries_threaded()
src_offset
read-cache
none
index-format.txt
签字人:马丁·奥格伦
记录在SHA-1存储库中,我们使用SHA-1,在SHA-256存储库中,我们使用SHA-256,然后用更中性的东西替换所有其他“SHA-1”的用法。避免引用“160位”哈希值。technical/index-format现在在其手册页中包括:所有二进制数都是按网络字节顺序排列的。在使用传统SHA-1的存储库中,下面提到的校验和和对象ID(对象名称)都是使用SHA-1计算的。类似地,在SHA-256存储库中,这些值是使用SHA-256计算的。除非另有说明,否则在此描述版本2。
technical/index-format
pkmbmrz72#
我决定做一些测试,以便更好地理解格式,并更详细地研究一些字段。下面的结果对于Git版本1.8.5.2和2.3是相同的。我用TODO标记了我不确定/没有找到的点:请随时补充这些要点。正如其他人提到的,索引存储在.git/index下,而不是作为标准的树对象,其格式是二进制的,并在以下位置进行了记录:https://github.com/git/git/blob/master/Documentation/technical/index-format.txt定义索引的主要结构位于cache.h,因为索引是用于创建提交的缓存。
1.8.5.2
2.3
TODO
当我们启动一个测试仓库时:
git init echo a > b git add b tree --charset=ascii
.git目录如下所示:
.git
.git/objects/ |-- 78 | `-- 981922613b2afb6025042ff6bd878ac1994e85 |-- info `-- pack
如果我们得到唯一对象的内容:
git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85
我们得到a。这表明:
a
index
git add b
现在让我们看看索引本身:
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 | ... |
首先是header,定义在:结构缓存头:
44 49 52 43
DIRC
00 00 00 02
00 00 00 01
b
接下来开始一个索引条目列表,由struct cache_entry定义这里我们只有一个。它包括:
ctime
mtime
注意如何:
54 09 76 e6 1d 81 6f c6
第一个字节是从EPOCH开始的秒数(十六进制):
date --date="@$(printf "%x" "540976e6")"
Fri Sep 5 10:40:06 CEST 2014
所以我举了这个例子。第二个4字节是纳秒。
00 00 03 e8
所有这些元数据(其中大部分不存在于树对象中)允许Git检查文件是否快速更改,而无需比较整个内容。
30
\n
echo
78 98 19 22 ... c1 99 4e 85
00 01
git update-index --assume-unchanged
0
man git-merge
1
2
3
在合并冲突期间,从1到3的所有阶段都存储在索引中,以允许像git checkout --ours这样的操作。如果git add,则stage 0会添加到路径的索引中,Git会知道冲突已被标记为已解决。TODO:检查一下。
git checkout --ours
0 01
62
然后是00:1 - 8字节的零填充,以便路径将以空值终止,索引将以8字节的倍数结束。这只发生在索引版本4之前。未使用延伸导线。Git知道这一点,因为文件中没有足够的空间来保存校验和。最后,索引内容上有一个20字节的校验和ee 33 c0 3a .. 09 ab 49 94。
00
ee 33 c0 3a .. 09 ab 49 94
bpzcxfmw3#
Git索引是工作目录和仓库之间的暂存区。您可以使用索引构建一组要一起提交的更改。当你创建一个提交时,提交的是当前在这个索引中的内容,而不是你的工作目录中的内容。要查看索引中的内容,请执行以下命令:
git status
当你运行git status时,你可以看到哪些文件被暂存(当前在你的索引中),哪些文件被修改但还没有暂存,哪些文件完全没有被跟踪。你可以读this。谷歌搜索抛出了许多链接,这应该是相当自给自足。
9w11ddsr4#
git ls-files可以显示索引的内容。请注意,单词index、stage和cache在Git中是相同的:它们可互换使用。
stage
cache
Git index,即Git cache,有三个重要属性:
1.索引包含生成单个(唯一确定的)树对象所需的所有信息。1.索引允许在它定义的树对象和工作树之间进行快速比较。1.它可以有效地表示有关不同树对象之间的合并冲突的信息,允许每个路径名与有关所涉及的树的足够信息相关联,以便您可以在它们之间创建三向合并。
来源:
ftf50wuq5#
作为对@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,那么stage 0会被添加到路径的索引中,Git会知道冲突已经被标记为已解决。TODO:检查一下。”更具体地说,不同的合并阶段。
详细说明了各个阶段的数字表示法,在本例中是一个带有冲突的文件.
$ 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
jyztefdp6#
这就是你需要的,使用这个命令。$ binwalk index
$ binwalk index
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
zpjtge227#
只是想把git ls-tree放进戒指里。索引是git中最重要的数据结构之一。它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作暂存区以写出要提交的下一个树对象。状态是“虚拟的”,在这个意义上,它不一定必须,并且经常不匹配工作树中的文件。如果说git ls-tree告诉我如果我 checkout 一个特殊的提交,应该存在哪些工作文件/对象,这是真的吗?在ls-tree的上下文中,我们说的是哪种树?示例
git ls-tree -r -l HEAD git ls-tree -r -l commit-hash
顺便说一句:ls-tree也适用于没有 checkout (-n)的克隆存储库,其中ls-files不返回任何内容。https://stackoverflow.com/a/56242906/2623045https://stackoverflow.com/a/67567058/2623045
7条答案
按热度按时间nhn9ugyo1#
Git手册中有一篇关于what an index includes的文章:
索引是一个二进制文件(通常保存在
.git/index
中),其中包含路径名的排序列表,每个路径名都有权限和blob对象的SHA1;git ls-files
可以显示索引的内容:Racy git problem给出了该结构的更多细节:
索引是git中最重要的数据结构之一。
它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作暂存区以写出要提交的下一个树对象。
状态是“虚拟的”,在这个意义上,它不一定必须,并且经常不匹配工作树中的文件。
2021年11月:另见Derrick Stolee中的“Make your monorepo feel small with Git’s sparse index”(Microsoft/GitHub)
Git索引是Git中的一个关键数据结构。它充当文件系统中的文件和提交历史之间的"暂存区"。
git add
时,工作目录中的文件将被散列并作为对象存储在索引中,从而使它们成为“阶段性更改”。git commit
时,存储在索引中的阶段性更改将用于创建新的提交。git checkout
时,Git从一个提交中获取数据并将其写入工作目录和索引。除了存储暂存的更改之外,索引还存储有关工作目录的文件系统信息。
这有助于Git更快地报告更改的文件。
要了解更多信息,请参阅。“git/git/blob/master/Documentation/gitformat-index.txt”:
Git索引文件格式如下
所有二进制数都是按网络字节顺序排列的。
签名为{'
D
','I
','R
','C
'}(代表“dircache
”)目前支持的版本为2、3和4。
扩展名由签名标识。
如果Git不理解可选扩展,则可以忽略它们。
Git目前支持缓存树和解析撤销扩展。
A
'..'Z
',则扩展名是可选的,可以忽略。mljrgcomments:
如果索引是准备下一次提交的地方,为什么“
git ls-files -s
”在提交后不返回任何东西?因为索引代表被跟踪的内容,在提交之后,被跟踪的内容与最后一次提交相同(
git diff --cached
不返回任何内容)。因此
git ls-files -s
列出了所有跟踪的文件(输出中的对象名、模式位和阶段号)。该列表(被跟踪的元素的列表)用提交的内容初始化。
当你切换分支时,索引内容被重置为你刚刚切换到的分支所引用的提交。
Git 2.20(Q4 2018)增加了索引条目偏移表(IET):
参见Ben Peart (
benpeart
)的commit 77ff112、commit 3255089、commit abb4bb8、commit c780b9c、commit 3b1d9e0、commit 371ed0d(2018年10月10日)。参见commit 252d079(2018年9月26日)by Nguyễn Thái Ngọc Duy (
pclouds
)。(由Junio C Hamano --
gitster
--合并于commit e27bfaa,2018年10月19日)ieot:添加索引条目偏移表(IET)扩展
这个补丁可以通过向索引添加额外的数据来解决加载索引的CPU成本,这将允许我们有效地多线程加载和转换缓存条目。
它通过添加一个(可选的)索引扩展来实现这一点,该索引扩展是索引文件中缓存条目块的偏移量表。
为了使这适用于V4索引,当写入缓存条目时,它通过对当前条目进行编码来定期“重置”前缀压缩,就好像先前条目的路径名完全不同一样,并将该条目的偏移量保存在IEOT中。
基本上,使用V4索引,它会生成前缀压缩条目块的偏移量。
使用new index.threads config setting,索引加载现在更快了。
因此(of using IEOT),commit 7bd9631清理了Git 2.23(Q3 2019)的
read-cache.c load_cache_entries_threaded()
函数。参见commit 8373037、commit d713e88、commit d92349d、commit 113c29a、commit c95fc72、commit 7a2a721、commit c016579、commit be27fb7、commit 13a1781、commit 7bd9631、commit 3c1dce8、commit cf7a901、commit d64db5b、commit 76a7bc0(2019年5月9日),作者Jeff King (
peff
)。(由Junio C Hamano --
gitster
--合并于commit c0e78f7,2019年6月13日)读缓存:从线程加载中删除未使用的参数
load_cache_entries_threaded()
函数接受一个它不使用的src_offset
参数。自77ff112(read-cache
:在工作线程上加载缓存条目,2018 - 10 - 10,Git v2.20.0-rc0)。在邮件列表上挖掘,该参数是earlier iteration of the series的一部分,但当代码切换到使用IEOT扩展时就变得不必要了。
在Git 2.29(2020年第4季度)中,格式描述调整为最近的SHA-256工作。
参见commit 8afa50a,commit 0756e61,commit 123712b,commit 5b6422a(2020年8月15日)by Martin Ågren (
none
)。(由Junio C Hamano --
gitster
--合并到commit 74a395c,2020年8月19日)index-format.txt
:文件SHA-256索引格式签字人:马丁·奥格伦
记录在SHA-1存储库中,我们使用SHA-1,在SHA-256存储库中,我们使用SHA-256,然后用更中性的东西替换所有其他“SHA-1”的用法。
避免引用“160位”哈希值。
technical/index-format
现在在其手册页中包括:所有二进制数都是按网络字节顺序排列的。
在使用传统SHA-1的存储库中,下面提到的校验和和对象ID(对象名称)都是使用SHA-1计算的。
类似地,在SHA-256存储库中,这些值是使用SHA-256计算的。
除非另有说明,否则在此描述版本2。
pkmbmrz72#
逐位分析
我决定做一些测试,以便更好地理解格式,并更详细地研究一些字段。
下面的结果对于Git版本
1.8.5.2
和2.3
是相同的。我用
TODO
标记了我不确定/没有找到的点:请随时补充这些要点。正如其他人提到的,索引存储在
.git/index
下,而不是作为标准的树对象,其格式是二进制的,并在以下位置进行了记录:https://github.com/git/git/blob/master/Documentation/technical/index-format.txt定义索引的主要结构位于cache.h,因为索引是用于创建提交的缓存。
设置
当我们启动一个测试仓库时:
.git
目录如下所示:如果我们得到唯一对象的内容:
我们得到
a
。这表明:index
指向文件内容,因为git add b
创建了一个blob对象高清解析
现在让我们看看索引本身:
提供:
接下来我们将得出结论:
首先是header,定义在:结构缓存头:
44 49 52 43
:DIRC
。TODO:为什么需要这样做?00 00 00 02
:格式版本:2.索引格式随时间而演变。目前版本最高为4。在GitHub上的不同计算机之间进行协作时,索引的格式不应该是一个问题,因为裸存储库不存储索引:它在克隆时生成。00 00 00 01
:索引上的文件数:只有一个b
接下来开始一个索引条目列表,由struct cache_entry定义这里我们只有一个。它包括:
ctime
,8字节mtime
,然后4字节:device、inode、mode、UID和GID。注意如何:
ctime
和mtime
与预期相同(54 09 76 e6 1d 81 6f c6
),因为我们没有修改文件第一个字节是从EPOCH开始的秒数(十六进制):
提供:
所以我举了这个例子。
第二个4字节是纳秒。
00 00 03 e8
,十六进制为1000:单用户设置的常用值。所有这些元数据(其中大部分不存在于树对象中)允许Git检查文件是否快速更改,而无需比较整个内容。
30
行的开头:00 00 00 02
:文件大小:2字节(a
和\n
从echo
)78 98 19 22 ... c1 99 4e 85
:20字节的SHA-1,覆盖条目的先前内容。请注意,根据my experiments with the assume valid flag,在此SHA-1中不考虑它后面的标志。00 01
git update-index --assume-unchanged
存储其状态的地方:https://stackoverflow.com/a/28657085/8952450
,它没有扩展标志。man git-merge
中:0
:常规文件,没有合并冲突1
:底座2
:我们的3
:他们的在合并冲突期间,从1到3的所有阶段都存储在索引中,以允许像
git checkout --ours
这样的操作。如果
git add
,则stage 0会添加到路径的索引中,Git会知道冲突已被标记为已解决。TODO:检查一下。0 01
:仅1字节,因为路径为b
62
(ASCIIb
):可变长度路径在前面的标志中确定的长度,这里只有1个字节,b
。然后是
00
:1 - 8字节的零填充,以便路径将以空值终止,索引将以8字节的倍数结束。这只发生在索引版本4之前。未使用延伸导线。Git知道这一点,因为文件中没有足够的空间来保存校验和。
最后,索引内容上有一个20字节的校验和
ee 33 c0 3a .. 09 ab 49 94
。bpzcxfmw3#
Git索引是工作目录和仓库之间的暂存区。您可以使用索引构建一组要一起提交的更改。当你创建一个提交时,提交的是当前在这个索引中的内容,而不是你的工作目录中的内容。
要查看索引中的内容,请执行以下命令:
当你运行git status时,你可以看到哪些文件被暂存(当前在你的索引中),哪些文件被修改但还没有暂存,哪些文件完全没有被跟踪。
你可以读this。谷歌搜索抛出了许多链接,这应该是相当自给自足。
9w11ddsr4#
Git index是一个二进制文件(一般保存在
.git/index
中),包含一个路径名的排序列表,每个路径名都有权限和一个blob对象的SHA1;git ls-files
可以显示索引的内容。请注意,单词index
、stage
和cache
在Git中是相同的:它们可互换使用。Git index,即Git cache,有三个重要属性:
1.索引包含生成单个(唯一确定的)树对象所需的所有信息。
1.索引允许在它定义的树对象和工作树之间进行快速比较。
1.它可以有效地表示有关不同树对象之间的合并冲突的信息,允许每个路径名与有关所涉及的树的足够信息相关联,以便您可以在它们之间创建三向合并。
来源:
ftf50wuq5#
作为对@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,那么stage 0会被添加到路径的索引中,Git会知道冲突已经被标记为已解决。TODO:检查一下。”
更具体地说,不同的合并阶段。
详细说明了各个阶段的数字表示法,在本例中是一个带有冲突的文件.
jyztefdp6#
这就是你需要的,使用这个命令。
$ binwalk index
zpjtge227#
只是想把git ls-tree放进戒指里。
索引是git中最重要的数据结构之一。
它通过记录路径列表及其对象名称来表示虚拟工作树状态,并用作暂存区以写出要提交的下一个树对象。
状态是“虚拟的”,在这个意义上,它不一定必须,并且经常不匹配工作树中的文件。
如果说git ls-tree告诉我如果我 checkout 一个特殊的提交,应该存在哪些工作文件/对象,这是真的吗?在ls-tree的上下文中,我们说的是哪种树?
示例
顺便说一句:ls-tree也适用于没有 checkout (-n)的克隆存储库,其中ls-files不返回任何内容。
https://stackoverflow.com/a/56242906/2623045
https://stackoverflow.com/a/67567058/2623045