Git的背后机制
为了理解Git的工作原理,我总结了根据Git操作.git目录中内容如何变化的情况。
前提是理解Git的术语和基本操作。
初始化Git
执行git init命令后,当前目录下的文件将被Git跟踪,并创建.git目录。
.git文件夹
.git目录的内容如下所示。
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
主要目录的作用
-
- HEAD – 現在のブランチの参照を表すファイル
-
- config – リモートブランチなどの情報が書かれたファイル
-
- objects – コミットなどのオブジェクトを保存するディレクトリ
-
- refs- ブランチの情報を保存するディレクトリ
heads – ブランチの情報を保存する
tag – タグの情報を保存する
加入舞台
使用git add命令将更改添加到暂存区。
当将其添加到舞台时,会有.git目录的内容。
.git
├── HEAD
├── config
├── description
├── hooks
│ ├── 省略
├── index
├── info
│ └── exclude
├── objects
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
- index – インデックスの情報を保存するファイル
将其添加到舞台后,索引文件和对象目录中会创建一个文件。
在objects文件夹中创建的名为e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391的文件是需要修改的压缩文件,并称之为blob对象。blob意为“块”,指代一个整体。
压缩文件的文件名是通过哈希函数将文件内容转换为40个字符的字母数字哈希ID,其中前两个字符用作目录名,剩余的38个字符用作文件名保存。
这个哈希ID是唯一的,如果文件内容相同,它就完全相同。
索引文件中记录了已更改文件的blob对象及其对应的文件名。
提交
提交在舞台上所做的更改。
提交时.git文件夹的内容如下。
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── 省略
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 09
│ │ └── b5607d0c6afa2cc0067699e6b25807c7c8659c
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f9
│ │ └── 3e3a1a1525fb5b91020da86e44810c87a2d7bc
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
在COMMIT_EDITMSG、logs、refs/heads/master和objects中创建了一些目录和文件。
重要的是在objects中的三个文件。其中一个是添加到舞台时的压缩文件,其余两个是树文件和提交文件。
树形文件
树文件是一个保存文件名和文件结构的文件,称为树对象。
由于压缩文件中没有保存文件名,所以需要通过树文件来对应压缩文件与文件名。
提交文件 (Tí
提交文件是一种保存谁,在什么时候,以及为什么变更了什么的记录,并被称为提交对象的文件。
提交文件中保存了tree、parent、author、committer和提交消息等5个信息。
提交时,tree会保存项目最顶层目录的树文件。通过保存这个树文件,记录了项目的快照。
parent保存着父节点的提交,即上一个提交。通过这样,可以追踪提交的历史记录。最初的提交没有父节点,所以不会保存parent。
在中国,作者和提交者的用户名和邮箱地址会被保存在提交记录中。
推动
为了将本地内容保存到远程仓库,执行git push命令。执行git push后,将创建remotes目录。remotes目录下的子目录将成为远程跟踪分支。
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── 省略
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 09
│ │ └── b5607d0c6afa2cc0067699e6b25807c7c8659c
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f9
│ │ └── 3e3a1a1525fb5b91020da86e44810c87a2d7bc
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
├── remotes
│ └── origin
│ └── main
└── tags
当使用cat命令检查refs/remotes/origin/main的内容时,保存了最新提交的哈希值,该提交是在推送时保存的。
09b5607d0c6afa2cc0067699e6b25807c7c8659c
创建分支
使用git branch命令创建分支后,会在refs/heads中创建一个以分支名称命名的文件,其中记录了最新提交的哈希值。
执行命令”git branch feature”。
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── 省略
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 09
│ │ └── b5607d0c6afa2cc0067699e6b25807c7c8659c
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f9
│ │ └── 3e3a1a1525fb5b91020da86e44810c87a2d7bc
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── feature
│ └── master
└── tags
使用 “cat .git/refs/heads/feature” 命令来确认创建的 “refs/heads/feature” 的内容。
09b5607d0c6afa2cc0067699e6b25807c7c8659c
這樣我們可以確認該分支已經參考到最新的提交。
切换分支
当使用git checkout命令切换分支时,切换后的分支名称会被记录在HEAD文件中。
在主分支上执行git checkout feature,并执行cat .git/HEAD命令来确认其内容。
ref: refs/heads/feature
通过这个,可以知道HEAD指向的是当前分支,并且该分支指向了最新的提交。
标签
使用git tag [标签名称]命令可创建标签,创建的标签文件将存放在refs/tags目录中。
在这里执行git tag v1.0。
.git
├── COMMIT_EDITMSG
├── HEAD
├── config
├── description
├── hooks
│ ├── 省略
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ ├── feature
│ └── master
├── objects
│ ├── 09
│ │ └── b5607d0c6afa2cc0067699e6b25807c7c8659c
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f9
│ │ └── 3e3a1a1525fb5b91020da86e44810c87a2d7bc
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── feature
│ └── master
└── tags
└── v1.0
查看 .git/refs/tags/v1.0 的内容。
09b5607d0c6afa2cc0067699e6b25807c7c8659c
通过这个可以看出这个标签指向了提交。
概况
git initでGitの初期化を行うと、.gitディレクトリが作られる
git addで変更をステージに追加すると、ファイルの内容を圧縮した圧縮ファイルが作られる
圧縮ファイルには一意の名前を設定するためにハッシュIDが使われる
git commitで変更をコミットすると、ファイル名とファイル構造を保存するツリーファイルと、いつ、誰が、何を、何のために変更したかを保存するコミットファイルが作られる
请将以下内容翻译成中文,仅需给出一种选项:
参考.
https://github.com/kaityo256/github/blob/main/internals/README.md 的中文释义如下:https://zenn.dev/kaityo256/articles/inside_the_index