180
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-06-16

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を作って遊んでみてください!

参考文献

180
138
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
180
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?