2017/12/12更新

[git] Gitの内部(はじめに)

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
最近Pro Gitという本を読んでいます。 今日は、その本から学んだgitの内部について、はじめの部分をブログに書きたいと思います。

画像

Special Thanks to http://flic.kr/p/aWTB1r



Gitの内部を学ぶことの意義

Gitの内部構造や実装を学ぶことで、Gitがどのように動作しているかを理解することができ、その結果としてより便利に強力にGitを使えるようになります。 Gitの内部を学習する意義は、この点が一番大きいですね。

gitは、連想記憶ファイルシステム(content-addressable filesystem)上に構築されたバージョン管理システムである、という点を理解しておく必要があります。この点は他のバージョン管理システム(SVNなど)とは異なる点で、gitの大きな特徴です。

SVNなどのバージョン管理では、1つのファイルはコミットごとにコミット前後の差分を保持します。しかしGitでは、特定のファイルの特定のリビジョンに対してハッシュ値を生成し、そのハッシュ値を用いてその時のファイルにダイレクトにアクセスすることができます。

gitのバージョン1.5より前では、このファイルシステムという考えが押し出されていたため、少し複雑で使いづらいUIとなっていたようです。 しかし最近では、gitのUIは再定義され、使い勝手は少し改善されました。

この連想記憶ファイルシステムという仕組みについては、次回以降に詳しく取り上げたいと思います。 今回のブログでは、それを説明する前段となる部分を解説します。



一般的なUIと内部的なUI

Gitには、一般的に利用される機能(pull, commit, add, push, branch,など)がたくさん存在します。git helpを使って、どのようなコマンドがあるかを調べることができます。
$ git help
The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty Git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and merge with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG
そして上記の一般的に良く利用する機能以外にも、様々な内部コマンド(=下位レベルのコマンド)が存在します。 例えば、git hash-objectgit cat-filegit write-treeなどです。

gitの内部を知るためには、それらの内部コマンドを利用することになります。 gitの内部コマンドを使うことで、Gitの中で何がどのように動作しているのかを知る手助けとなります。 それぞれの内部コマンドは、必要な場面でそれぞれ説明できればと思います。



gitレポジトリの構造

ここでは、gitレポジトリの構造について説明します。 まずは、git initコマンドでレポジトリを新規作成してみましょう。
$ git init
Initialized empty Git repository in /Users/munesadayohei/tmp/test/.git/
git initを実行すると、.gitディレクトリが作成されました。 この.gitディレクトリは、Gitにおいてコアとなる存在なのです。 例えばgitレポジトリをバックアップしたりクローンしたい場合には、この1つのディレクトリをどこか違うディレクトリにコピーすれば、 必要なことのほとんど全てができてしまいます。 Gitの内部構造を知るために、以降ではこの.gitディレクトリを中心に扱っていきたいと思います。

それではさっそく、先ほど作成したレポジトリの.gitの中を見てみましょう。
$ ls .git
HEAD
branches/
config
description
hooks/
index  # もしかしたらこれは最初は無いかも
info/
objects/
refs/
.gitディレクトリは、上記のファイルやディレクトリで構成されています。 既に利用中のレポジトリの場合には、他にもいくつかのファイルが存在するかもしれません。

これらの中で特に重要なものは、HEADファイル、indexファイル、objectsディレクトリ、refsディレクトリです。それぞれの構成要素の役割は、以下の通りです。
objects
このディレクトリは、gitレポジトリの実際のデータ(プログラムファイルや画像など)を全て保管しています。
refs
このディレクトリは、データ(やブランチ)内のコミットオブジェクトを指すポインターを保持します。
HEAD
このファイルは、チェックアウトしているブランチを指し示します。
index
このファイルは、Gitがステージングエリアの情報を保持する場所です。
これらの構成要素を利用してバージョン管理を行います。
なお、上記以外にも以下の要素が.gitには含まれます。
config
このファイルは、プロジェクト固有の設定内容(リモート先やサブモジュールなど)の情報を保持します。
description
このファイルは、GitWebプログラムで利用されるファイルです。
info
このディレクトリは、.gitignoreには書きたくないような追跡除外パターンを書くための、グローバルレベルの除外設定ファイルを保持します。
hooks
このディレクトリは、クライアントサイドやサーバーサイドで利用するフックスクリプトを保持します。
これらの構成要素も便利なものではありますが、gitの内部構造や動作を学習するためにはあまり重要でないため、以降では扱わないと思います。



参考資料

Gitの内部挙動を理解するために、以下の資料を参照しました。ありがとうございます。

Pro Git | git-scm.com/book



最後に

今回は、gitの内部についてのはじめの部分を扱いました。.gitディレクトリがGitではキーとなる要素なんですね。 次は、バージョン管理で保管されている対象そのものであるobjectについて、見ていければと思います。

最後までご覧頂きましてありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。