git入門 ~仕組みを理解する~ 第2回 リポジトリのcommitツリーをイメージする
今回が一番重要な回です。
commitツリーをイメージできる状態になればgitの半分は理解できたと思っていいです。
「gitが難しい」と言われている方の大半はこのcommitツリーがイメージできていない状態でコマンドだけを覚えて作業している方が多いので、しっかりとイメージできるようにしましょう。
commitとは?
commitを一言でいうと、
gitリポジトリでバージョン管理するためにファイルやフォルダをまとめたデータ
です。
commitを理解するためにはcommitでできること(特徴)がわかるとそのあとのcommitツリーについても理解が深まります。
gitのcommitのできること(特徴)を簡単に説明すると以下の6点です。
- ファイルやディレクトリをcommitと呼ぶ単位にまとめて管理する
- commitは任意のタイミングで作成することができる
- commitには名前が付与される
- commitは親子関係が形成され履歴管理される
- 作成したcommitは名前を指定することでいつでも取得できる
- 他のgit環境とcommitの情報を交換できる
文字で見てもわかりづらいので図示してみましたので、commitでできることを順番にイメージしてみましょう。
現時点では、はっきりと理解できなくでも大丈夫です。なんとなく「こんなことができるのか~」というレベルでOKです。
ファイルやディレクトリをcommitと呼ぶ単位にまとめて管理する
「directory-A」の中に「file-A」と「file-B」がある状態を保存したいと思った場合に、3つのオブジェクトを1つのcommitとして管理することができます。
commitは任意のタイミングで作成することができる
「任意のタイミングで」というのは上の図の状態にではなく「file-B」を作成する前の状態を保存したいと思った場合にでも、commitとして管理することができます。
commitには名前が付与される
commitは作成するとgitが名前を付与します。
commitオブジェクトをもとにhash関数で取得した40文字の文字列がcommitの名前(commit-hash)として設定されます。
commitは親子関係が形成され履歴管理される
commitは作成すると元になったcommit(親commit)を記録することでバージョン履歴を管理しています。
以下の例は、ファイルを1つ作成するタイミングでcommitを作成した場合です。
作成したcommitは名前を指定することでいつでも取得できる
commitは40文字のhash値からなる名前(commit-hash)を指定することで、ディレクトリやファイルを取得することができます。
以下の例では「commit-A」と「commit-B」がある状態で「commit-A」の状態のディレクトリとファイルを確認したいとなった場合に、commitの名前である「commit-A」を指定して取得することができます。
他のgit環境とcommitの情報を交換できる
git環境(リポジトリ)は他のgit環境(リポジトリ)から指定したcommitやリポジトリ全体の最新のcommitを取得するなどできます。
また、逆に他のgit環境(リポジトリ)にcommitを渡すこともできます。
commitは3つのステップで作成する
commitについてなんとなくイメージできてくれば、次はcommitの作り方について学んでいきましょう。
実際のgitコマンドを実行する前に、少し抽象化した図で表現するようにしましたので、commitができるまでの流れを覚えましょう。
commitは3つのステップで作成していきます。
- 作業場所でディレクトリやファイルを作成する
- ファイルに名前をつけて倉庫に保管し、梱包エリアでファイルリストを作成・修正する
- 梱包エリアで作成したファイルリストにディレクトリ情報や親commit情報などを追加したリストを作成し、リストに名前をつけてを倉庫に保管する。この倉庫に保管したリストを「commit」と呼びます。
では、それぞれの作業を詳細に確認していきましょう。
Step 1 作業場所でディレクトリやファイルを作成する
作業場所はファイルの作成や編集を行うエリアです。
作業場所で、以下の操作を行ったとします。
- dir-Aを作成
- dir-Aの中にfile-Aを作成
- dir-Bの中にfile-Bを作成
まだ、特にgitは関係ありません。
普通のディレクトリ内にファイルやディレクトリを作成しただけです。
Step 2 梱包エリアでファイルリストを作成・修正する
作業場所でファイルやディレクトリの作成が完了したら、次はcommitを作成する準備として、梱包エリアでcommit対象とするファイル一覧を作成します。
また、作成したファイルを名前を付けて倉庫に保管します。
ここでは、倉庫に格納する際の名前をそれぞれ、「hash-B」と「hash-C」とします。
勘のよい方ならお気づきですねcommit-hashの際に説明しましたとおり、実際の名前は40文字のhash値です。
Step 3 倉庫にcommitを保管する
commit対象のファイルを倉庫に保管し、ファイル一覧が作成されている状態であれば、commitを作成することができます。
まず、梱包エリアのファイル一覧にディレクトリがある場合は、倉庫にディレクトリオブジェクトに名前を付けて保管します。
ここでは名前を「hash-A」とします。そしてファイルと同じく40文字のhash値です。
最後に、commitを作成します。commitには次の情報を記録します。
- ファイル一覧に紐付く倉庫に保管されたディレクトリの名前(hash値:hash-A)
- ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash値:hash-B、hash-C)
- commitの名前(hash値:commit-hash-A)
倉庫には「commit」以外に、「ディレクトリ」や「ファイル」も保管されhash値の名前が付けられています。
そして、「commit」はファイルやディレクトリそのものではなく、それぞれのhash値を記録していることです。
commitツリーをイメージする
ここまでで、1つのcommitができるまでについてを学んできました。
次は、今回のメインであるcommitを複数作成し、commitツリーをイメージできるようになりましょう。
簡単なシナリオに沿って確認してみましょう。
1つ目のcommit-Aを作成
作業場所でfile-Aを新規作成
file-Aに名前(hash-A)を付けて倉庫に保管し、梱包エリアでファイル一覧にfile-Aを記録する
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-A)をcommitに記録し、名前をcommit-hash-Aとして倉庫に保管する
2つ目のcommit-Bを作成
作業場所でfile-Bを新規作成
file-Bに名前(hash-B)を付けて倉庫に保管する
梱包エリアでファイル一覧にfile-Aとfile-Bを記録する
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-Aとhash-B)をcommitに記録し、名前をcommit-hash-Bとして倉庫に保管する
また、commit-hash-Bには変更元のcommitがcommit-hash-Aと記録する
3つ目のcommit-Cを作成
作業場所でfile-Cを新規作成
file-Cに名前(hash-C)を付けて倉庫に保管する
梱包エリアで一覧表にfile-Aとfile-Bとfile-Cを記録する
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-Aとhash-Bとhash-C)をcommitに記録し、名前をcommit-hash-Cとして倉庫に保管する
また、commit-hash-Cには変更元のcommitがcommit-hash-Bと記録する
2つ目のcommit-Bを取得する
倉庫からcommit(commit-hash-B)を取り出す
取り出したcommitの内容を梱包エリアに持ってくる
ファイル一覧はfile-Aとfile-Bが記録された状態になる
作業場所にfile-Aとfile-Bを配置する
4つ目のcommit-Dを作成する
作業場所でdir-Aを作成しdir-Aの中にfile-Dを新規作成
dir-Aに名前(dir-hash-A)を付けて倉庫に保管する
file-Dに名前(hash-D)を付けて倉庫に保管する
梱包エリアで一覧表にfile-Aとfile-Bとfile-Dを記録する
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-Aとhash-Bとdir-Aとhash-D)をcommitに記録し、名前をcommit-hash-Dとして倉庫に保管する
また、commit-hash-Dには変更元のcommitがcommit-hash-Bと記録する
5つ目のcommit-Eを作成する
作業場所でfile-Aを削除する
梱包エリアでファイル一覧からfile-Aを削除し、ファイル一覧にfile-Bとdir-Aとfile-Dが記録された状態にする
※倉庫からfile-Aは削除されない
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-Bとdir-Aとhash-D)をcommitに記録し、名前をcommit-hash-Eとして倉庫に保管する
また、commit-hash-Eには変更元のcommitがcommit-hash-Dと記録する
6つ目のcommit-Fを作成する
作業場所でfile-Bを修正する
修正後のfile-Bに名前(hash-B2)を付けて倉庫に保管する
梱包エリアでファイル一覧にfile-Bとdir-Aとfile-Dを記録する
ファイル一覧に紐付く倉庫に保管されたファイルの名前(hash-B2とdir-Aとhash-D)をcommitに記録し、名前をcommit-hash-Fとして倉庫に保管する
また、commit-hash-Fには変更元のcommitがcommit-hash-Eと記録する
まとめ
今回は、かなり長くなってしまいましたが、ポイントをまとめると
commitには以下の特徴がある
- ファイルやディレクトリをcommitと呼ぶ単位にまとめて管理する
- commitは任意のタイミングで作成することができる
- commitには名前が付与される
- commitは親子関係が形成され履歴管理される
- 作成したcommitは名前を指定することでいつでも取得できる
- 他のgit環境とcommitの情報を交換できる
commitは作業場所と梱包エリアで準備し、倉庫に格納する
commitは倉庫の中でツリー上に履歴管理される
次回は作業場所、梱包エリア、倉庫について実際のgitのフォルダやコマンドで学んでいきましょう。