【Git】ざっくり概念・構造理解編


Gitの概念や構造をざっくりと、

運用的概念、設計思想についてはこちらを

活用に必要な概念

開発の管理は主に設定ファイルやソースの管理と言っても差し支えません。これらのソースはテキストが主で、ディレクトリ構成をしています。

また、変更を加えるということは、時間経過で中身が変わっていきます。つまり同名でも中身が違うので、それを管理する必要があります。

さらにできれば作業中にその管理内容を、自動的に保存したり、確認(testやdiff、参考など)したり、ベースとして引用したりしたいですよね。そのためのツールや、その時々のスナップショットのラベリング(命名規則)があります。

そのため、ファイルの管理スナップショットの管理、上記のようなパッチ・変更等の作業支援がGitの主な役割です。

なので、どこで作業するのか、ファイルをどう管理するのか、その時のファイルリストを管理するのかに注意して、Gitを理解していくと、骨格が見えてきます。次からそこに注意しながら読んでいってください。

ワーキングディレクトリ
ステージング
ストレージ
checkout
ステージング
コミット

Gitで出てくる主な領域

Gitを使うにあたって、おもな登場人物を先に説明して、その次に主なオブジェクトとデータ構造を説明します。

活用に必要な概念として、次の3つの領域違いを意識しておくとGitが理解しやすくなると思います。

それぞれの対応関係を理解する一助として、流れを説明すると、最初にワーキングディレクトリを作ってPC内に作業場所を確保します。そこでソースを修正(追加、変更、削除等)したあと、ステージングにあげ、変更点の最終確認をします。ソース群のスナップショットはストレージに保存します(コミット)。

以後、修正するたびにストレージから出して同様のサイクルを繰り返します。次回以降のスナップショットは前回のスナップショットと繋がりも保持することで、履歴がたどれるようになっています。

また、レポジトリとしては、リモートも活用可能で、リモートレポジトリと同期できる仕組み(ローカルレポジトリ(上記レポジトリ)とリモートレポジトリの動機)があります。

Gitにおける活用領域 目的
作業領域 ワーキングディレクトリ
プレコミット領域 ステージング領域
ストレージ スナップショットを保持するレポジトリ領域

作業領域

ソースを変更したり、動作を確認したりする領域です。大抵トップディレクトリに.gitを置いてソース管理します。

ディレクトリの管理やバージョンの変更、パッチあてが簡単にできるように、gitでは作業領域をきれいに準備してくれます。

つまりユーザ以外にgitもこの箇所を変更するので、ぼぅっと作業するとユーザのファイルが消えた!って思うこともあるかと思います(ただ単に自分からGitに対してほかのコミット状態にワーキングディレクトリ上のファイルをすべてクリアして、上書きさせているだけ)。

ステージング領域

コミット作業前の、プレコミット領域です。コミット対象の過不足の確認や修正点の確認をします。実質フィルターがかかるので、プロジェクト対象のファイルが多くてもすっきり確認できます。見落としも少なくなります。

※データ構造的には、ただのコミット単位です。運用上意味があるのでgit commandでは別の扱い方をします。

このステージングステップを通じて、ストレージであるレポジトリ領域に新たなスナップショット(ファイルリストとファイルの実体)がワーキングディレクトリからレポジトリへコピーして保存されます。

ストレージ領域

カレントディレクトリの.git配下にある 領域です。おもに次の2つを抑えておけばよいと思います。そのほかには設定ファイル、ログファイル(作業履歴:日付け、作業者)等があります。

  • ファイル(同名でも、中身が違えば別管理)
  • コミット単位(ファイルリスト)
Gitでファイル管理対象を追加(stagingへのadd)時に、スナップショットとして、コミット情報とファイルが追加されます。過去のスナップショットを取り出すとき(checkout) 主にここから情報を引っ張って、ワーキングディレクトリへ展開します(ワーキングディレクトリの内容は消える)

Gitに出てくる主なオブジェクト概念

領域を話しましたが次は、オブジェクト寄りの概念を説明します。


概念 オブジェクト 場所
ファイル blob .git/objects/
スナップショット、コミット リファレンス .git/refs/
ステージングリスト、タグ、ブランチ リファレンス .git/refs/
ディレクトリ tree .git/objects/

ファイル

ファイルは、そのまま格納されます。ただ変更があった場合同名でも別オブジェクトとして扱います。 blobについては後述

ディレクトリ構造とスナップショット(リファレンス)

スナップショットやコミット単位、ディレクトリは、全てファイルリストです。indexもファイルリストです。 ディレクト構成は tree型のリンク構造で1階層ずつ表していますので、 treeの中は tree またはblobがあります。

スナップショットやタグ等も、気づいた人もいるかもしれませんが、ファイルリストにほかなりません。つまりHEADなどのリファレンスは、他のリファレンスまたはtreeを指しています。 stagingで追加した場合も、空のtreeにファイルindexとblobが追加され、結果的にコミットするときにコミット単位のtree情報が出来上がっていることになります。

コミットリファレンス図 (矢印は親コミットを指す)
A
B
C
H
Object Tree図 (矢印は参照先を指す)
P



Git - リセットコマンド詳説
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%83%AA%E3%82%BB%E3%83%83%E3%83%88%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E8%A9%B3%E8%AA%AC
Git - リセットコマンド詳説

stashによる一時退避も、カレント作業のコミットを指すHEADも index(ステージ)もすべて、ファイルリストへのリファレンスです。

上記でcommti時ではなく、staging時なの?と感じた人もいるかもしれません。staging時に保存することで、上記のようにシームレスにtreeとリファレンス情報が作成されます。

また、パッチ等の確認やテスト確認として、一時的な作業領域があると、差分確認や、作業も戻し等もスムーズになります(つまり作業支援)。

もともと数千のパッチワーク作業に耐えうるよう、作業環境の変更・確認がすぐにできるようになっています。アルゴリズムとしては、実体を直接扱うのではなく、ワンクッションリンク(参照)という構造をとって拡張性(ソース管理でいう変更耐性)があるのです。ワーキングディレクトリにゴミファイルがあろうとも、commit時には問題なくまとめて間違いなく保存できるのです。

細かな設計思想はページの初めで紹介したリンク先を読んでみてください。

確か、ごみのblobは後(gc)で整理されると思います。

ブランチ

Gitでは、くどく言いますが、コミット単位にファイルリストを管理しています。さらに一つ前のコミット対象のリンクも保持しています。

※リンク構造は、組み換えが素早く、簡単にできる。

git内部的には、hash IDがありますが、人側としてはそれは大変ですのでラベルを付けらることができます。一連の系列、そのコミット系列の流れブランチと言います。trunckという概念もありません。masterもブランチです。ネーミングの初期値という意味しかありませんので変更も可ですし、変更しても影響はありません。特別な扱いもgitではしません。運用チームで判断するだけでOKです。

その他リファレンス関連でよく出てくる概念にHEADがあります。HEADというのは、現在作業しているブランチのcheckoutしたものを指しています。間接参照です。コミットするとHEADも動きます。checkoutしてもHEADは動きます。しかし、個々のコミット情報には変更ありませんし、変更の必要もありません。

TAGも同様にある一点のコミット時点のファイルリストを指すことができます。

こうすることで以下の3つのメリットがあります。

  • 好きなコミットタイミングの環境を自由にすぐに作れる
  • 過去の情報や経緯、流れ、文脈が確認しやすい。
  • 3wayマージの時、2wayに比べ、差分範囲を局所化でき競合の可能性も少なく、全体を正確に把握していなくても、各担当者が最新版に対してマージをしやすい。同様の理由から、各自が好きな開発を進めることができる(分散レポジトリ)。

データ構造

blob

ファイルはzlibで圧縮され、storageに保存されています。名前はsha1に通した一連のユニークIDに振り、上2ケタはフォルダ名、下2桁をGit管理上のファイル名に置き換えます。

これによって、ファイルが変われば新しいオブジェクトが作られ、同名でも混乱せずにファイルリストを管理することができるのです。

またhashになっているため、ファイルが壊れたり、ディスクが壊れたかどうかもすぐ確認できますし、スムーズに目的のファイルにもアクセスすることができます。

このように1文字でも変わったら別ファイルとなるため、巨大なファイルの扱いは苦手でしたが、packによる辞書式ではなく、差分の圧縮方法を取り入れ、さらに圧縮率を高めます。

ただし同系列ですぐ圧縮してしまうと、ほかのソース管理システムのように、ソースがスムーズに取り出せなくなってしまいます。

データ構造についてはの中ほどを確認してください。

【Git】そろそろGitをしっかり理解しておきたい時向けの勘所を狙って説明してみるチャレンジ

まとめ

gitはスナップショット単位、つまりファイル構造を管理している。

次回

次はユースケースごとの、スナップショットを意識したうえで、影響範囲を絡めて、よく使われるコマンドを確認していきます。

次回:ユースケースご別よく使うコマンド

Delicious にシェア
Digg にシェア
reddit にシェア
LinkedIn にシェア
LINEで送る
email this
Pocket

25 views.



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です