首页 > 解决方案 > Git 查看 objects/pack/pack-hash.pack 中的文件名

问题描述

我错误地提交了大型临时文件并将其推送到 git 服务器。在 git 服务器上,我使用我通过 Google 搜索找到的命令及其 Web 界面恢复了最后一次提交,提交次数减少了一个,最后一次提交消失了。

尽管如此,服务器上的数据大小似乎并没有减少。我确实运行了那些“prune”和“reflog”命令。在服务器上,有一个大的“pack”文件和一个“idx”文件。我跑了git verify-pack -v <file name>.idx,显示了很多数据,但每一行都很神秘

[哈希码] blob [编号] [编号] [编号]

所以,我不知道它们是什么。我可以看到像“program.cs”这样的原始文件名,以便我可以查看存储库中是否仍然存在临时文件?

标签: git

解决方案


要回答提出的实际问题:对象没有文件名。它们只是对象

提交存储文件,但它们是间接提交的。每个提交对象都有一个对一个对象的引用。在 Git 中,树对象由一系列记录组成,每条记录包含:

  • a mode,它是一个表示八进制数的文本字符串,例如100755, 100644, 40000, 等等;
  • 路径名组件:可变长度的二进制(但通常是有效的 UTF-8)字符串,不包含/NUL 字节或 NUL 字节,后跟一个 NUL 字节;和
  • 哈希 ID(二进制,20 字节长)。

a modeof40000表示记录中的hash ID是另一个树对象的hash ID,所以hash ID必须是另一个树对象的hash(或者repository坏了)。其他模式意味着其他哈希 ID 用途,在这种情况下,哈希 ID 通常是 blob 的 ID。还有另一种特殊情况:mode160000表示一个gitlink,并表示该条目提供了来自子模块的期望和 to 的哈希 ID git checkout

因此,blob ID B可以表示多个不同的文件路径名。这些文件名是通过将每个树对象中的路径名段与导致找到最终对象的一系列对象中的最终模式100755或模式blob 对象中的路径名段连接来构造的。100644

也就是说,假设提交C a具有作为其顶级树哈希 ID T 1 ,它通过 name引用树T 2d1,然后T 2通过name引用 blob B hf1。然后 blob B h在此提交中表示文件d1/f1。但是假设提交C b有树T 3,它按名称引用树T 4d2,而T 4按名称引用B hf2。然后 blob Bh代表d2/f2提交C b中的文件。如果提交C c具有引用B h的顶级树T 5 ,则提交C c将相同的文件内容存储在名称下(没有子文件夹)。f3f3

存储库中的对象持久性是一系列规则的功能,其主要驱动力是可达性。有关可达性的定义,请参阅Think Like (a) Git 。无法访问的对象将(通常,最终)被删除——但附加规则会在一段时间内阻止删除无法访问的松散对象,以便 Git 可以创建临时对象并最终——在一段时间内——<em>使它们可以访问并因此永久(或尽可能永久,因为它们保持可达)。

包内的对象根本无法删除。但是,包含许多无用对象的包文件通常可以重新打包到新的(和不同的)包文件中;或者它们可以爆炸成单个松散的物体。一旦不再需要旧的包文件——因为它的所有对象都可以作为松散对象或在替代包中使用——它可以被丢弃,但是.keep包文件的文件会阻止它被丢弃。Git 本身不会创建.keep文件:它们适用于直接摆弄包文件的人(无论出于何种目的)。

git gc命令是一个包装器,通常负责创建和维护包文件以及清除过期的、未引用的松散对象。它运行其他内部 Git 命令,包括git reflog expiregit repackgit prune,以实现此结果。


推荐阅读