Gitの話†
VCSの特徴†
歴代のVCS(Version Control System: バージョン管理システム)の特徴
名称 | 環境 | 管理単位 | リポジトリ |
RCS | スタンドアロン | 単一のファイル | 単一のファイルをlock/unlock |
CVS Subversion | ネットワーク | ファイルツリー | ネット上で単一のリポジトリを共有 |
Git | 複数のリポジトリがネット上に共存 |
部構造†
Gitではコミットする度にリポジトリ内部にひとまとまりのデータ構造が作成される。
- 作成されるデータ構造の内訳
- コミットオブジェクト
一回のコミットそのものを表すデータオブジェクト。
- コミットオブジェクトを起点として、そのコミット時点の全ての情報を参照できる。
- コミットオブジェクトにはその内容から算出されるSHA1のハッシュが識別子として割り当てられる。これをコミットIDと呼ぶ。
- コミットオブジェクトはその直前のコミットオブジェクトを指し示している。これを手繰ってゆくことでコミットの履歴を新しい方から古い方へ参照することができる。
- ツリーオブジェクト
コミットオブジェクト毎に、管理しているファイルの階層関係を表すオブジェクト
- コミットオブジェクトはおおざっぱに言うとファイルの階層関係を記録しているだけ。
OSが管理するファイルシステムそのものを記録しているわけではないので、ファイルやディレクトリの属性がすべて記録されているわけではない。
特にそのファイルのオーナやグループは全く記録されていない。
- BLOB (Binary Large OBject)
ファイルの内容を保持するオブジェクト。
- ファイルオブジェクトにもファイル内容のSHA1のハッシュ値がIDとして割り当てられる。
Gitでは、BLOBのオブジェクトIDが同じであれば、実ファイルシステム上で異なるファイルであっても、あるいは全く関係ない別のリポジトリのファイルであっても、すべて「同一のもの」として扱われる。
- コミット
Gitでは、「コミット」という言葉は2つの意味を持つ。
一つは、リポジトリ内でコミットオブジェクトと、それが指し示すツリーオブジェクトとBLOBの全体を称して名詞的に使う。
例えば「コミットを取り出す」とか「2つのコミットの差分を調べる」というように使う。
もう一つは、他のVCSでも用いられる「コミットする」という動詞的な意味。
この2つの違いを意識するとGitの理解が進む(と思う)。
- ブランチ
「ブランチ」という言葉も、他のVCSとは違う使われ方をする場合がある。
- 「ブランチ」は「現在の最新のコミットを指し示すポインタ(のようなもの)」につけた名前。
あるブランチに対しコミットが追加されると、そのブランチは新たに追加されたコミットを指すようになる。
- Gitのリポジトリを作成すると、「master」というブランチが作成される。これは他のVCSでのMain Trunkのような役割を果たす。
- 「HEAD」というブランチは、「現在作業対象となっているブランチ(カレントブランチ)」を表している。
- コミットの操作
コミットの操作(コミットの再試行、取り消し、変更)関連のコマンドは種類が多く、初学者が混乱しやすい部分。
- git reset
- git checkout
- git commit --amend
- git revert
- git rebase
- git cherry-pick ...など...
これらはそれぞれのコマンドを実行することによってコミットオブジェクトがどのように変化するかを比較してみると、それぞれのコマンドの意味が理解しやすい(と思う)。
分散リポジトリ†
Gitでは複数のリポジトリを設置し、リポジトリ間でコミットを送受信することができる。
Gitの仕組み的には、全てのリポジトリは対等。
通常は、基点となるリポジトリを設け、そのリポジトリから複製した別のリポジトリ上で作業を行い、その作業結果を基点となるリポジトリに集約する「中央リポジトリ方式」がよく使われる。
複製(クローン)したリポジトリ内には、複製元のリポジトリの状態を記録するための特殊なブランチが存在し、これを「追跡ブランチ」と呼ぶ。
- リモートリポジトリに手元の追跡ブランチを同期させる操作をフェッチ(fetch)と呼ぶ。
- プル = フェッチ+マージ
- ローカルブランチの内容をリモートリポジトリに送りつける操作をプッシュと呼ぶ
リモートリポジトリを操作するには、
- ローカルリポジトリに存在するブランチ
- ローカルリポジトリ内の追跡ブランチ
- リモートリポジトリ内に存在するブランチ
を明確に区別して指定する必要がある。このための記法をrefspec (参照仕様)と呼ぶ。
参照仕様の理解もGitを使う上でのポイントの一つ(と思う)。
#img(): File not found:
おすすめドキュメント†
ネット上、書籍共に数多くありますが…。
ツールとか†
- リポジトリ管理
中央リポジトリをウェブベースで管理するツール。GitHub.comのインターフェースを参考に作成されている。
リポジトリだけでなく、ユーザアカウント管理、イシュートラッカー、Wikiといったプロジェクト管理機能も同時に実装されている。
- GitLab
コミュニティ版、エンタープライズ版、SaaS版、ホストサービスが提供されている。
単一のリポジトリ内で、コード提出→レビュー→承認といったフローを想定していため、承認要請は「プルリクエスト」ではなく「マージリクエスト」である。
Ruby on Railsで記述。
- GitBucket
個人(竹添氏)によるもの。Scalaで記述。
「Github Enterpriseは高いしOSSではない、GitLabはインストールやバージョンアップがめんどくさい、という隙間を狙ったプロダクト」とのこと。
開発フロー†
作業用ブランチ(トピックブランチ)の作成やマージといった作業フローについては、様々な議論があるようだ。
例えば、
など。
- VCSは時代を反映する
今回Gitを使うようになって感じたことの一つ
- RCS ... IPネットワーク以前。一台のマシンに全員がTSSでログインして作業するイメージ。
→一つのファイルはある時点では一人しかいじれない。
- CVS, svn ... IPネットワーク普及後。リポジトリはネットワーク経由でどこからでもアクセス出来るようになった。
→ファイルを複数人で並行していじれように。
- Git ... 大容量のストレージが個人レベルで入手可能に。ネットワークも高速な回線が常時使用可能なのがあたりまえ。
→リポジトリは全員が持てばいい。コミットも差分などは取らずそのまま保存。
- 黒い画面怖い
Gitについて色々調べている過程で目についたフレーズ。
Gitは今ではメジャーなソフトなので、インフラ寄りはないエンジニアやウェブのデザイン系の人達も使う機会が多いようだ。彼らはCLIに馴染みがないためこのようなフレーズが発せられる模様。
前述のようにGUIのクライアントもあるが、コマンドラインでの操作をする必要がまったくなくなったわけではない。
- GUIでカバーしていないニッチな機能を使う必要が生じた場合
- SSHのような、Gitを使う上で必要となる周辺技術
- VCSには他のソフトにはない独自の概念が多くあり、それらが可視化されていないCLIではやりたいことと実際の操作の関連がわかりにくい。
- ほんこれ
ロブ・パイクは「Programming in C」の中で、以下のように述べている;
Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self evident. Data structures, not algorithms, are central to programming.
データがソフトウェアの主役である。データ構造を適正に選び、それを適切に構成すればアルゴリズムは自ずと自明なものになる。アルゴリズムではなく、データ構造がプログラミングの根幹である。
今回Git習得の過程でこのことを実感した。