.git目录的解释【翻译】
你好!本周我在 Mastodon 上发布了一个关于 .git
目录中内容的漫画,有人要求提供文本版本,所以就在这里。我还添加了一些额外的注释。首先,这是图片。它是对 .git
目录每个部分的约 15 个字的解释。
如果您想自己运行所有这些示例,可以“git clone https://github.com/jvns/inside-git”。
以下是目录:
- HEAD:.git/head
- 分支:.git/refs/heads/main
- 提交:.git/objects/10/93da429…
- 树:.git/objects/9f/83ee7550…
- blobs:.git/objects/5a/475762c…
- reflog:.git/logs/refs/heads/main
- 远程跟踪分支:.git/refs/remotes/origin/main
- 标签:.git/refs/tags/v1.0
- 存储:.git/refs/stash
- .git/config
- 钩子:.git/hooks/pre-commit
- 暂存区:.git/index
- 这不是详尽无遗的
- 这并不是要完全解释 git
前5个部分(HEAD、分支、提交、树、bols)是git的核心。
HEAD: .git/head
HEAD
是一个小文件,仅包含当前分支的名称。
示例内容:
1 | $ cat .git/HEAD |
“HEAD”也可以是提交ID,称为“分离HEAD状态”。
branch: .git/refs/heads/main
A branch is stored as a tiny file that just contains 1 commit ID. It’s stored in a folder called refs/heads
.
分支存储为一个小文件,仅包含1提交ID。它存储在名为“refs/heads”的文件夹中。
示例内容:
1 | $ cat .git/refs/heads/main |
commit: .git/objects/10/93da429...
提交是一个小文件,包含其父文件、消息、树和作者。
示例内容:
1 | $ git cat-file -p 1093da429f08e0e54cdc2b31526159e745d98ce0 |
这些文件是压缩的,查看对象的最佳方法是使用 git cat-file -p HASH
.
tree: .git/objects/9f/83ee7550...
树是包含目录列表的小文件。其中的文件称为 blobs。
示例内容:
1 | $ git cat-file -p 9f83ee7550919867e9219a75c23624c92ab5bd83 |
这里的权限看起来像unix权限,但实际上它们是超级限制的,只允许644和755。
blobs: .git/objects/5a/475762c...
blobs 是包含实际代码的文件
示例内容:
1 | $ git cat-file -p 665c637a360874ce43bf74018768a96d2d4d219a |
存储一个包含每一个更改的新blob可能会变得很大, 因此git gc
定期 打包它们 以提高 .git/objects/pack
中的效率。
reflog: .git/logs/refs/heads/main
reflog存储每个分支、标签和HEAD的历史。 对于(大多数) .git/refs
中的每个文件,.git/logs/refs`中都有相应的日志。
main
分支的示例内容:
1 | $ tail -n 1 .git/logs/refs/heads/main |
reflog的每一行都有:
- 提交之前/之后ID
- 用户
- 时间戳
- 日志消息
通常都是一行,为了可读性,我只是在这里将其包装起来。
remote-tracking branches: .git/refs/remotes/origin/main
远程跟踪分支存储远程分支最近看到的 提交ID。
示例内容:
1 | $ cat .git/refs/remotes/origin/main |
当git status显示“您与‘origin/main’保持最新状态”时,它只是在查看这个。它经常过时,您可以使用git fetch origin main
更新它。
tags: .git/refs/tags/v1.0
标签是 .git/refs/tags
中的一个小文件,包含提交ID。
示例内容:
1 | $ cat .git/refs/tags/v1.0 |
与分支不同,当您进行新的提交时,它不会更新标签。
the stash: .git/refs/stash
存储是一个名为 .git/refs/stash
的小文件。它包含运行 git stash
时创建的提交的提交 ID。
1 | cat .git/refs/stash |
存储是一个堆栈,以前的值存储在 .git/logs/refs/stash
中( stash
的 reflog)。
1 | cat .git/logs/refs/stash |
与分支和标签不同,如果您从存储中“git stash pop”提交,它将从引用日志中删除,因此几乎不可能再次找到它。存储是 git 中唯一一个在添加后很快就会被删除的引用日志。(分支引用日志中的条目也会过期,但通常仅在 90 天后)
关于 ref 的说明:
此时,您可能已经注意到,很多东西(分支、远程跟踪分支、标签和存储)都是 .git/refs
中的提交 ID。它们被称为“引用”或“refs”。每个 ref 都是一个提交 ID,但 git 对不同类型的 ref 的处理方式非常不同,因此,我发现分别考虑它们很有用,即使它们都使用相同的文件格式。例如,git 从存储引用日志中删除内容的方式与分支或标签引用日志不同。
.git/config
.git/config
是存储库的配置文件。您可以在这里配置远程服务器。
示例内容:
1 | [remote "origin"] |
git 有本地和全局设置,本地设置在这里,全局设置位于 ~/.gitconfig
钩子中
hooks: .git/hooks/pre-commit
钩子是可选脚本,您可以设置运行(例如在提交之前)来执行任何您想要的操作。
示例内容:
1 | #!/bin/bash |
(这显然不是一个真正的预提交钩子)
the staging area: .git/index
暂存区用于存储您准备提交的文件。这是一个二进制文件,与 git 中的许多本质上是纯文本文件的东西不同。
据我所知,查看索引内容的最佳方式是使用“git ls-files –stage”:
1 | $ git ls-files --stage |
这并不详尽
.git
中还有一些其他内容,例如 FETCH_HEAD
、worktrees
和 info
。我只包括了我认为有助于理解的内容。
这并不是要完全解释 git
我听到的关于 git 最常见的建议之一是“只要了解 .git
目录的结构,你就会明白一切!”。
我比任何人都更喜欢了解事物的内部结构,但“.git 目录的结构”并没有解释很多东西,比如:
- merge和rebases如何工作以及它们可能出错的原因(例如,rebases可能出错的原因 的列表)
- 您的同事究竟是如何使用 git 的,以及您应该遵循哪些准则才能成功地与他们合作
- 如何从其他存储库推送/拉取代码
- 如何处理合并冲突
但愿这对某些人有用。
其他一些参考资料:
- James Coglan 的《building git》一书(附注:看起来 1 月剩余时间 有 50% 的折扣)
- mary rose cook 的《git 从内而外》
- 官方 git 存储库布局文档
1 | 本文为个人知识学习,非原创!非作者!如本博客有侵权行为,请与我联系。 |