你的引擎盖描述大多是正确的。唯一不是100%的东西与这部分有关:
每次分段更改时 git add 在下创建一个blob对象 git的/对象/
git add
在内部, git add 哈希工作树文件中的数据内容,一个la git hash-object -w -t blob 。事实并非如此 一定 创建一个 新 object:如果散列内容是 已经在存储库中 ,它只是重用现有的对象。现有的对象可能是 打包 ,即在 .git/objects/pack , 而不是 疏松 作为一个单独的blob。
git hash-object -w -t blob
.git/objects/pack
而且,内容写入blob对象 威力 是 任意 不同于工作树中的内容所致 清洁过滤器 。更常见的是,由于行结束设置,CR-LF-line-end-与工作树中的内容不同。清洁过滤器和行尾设置部分(或大部分,取决于您对Git的使用)通过您的 .gitattributes 文件,部分(或大部分)通过配置中的设置。
.gitattributes
在任何情况下,重要的是您获得blob对象的哈希ID。 blob对象肯定存在于某个地方 .git/objects 目录作为松散对象或包文件。现在 git add 可写入 .git/index (或其他任何文件 GIT_INDEX_FILE 表示):它将在暂存时隙零的索引中存储给定的条目 path ,使用计算的blob-hash和模式 100644 要么 100755 取决于工作树文件是否应该在以后标记为可执行文件。
.git/objects
.git/index
GIT_INDEX_FILE
path
100644
100755
[场景剪断,但最终结束 git checkout HEAD -- path 用它来破坏索引条目 $path 代表 $blobhash 和模式 $mode 信息, 的 和 强> 破坏文件的工作树副本 path 。)
git checkout HEAD -- path
$path
$blobhash
$mode
除非内容中的垃圾收集仍然存在,否则技术上仍然存在。但我不知道如何将其取回,然后手动尝试以某种方式找到哈希并阅读内容 git cat-file 。
git cat-file
实际上,你不能:哈希ID计算是一个 陷门功能 ,只有你 做 有你的哈希你可以让Git溢出内容,但如果你没有哈希,你需要有内容。那是你的 Catch-22情况 。
如果 “他是一个非常重要的”“如果”的内容 是 独特的,所以 git add 确实创造了一个 新 blob对象, 和 你刚刚覆盖了索引中的blob引用,blob对象确实不再被引用。另一方面,如果 git hash-object -w 最后重新使用一些现有的blob,blob对象仍被之前引用的任何引用引用。所以现在有两个有趣的案例:blob 是 独特的,现在有资格进行垃圾收集,或者,blob是 不 独特而不是。
git hash-object -w
运用 git fsck --lost-found 要么 git fsck --unreachable 要么 git fsck --dangling (默认),你可以让Git遍历整个对象数据库,确定是哪些对象 到达 哪些不是,并告诉你一些或所有无法访问的和/或从中或从中复制信息 .git/lost-found 。如果是blob对象 是 它无法到达 将 被列为这些无法到达或悬空的斑点之一,或将其内容恢复到其中 .git/lost-found 。
git fsck --lost-found
git fsck --unreachable
git fsck --dangling
.git/lost-found
这里的缺点是可能有数十甚至数百个悬空blob对象。你的任务有现在从“猜测哈希”(几乎不可能)转变为“在大海捞针中找到针头”(不是那么困难,但很乏味,你可能会发现 错误 针头并不是一个干草堆,毕竟它是一堆针。当然,这只适用于“blob是独一无二的”案例。
(顺便说一下,这是这个问题的所在 不 真的是重复的 git可以撤消未分段文件的签出 。但那个仍然有用,所以也可以看看。)
有没有类似的东西 git reflog 对于指数?
git reflog
不,你 能够 制作自己的备份副本:只是 cp .git/index 某处。但是Git并不是自己做这件事。你可以在a之前做一个 git checkout HEAD -- path 操作,通过一些别名或shell函数,用于执行这种危险的操作。
cp .git/index
请注意,Git不知道这些备份副本,所以 git gc 不会考虑受保护的引用对象。使用像管道命令一样的备份 git ls-files ,将路径名称放入 GIT_INDEX_FILE 在该命令的持续时间内。
git gc
git ls-files
是 git checkout @ -- 文件被认为是危险的命令 git reset --hard 你可能会失去工作的地方?
git checkout @ --
git reset --hard
答案取决于谁在考虑这个问题。我建议自己考虑危险,因为你问的是这个问题。 :-)
是否有管道命令来手动更改/重写索引? (参见上面的情况,那里的物体仍在那里)
是: git update-index 是一次性的一次性更新程序(使用 --cacheinfo 要么 --stdin 提供原始索引条目数据,而不是让它复制很多 git add 工作)。许多其他命令也会部分地或集中地更新索引。
git update-index
--cacheinfo
--stdin
如果您有一个进程备份索引之前的索引 git checkout HEAD -- ... 操作,您可以读取备份索引中的条目(使用 GIT_INDEX_FILE=... git ls-files 例如)然后使用 git update-index , 无 有 GIT_INDEX_FILE 设置,将信息放入常规索引中。当然,这是一个index-overwrite-y操作,您可能希望首先对索引进行另一次备份。
git checkout HEAD -- ...
GIT_INDEX_FILE=... git ls-files
是否有另一种方法可以在不立即暂存的情况下签出单个文件?
不,但仅仅因为动词 查看 这里。至 查看内容 一个文件在索引中,或在任何提交中,内容的名称是 git rev-parse 可以理解的 git show :
git rev-parse
git show
git show :file # file in index at stage zero git show :3:file # file in index at stage three, during merge conflict git show HEAD:file # file in current commit git show master~7:file # file in commit 7 first-parent hops back from master
另请注意 git reset 可以覆盖索引中的一个或多个文件而不触及工作树中的文件:
git reset
git reset HEAD -- file # copy HEAD:file to :file leaving work-tree file undisturbed
如果你给 git reset 如果是目录的路径,它会重置索引中已存在且位于目录中的所有文件。