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

bannerAds