Skip to content

Commit

Permalink
Add contents
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinliu6 committed Jan 20, 2024
1 parent 596589f commit 1fe53c9
Show file tree
Hide file tree
Showing 66 changed files with 750 additions and 128 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build/
.DS_Store
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"asciidoc.antora.enableAntoraSupport": true
}
8 changes: 0 additions & 8 deletions src/content/adding-content.adoc

This file was deleted.

293 changes: 293 additions & 0 deletions src/content/git-directory.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
== `.git` 目录

=== 简介

在一个目录中执行 link:https://harshkapadia2.github.io/git_basics/#_git_init[`git init` 命令^] 时,Git 会在这个目录下创建一个隐藏目录 `.git`。`.git` 目录包含了 Git 可以执行其版本控制功能的项目的所有历史数据。此外,它还包含了用于配置 Git 如何处理该特定 link:https://harshkapadia2.github.io/git_basics/#_repository[仓库^] 的相关事宜的配置文件。

=== `.git` 目录的内容

[source, shell]
----
.git
├───addp-hunk-edit.diff
├───COMMIT_EDITMSG
├───config
├───description
├───FETCH_HEAD
├───HEAD
├───hooks
│ └───<*.sample>
├───index
├───info
│ └───exclude
├───lfs
│ ├───cache
│ │ └───locks
│ │ └───refs
│ │ └───heads
│ │ └───<branch_names>
│ │ └───verifiable
│ ├───objects
│ │ └───<first_2_SHA-256_characters>
│ │ └───<next_2_SHA-256_characters>
│ │ └───<entire_64_character_SHA-256_hash>
│ └───tmp
├───logs
│ ├───HEAD
│ └───refs
│ ├───heads
│ │ └───<branch_names>
│ ├───remotes
│ │ └───<remote_aliases>
│ │ └───<branch_names>
│ └───stash
├───MERGE_HEAD
├───MERGE_MODE
├───MERGE_MSG
├───objects
│ ├───<first_2_SHA-1_characters>
│ │ └───<remaining_38_SHA-1_characters>
│ ├───info
│ │ ├───commit-graph
│ │ └───packs
│ └───pack
│ ├───multi-pack-index
│ ├───<*.idx>
│ ├───<*.pack>
│ └───<*.rev>
├───ORIG_HEAD
├───packed-refs
├───rebase-merge
│ ├───git-rebase-todo
│ ├───git-rebase-todo.backup
│ ├───head-name
│ ├───interactive
│ ├───no-reschedule-failed-exec
│ ├───onto
│ └───orig-head
└───refs
├───heads
│ └───<branch_names>
├───remotes
│ └───<remote_aliases>
│ └───<branch_names>
├───stash
└───tags
└───<tag_names>
----

=== `index` 文件

* 该文件包含了 link:https://harshkapadia2.github.io/git_basics/#_added_files[已暂存(已添加)^] 文件的全部细节,它就是 Git 仓库的暂存区。

[NOTE]
====
* 在 Git 中,“index”,“stage” 和 “cache” 是同义词,它们之间可以互换使用。
* 不要将这个 `index` 文件和 link:#_pack_目录[位于 `.git/objects/pack` 中的 `.idx` 索引文件] 搞混了,它们之间没有关系。
====

* 该文件是在第一次添加文件时创建的,以后每次执行 link:https://harshkapadia2.github.io/git_basics/#_git_add[`git add` 命令^] 时都会更新它。

image::index-explained.png[alt="Index file explained", 400, 400]

* 该文件是一个二进制文件,只是使用 `cat .git/index` 查看其内容时会导致乱码. 想要查看其内容可以使用 `git ls-files --stage` [底层命令]。

image::git-ls-files.png[alt="'git ls-files --stage' command", 600, 600]

* 上图中的内容解释
** `100644` 表示文件的模式,它是一个八进制数。
+
[source, plaintext]
----
Octal: 100644
Binary: 001000 000 110100100
----

*** 前 6 个二进制位指示对象类型。
**** `001000` 表示普通文件。(如本例所示。)
**** `001010` 表示 link:https://tdongsi.github.io/blog/2016/02/20/symlinks-in-git[符号链接^].
**** `001110` 表示 link:https://www.oreilly.com/library/view/version-control-with/9780596158187/ch15s04.html#:~:text=gitlink[gitlink^].
*** 接下来的 3 个二进制位 (`000`) 保留。
*** 最后 9 个二进制位 (`110100100`) 表示 link:https://harshkapadia2.github.io/cli/terminal.html#changing-permissions[Unix 文件权限^]。
**** `644` 和 `755` 对于普通文件有效。
**** 对于符号链接和 gitlinks 这 9 位的值都是 `0`。
** 接下来的 40 个字符的十六进制字符串表示的是文件的 link:https://harshkapadia2.github.io/git_basics/#_sha1[SHA-1 哈希^]。
** 下一个数字是暂存号/槽,它在处理合并冲突时很有用。
*** `0` 表示正常无冲突的文件。
*** `1` 表示文件的原始版本。
*** `2` 表示“我们的”版本,即 HEAD 指向的版本,包括了冲突双方的更改。
*** `3` 表示“他们的”版本,即被合并的版本的文件。
** 最后的字符串是所引用文件的名称。

NOTE: 有关 `index` 文件的更多内容可参阅 link:#_有关暂存区_index_文件[资源] 一节。

=== `HEAD` 文件

* 它用于引用当前分支中的最新提交。
* HEAD 文件通常不使用这个最新 commit 的 link:https://harshkapadia2.github.io/git_basics/#_sha1[SHA-1^] 哈希,而是记录了一个在 link:#_refs_目录[refs 目录] 下的文件(以当前分支的名称命名)路径,这个文件存储了在它这个分支下最后一个 commit 的 SHA-1 哈希。
* 当 link:https://harshkapadia2.github.io/git_basics/#_commits_sha[一个特定的 commit 或 tag 被检出^] 时,该文件才会包含提交的 SHA-1 哈希。(link:https://harshkapadia2.github.io/git_basics/#_detached_head[分离头(Detached HEAD)状态^]。)
* link:https://harshkapadia2.github.io/git_basics/#_head[关于 `HEAD` 文件的更多内容^]
* Eg:
+
[source, shell]
----
# in the 'main' branch
$ cat .git/HEAD
ref: refs/heads/main
$ git switch test_branch
Switched to branch 'test_branch'
$ cat .git/HEAD
ref: refs/heads/test_branch
----

=== `refs` 目录

[source, shell]
----
.git
├───...
└───refs
├───heads
│ └───<branch_name(s)>
├───remotes
│ └───<remote_alias(es)>
│ └───<branch_name(s)>
├───stash
└───tags
└───<tag_name(s)>
----

* 该目录保存了对每个本地分支中最新提交的引用,并以该提交的 SHA-1 哈希形式获取远程分支。
* 它还存储了已经 [打了标签] 的 commit 的 SHA-1 哈希。
* link:#_head_文件[`HEAD` 文件] 引用了该目录(`refs`)下的 `heads` 子目录的一个文件(link:https://harshkapadia2.github.io/git_basics/#_new_branch_name[以当前检出分支命名^])。

NOTE: 不要把 `.git/refs` 目录和 link:#_logs_目录[`.git/logs/refs` 目录] 搞混了,他们的用处不同。

=== `packed-refs` 文件

* Git 会在 link:#_refs_目录[`refs` 目录] 下的为每个分支和标签创建一个文件。
* 在拥有很多分支和标签的仓库中,便会存在很多引用(refs),其中很少会被主动使用或更改的。
* 这些引用占用了大量的存储空间,以致出现性能问题。
* `git pack-refs` 就是用来解决上面👆🏻这个问题的。它将所有的引用存储在这个名为“packed-refs”的文件中。`git gc` 命令也可以用来执行此操作。

image::cat-packed-refs.png[alt="Print the packed-ref file", 600, 600]

* 执行上述命令打包后,如果某个引用在 `refs` 目录中缺失了,Git 就会在此文件中查找。
* 对已打包 ref 的分支进行后续更新(新提交、拉取或推送更改)时,会像往常一样在 `refs` 目录中创建一个带有该分支名称的新文件,但它不会将该分支在 `packed-refs` 文件中的哈希值更新为最新的哈希值。(为此必须生成一个新的 `packed-refs` 文件。)

=== `logs` 文件夹

[source, shell]
----
.git
├───...
└───logs
├───HEAD
└───refs
├───heads
│ └───<branch_name(s)>
├───remotes
│ └───<remote_alias(es)>
│ └───<branch_name(s)>
└───stash
----

* 该目录包含了按顺序排列的所有提交的历史记录。

image::cat-logs.png[alt="Print a branch's log file", 1000, 1000]

* 每一行内容按照从左到右的顺序分别是:父提交的 link:https://harshkapadia2.github.io/git_basics/#_sha1[SHA-1 哈希^],当前提交的 SHA-1 哈希,提交者的名字和邮箱,提交的 link:https://www.epochconverter.com/#:~:text=What%20is%20epoch%20time[Unix 时间戳^],时区,行为类型和消息。
* 本地 Git 仓库中的每个分支以及从单个或多个远程 Git 仓库(如果有的话)获取的分支都有日志。
* 进入 `logs` 目录
** `HEAD` 文件存储了用户执行的所有命令的信息,像分支切换、提交、变基等。
** `refs` 目录中仅包含特定于分支的操作和历史,例如提交、拉取、重置、变基等。

NOTE: 不要把 `.git/logs/refs` 目录 and the link:#_refs_目录[`.git/refs` 目录] 搞混了,他们的用处不同。

=== `FETCH_HEAD` 文件

* 它包含了取回的远程分支的最新提交。
* 它对应的分支是:
** 上次取回时 link:https://harshkapadia2.github.io/git_basics/#_new_branch_name[检出^] 的分支。
+++
<br />
<br />
+++
image:cat-FETCH_HEAD-1.png[alt="The contents of the FETCH_HEAD file", 800, 800]

*** 从上图可以看到,只有一个分支不带 `not-for-merge` 文本描述。这个奇怪的分支(本例中是 `main` 分支)就是远程取回时检出的分支。
** 使用 link:https://harshkapadia2.github.io/git_basics/#_git_fetch[`git fetch <remote_repo_alias> <branch_name>` command^] 命令时明确指定的分支。
+++
<br />
<br />
+++
image:cat-FETCH_HEAD-2.png[alt="The contents of the FETCH_HEAD file", 800, 800]

=== `COMMIT_EDITMSG` 文件

* 提交信息就是写入此文件中的。
* 当执行 link:https://harshkapadia2.github.io/git_basics/#_git_commit[`git commit` command^] 命令时,该文件会被编辑器打开。
* 该文件内容包含 link:https://harshkapadia2.github.io/git_basics/#_git_status[`git status` command^] 命令输出中由该字符 `&#35;` 注释掉的内容。
* 如果之前有过提交,那么这个文件将会显示上次提交的信息以及本次提交之前的 `git status` 的输出。

=== `objects` 目录

[source, shell]
----
.git
├───...
└───objects
├───<first_2_SHA-1_characters>
│ └───<remaining_38_SHA-1_characters>
├───info
│ ├───commit-graph
│ └───packs
└───pack
├───multi-pack-index
├───<*.idx>
└───<*.pack>
----

* `.git` 目录下最重要的目录了。
* 它保存着仓库中所有的 link:#_git_对象[commit, tree and blob 对象] 的数据(SHA-1 哈希)。
* 为了减少访问时间,对象被放置在存储桶(目录)中,其 SHA-1 哈希值的前两个字符作为存储桶的名称,其余 38 个字符用于命名对象的文件。
* link:#_pack_目录[关于 `pack` 目录的更多内容]

NOTE: 不要将这个目录 (`.git/objects/info`) 和 link:#_info_目录[`.git/info` 目录] 搞混了,它们的用处不同。

=== `info` 目录

[source, shell]
----
.git
├───...
└───info
└───exclude
----

* 它含有一个 `exclude` 文件,其行为类似于 link:https://harshkapadia2.github.io/git_basics/#_gitignore_file[`.gitignore` 文件^],但用于在本地忽略文件而不修改 `.gitignore`。
* link:https://harshkapadia2.github.io/git_basics/#_ignore_files_locally_without_modifying_gitignore[关于 `exclude` 文件的更多内容。^]

NOTE: 不要将这个目录 (`.git/info`) 和 link:#_objects_目录[`.git/objects/info` 目录] 搞混了,它们的用处不同。

=== `config` 文件

* 这个文件包含了本地 Git 仓库的配置。
* 使用 link:https://harshkapadia2.github.io/git_basics/#_git_config[`git config --local` 命令^] 可以修改它。

=== `addp-hunk-edit.diff` 文件

* 当在 link:https://harshkapadia2.github.io/git_basics/#_p_or_patch[`git add --patch` 命令^] 中指定了 `-e` (edit) 选项时创建该文件。
* 该文件的创建使得你可以手动编辑将要 link:https://harshkapadia2.github.io/git_basics/#_added_files[暂存^] 的文件 hunk。

=== `ORIG_HEAD` 文件

* 它包含了一个 commit 的 SHA-1 哈希。
* 它是 HEAD 的前一个状态,但不一定是紧邻的前一个状态。
* 它是由某些具有破坏性/危险行为的命令设置的,因此它通常指向具有破坏性更改的最新提交。
* 由于 [`git reflog` 命令] 的存在,它现在不是那么有用,`git reflog` 更容易回退/重置到一个特定的 commit。

=== `description` 文件

* 仓库的描述文件。
* 该文件由 link:https://git-scm.com/book/en/v2/Git-on-the-Server-GitWeb[GitWeb^] 使用,目前几乎没有人使用它,因此可以不用管。
Loading

0 comments on commit 1fe53c9

Please sign in to comment.