2014.12.09
Gitの中身を見てみよう!vol.1 – 配管(Plumbing)と磁器(Porcelain)(Advent Calendar 9日目)
こんにちは。アドベントカレンダー9日目を担当する佐藤(ま)です。
アライドでは「大佐」と呼ばれております。
今回から git-scm.com をみながら Git (.git) の中身をみていってみようと思います。(まぁ他にもいろいろ記事はありますが書きたかったので気にせず垂れ流していこうと思います。)現在の Document には、v1 と v2 がありますが、v2 は途中まで日本語化されていて、日本語で見たい方はこちらに参考サイトがあります。(もちろん英語のままでもだいじょうぶですが)
配管(Plumbing)と磁器(Porcelain)
そもそも Git には大きく配管(Plumbing)コマンドと磁器(Porcelain)コマンドがあり、普段良く使うコマンドは、ユーザフレンドリーなコマンドとして、磁器(porcelain)コマンドとよばれ、下位レベルの仕事を行うためのコマンドが、配管(Plumbing)コマンドと呼ばれます。
配管(Plumbing)コマンドは、
Gitの内部動作にアクセスして、Gitの内部で、何を、どのように、どうして行うのかを確かめるのに役に立つ
ということなので、今回からは配管(Plumbing)コマンドを使っていくことになります。コマンドリファレンスでいうところの、こちら↓になります。
では早速上記 Document を元に .git の中身をみていこうと思います。
git init を実行した直後のデフォルトリポジトリ
まず、git リポジトリを初期化した直後の .git 内の構成を確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
% mkdir plumbing % cd plumbing % git init % cd .git % ls -l -rw-r--r-- 1 HEAD -rw-r--r-- 1 config -rw-r--r-- 1 description drwxr-xr-x 11 hooks drwxr-xr-x 3 info drwxr-xr-x 4 objects drwxr-xr-x 4 refs (branches (v2にはない)) |
HEAD ファイル
現在チェックアウトしているブランチ
中は以下のように書かれています。
1 |
ref: refs/heads/master |
config ファイル
自分のプロジェクト固有の設定オプション
remote 情報などはここに記載されます。
description ファイル
GitWeb プログラムのみで使用
hooks ディレクトリ
クライアントサイド、またはサーバサイドのフックスクリプトが含まれる。
hooks の下は、以下のようにサンプルスクリプトが用意されているので利用する際は、.sample をコピーして使ったりします。フックについては、こちら(7.3 Git のカスタマイズ – Git フック) に詳細が書かれています。
1 2 3 4 5 6 7 8 9 10 |
# hook sample -rwxr-xr-x 1 applypatch-msg.sample -rwxr-xr-x 1 commit-msg.sample -rwxr-xr-x 1 post-update.sample -rwxr-xr-x 1 pre-applypatch.sample -rwxr-xr-x 1 pre-commit.sample -rwxr-xr-x 1 pre-push.sample -rwxr-xr-x 1 pre-rebase.sample -rwxr-xr-x 1 prepare-commit-msg.sample -rwxr-xr-x 1 update.sample |
info ディレクトリ
追跡されている .gitignore ファイルには記述したくない無視パターンを書くための、グローバルレベルの除外設定ファイルを保持する。
.gitignore で共有したくなく、自分のローカル環境でのみ無視したい場合に使えます。
objects ディレクトリ
データベースのすべてのコンテンツを保管
refs ディレクトリ
ブランチ内のコミットオブジェクトを指すポインターを保管
index ファイル
Git がステージングエリアの情報の保管する場所を示す
※ 初期化時には作成されない
中でもGit の中核(コア)部分に相当するのが、HEAD,objects,refs,indexで、これらが .git の中でも重要なエントリとなります。
Git は連想記憶ファイル・システム
Git は連想記憶ファイル・システムです。素晴らしい。…で、それはどういう意味なのでしょう?それは、Git のコアの部分が単純なキーバリューから成り立つデータストアである。
記述にあるように、Git が単純なキーバリューストアであるというのを簡単に確認してみようと思います。
hash-object コマンド
hash-object コマンドでは、.git/objects/ ディレクトリに、オブジェクトを格納することができます。まず、.git/objects ディレクトリに移動してみると空の info と pack が存在しているのがわかります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
% ls -l -rw-r--r-- 1 HEAD -rw-r--r-- 1 config -rw-r--r-- 1 description drwxr-xr-x 11 hooks drwxr-xr-x 3 info drwxr-xr-x 4 objects drwxr-xr-x 4 refs % cd objects % ls -l drwxr-xr-x 2 info drwxr-xr-x 2 pack |
そこで以下のコマンドを発行すると、40文字から成るチェックサムのハッシュ値が出力されます(SHA-1ハッシュ)。サブディレクトリは、SHA-1ハッシュのはじめの2文字で名付けられ、残りの38文字でファイル名が決まります。
1 2 3 4 5 6 7 8 9 10 11 |
$ echo 'test content' | git hash-object -w --stdin d670460b4b4aece5915caf5c68d12f560a9fe3e4 $ ll drwxr-xr-x 3 d6 drwxr-xr-x 2 info drwxr-xr-x 2 pack $ cd d6 $ ll -r--r--r-- 1 70460b4b4aece5915caf5c68d12f560a9fe3e4 |
d6 と 70460b4b4aece5915caf5c68d12f560a9fe3e4 を合わせると40文字となります。
cat-file コマンド
cat-file コマンドは、格納したオブジェクトのコンテンツを Git の外に引き出すことができます。
1 2 |
% git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4 % test content |
hash-object コマンドで Git にコンテンツを追加し、cat-file でそれを出力しました。
では、これらを使って、あるファイルのバージョン管理の動作を確認してみようと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
% cd [リポジトリホーム] % echo 'version 1' > test.txt # この時点ではまだ .git/objects にはなにも書き込まれていません。 % git hash-object -w test.txt 83baae61804e65cc73a7201a7252750c76066a30 % echo 'version 2' > test.txt % git hash-object -w test.txt 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a % find .git/objects -type f .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 |
test.txt ファイルに version 1 と version 2 を書き込みましたが、objects ディレクトリ配下にデータを保持しているので、ファイルを最初のバージョンにしたり、2つ目のバージョンにしたり切り替えることができます。
1 2 3 4 5 6 7 |
% git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt % cat test.txt version 1 % git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt % cat test.txt version 2 |
オブジェクトのタイプ
また、cat-file -t コマンドに SHA-1キーを渡すことで、あなたは Git 内にあるあらゆるオブジェクトのタイプを問い合わせることができます。
これらのオブジェクトにはタイプがあり、今回作成したオブジェクトは、バイナリデータを扱うデータ型である blob となります。
1 2 |
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a blob |
オブジェクトのタイプは他にも存在しますが、次回以降に確認してみようと思います。
今回 git-csm.com の Documentをみながら確認していきましたが、結果的にほとんど Document の内容をなぞる形になってしまいました。ただ、読むだけじゃなくて、読みながら色々試したりしたことで Git の仕組みへの理解が深まりましたので、興味のある方は是非試してみてください。
明日は、 sekine の番です。
よく使うであろうことをできるだけ分かりやすく発信していきます。 Gitの情報を無駄にキャッチアップしてます。