Help us understand the problem. What is going on with this article?

.gitディレクトリの中身を見てみる👀

git init をすると、 .git と言うディレクトリが作られます。
Gitに必要なファイルは全てこのディレクトリに含まれているのですが、普段はあまり意識しない人の方が多いと思います。
今回は .git ディレクトリの中身を少し探検してみましょう。

.gitディレクトリの構成

まずは git init して .git ディレクトリを作成してみます。
.git の中身はこのようになっています。

.
├── HEAD
├── branches
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags
  • HEAD:現在のブランチの参照
  • branches: git fetchgit pull、およびgit pushのURLを省略形を指定するために使用される、廃止予定
  • config: リポジトリのGit設定、git configで設定するメールなど
  • description: GitWeb(gitのデフォルトのWebUI)で使われる
  • hooks: Gitの各コマンドを実行した時に呼び出されるスクリプトを設定できる(e.g. pre-commitならgit commitの前)
  • info: このリポジトリに対する追加情報
    • exclude: .gitignoreのようなもの
  • objects:Gitの実体(オブジェクト)が保存される場所
    • info: オブジェクトに対する追加情報
    • pack: ランダムアクセスするためのインデックスファイルや、多数のオブジェクトを圧縮したファイル
  • refs: Gitの各参照先が保存されている場所
    • heads: 参照先のブランチ(実体はコミットオブジェクト)
    • tags: 参照先のタグ名(実体はコミットオブジェクト)

git commitしてみる

hoge.txtというファイルを新規作成して、git add, git commitしてみます

$ echo hoge > hoge.txt
$ git add hoge.txt
$ git commit -m "Add hoge.txt

.git配下はどうなっているでしょうか

.
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 22
│   │   └── 62de0c121f22df8e78f5a37d6e114fd322c0b0
│   ├── 57
│   │   └── c089a02b22cb27920e14c256e9140c1b19dbb5
│   ├── 6a
│   │   └── 73751cba5a86b1ebe10ab2856b68404aab50fd
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

何やらいくつか新しいファイルが生成されています。

COMMIT_EDITMSGにはコミットメッセージが入ります。

$ cat COMMIT_EDITMSG
Add hoge.txt

indexは、git addされたコミットする前のステージング領域として利用されます。
git commitする時にコミットされるのは、作業ディレクトリではなくここの領域のものです。
バイナリファイルであり、中身はgit ls-files --stageで確認出来ます。

$ git ls-files --stage
100644 2262de0c121f22df8e78f5a37d6e114fd322c0b0 0       hoge.txt

logsには参照に加えられた変更が残ります。

logs/HEADは現在作業しているブランチの先頭のポインタです

$ cat logs/HEAD
0000000000000000000000000000000000000000 57c089a02b22cb27920e14c256e9140c1b19dbb5 tatane616 <メールアドレス> 1560681812 +0900      commit (initial): Add hoge.txt

ちなみに、Gitのコミットは自分のコミット番号と親のコミット番号を持っているのですが、ここで0000000000000000000000000000000000000000となっているのは、このコミットが最初のコミットで親を持たないからです。(57c089a02b22cb27920e14c256e9140c1b19dbb5はこのコミットの番号)

現在作業しているのはmasterブランチなので、logs/refs/heads/masterも同じコミットを参照していることになります。

$ cat logs/refs/heads/master
0000000000000000000000000000000000000000 57c089a02b22cb27920e14c256e9140c1b19dbb5 tatane616 <メールアドレス> 1560681812 +0900      commit (initial): Add hoge.txt

当然refs/heads/masterも同じコミットを参照しています。

$ cat refs/heads/master
57c089a02b22cb27920e14c256e9140c1b19dbb5

objectsの中にも何かできています。

├── objects
│   ├── 22
│   │   └── 62de0c121f22df8e78f5a37d6e114fd322c0b0
│   ├── 57
│   │   └── c089a02b22cb27920e14c256e9140c1b19dbb5
│   ├── 6a
│   │   └── 73751cba5a86b1ebe10ab2856b68404aab50fd
│   ├── info
│   └── pack

objects/57/c089a02b22cb27920e14c256e9140c1b19dbb5は、いまHEADが参照しているコミットです。
コミット番号は57c089a02b2...ですが、最初の2文字でサブディレクトリを作ってobjects/57/c089a02b2...のように作られます。
オブジェクトは、このようにコミット番号(SHA1)の最初の2文字を使用して256個のサブディレクトリに配置され、オブジェクト自体のディレクトリエントリ数を管理可能な数に保ちます。

3つオブジェクトが追加されていますが、これは、1つはコミットした時のスナップショットで、2つ目はコミット情報、3つ目がコミット自体を圧縮したものです。(理解が怪しいので詳しい方いらっしゃったらコメントもらえると嬉しいです…)
git cat-file -pで見ることが出来ます。

$ git cat-file -p 2262de
hoge
$ git cat-file -p 57c08
tree 6a73751cba5a86b1ebe10ab2856b68404aab50fd
author tatane616 <メールアドレス> 1560681812 +0900
committer tatane616 <メールアドレス> 1560681812 +0900

Add hoge.txt
$ git cat-file -p 6a737
100644 blob 2262de0c121f22df8e78f5a37d6e114fd322c0b0    hoge.txt

別ブランチを作ってみる

master以外にもブランチを作ってみましょう。

$ git checkout -b feature
$ echo foobar > foobar.txt
$ git add foobar.txt
$ git commit -m "Add foobar.txt" 

.gitディレクトリの中をみてみます。

.
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           ├── feature
│           └── master
├── objects
│   ├── 22
│   │   └── 62de0c121f22df8e78f5a37d6e114fd322c0b0
│   ├── 32
│   │   ├── 3fae03f4606ea9991df8befbb2fca795e648fa
│   │   └── 7935c13bb7741628e9edd2bb423c759f513300
│   ├── 57
│   │   └── c089a02b22cb27920e14c256e9140c1b19dbb5
│   ├── 6a
│   │   └── 73751cba5a86b1ebe10ab2856b68404aab50fd
│   ├── db
│   │   └── 7d1a982785cdb9eb8c9b4ac2ae72d1f62f20ee
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   ├── feature
    │   └── master
    └── tags

いくつかの部分にfeatureが増えていますね。
HEADを見ると、しっかりfeatureに変わっています。

$ cat HEAD 
ref: refs/heads/feature

ちなみに、現在のgit logはこのようになっています。

commit db7d1a982785cdb9eb8c9b4ac2ae72d1f62f20ee (HEAD -> feature)
Author: tatane616 <メールアドレス>
Date:   Sun Jun 16 22:15:07 2019 +0900

    Add foobar.txt

commit 57c089a02b22cb27920e14c256e9140c1b19dbb5 (master)
Author: tatane616 <メールアドレス>
Date:   Sun Jun 16 19:43:32 2019 +0900

    Add hoge.txt

refs/heads/featureを見ると、現在のHEADに合致しています。

$ cat refs/heads/feature
db7d1a982785cdb9eb8c9b4ac2ae72d1f62f20ee

もっと詳しく探検したい人は

友人(@zawawahoge)が.gitディレクトリの内部でgit initして、.gitの差分をGitで確認してました、天才ですね🎉
皆さんも興味がわいたらGitのGitを作って遊んでみてください!

参考文献

tatane616
昼寝とかフロントエンドとか
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした