Gitの使い方2

Gitの用語説明

Gitはコマンドやら何やらの専門用語が多い上に、その概念が複雑なために分かりにくい。筆者も細かいことは把握できていないのでとりあえず共同開発に最低限必要と思われるところまで頑張って説明する。

かなり細かく話すので、そんなんいいから使い方だけ教えてという人はこちらからお願いします。 使った後に読む方が分かりやすいかもしれない。

まずGitの流れは次のような図になっている。

../_images/git-commands.png

Gitでのクローンのやり方より図を引用。(その内画像を差し替えます。)

初めて見ると何が何だか...という感じだと思うが、かなりよくまとまっている方だと思うのでこの図にしたがって説明する。まずは用語について説明する。

前提知識

  • リポジトリ(Rep.)

データの保管庫や管理庫というイメージをしてほしい。注意してほしいのはファイルを含んでいるディレクトリそのものを指し示す言葉ではなく抽象的な概念に近いということである。

個人的にはディレクトリが単にファイルを格納するための具体的な置き場であるのに対し、リポジトリはファイルやディレクトリを管理する体制や領域だと思っているが、人によってリポジトリの認識にも差があるように思う。

さらにリポジトリにはローカルリポジトリリモートリポジトリの2種類がある。自分の手元のPCのデータ保管庫がローカルリポジトリであり、GitHub上のデータ保管庫がリモートリポジトリである。イメージが湧きにくいと思うのでローカルリポジトリで説明する。

後で具体的に説明するが、クローンと呼ばれる操作によりGitHub上のデータ保管庫を手元のPCのどこかのディレクトリに複製することができ、複製したものをローカルリポジトリと呼ぶ。クローンをした場合例えば以下のようなディレクトリ構造になる。ここではDIRというディレクトリに入ってクローンを行った結果homepageというディレクトリが作られている。

DIR

└─homepage

​    ├─ aaa.html

​    ├─ bbb.html

​    ├─ ccc.css

​    └─ .git

aaa.html, bbb.html, ccc.cssはリモートリポジトリに置いてあった編集対象のファイルとする。.gitはGitでローカルリポジトリのバージョンや編集履歴等を管理するのに必要な情報を含むファイルがまとめられたディレクトリである。これらの編集対象のファイルや.gitをまとめてローカルリポジトリという。

そのためじゃあ結局homepageのディレクトリ=ローカルリポジトリじゃん

と考えると半分正解で半分不正解な気がする。ローカルリポジトリの実体としてはそうかもしれないが、あくまで管理体制である。homepageというディレクトリがGitの管理下にあってローカルリポジトリとなっているということだ。

  • 作業ツリー(ワークツリー)

これは単にファイルの加筆や編集をするディレクトリのことである。上のディレクトリ構造で言えばhomepageディレクトリであり、aaa.htmlや.gitと同じ位置の階層である。

作業ツリーが具体的なディレクトリを指すのに対しリポジトリは概念的な領域を指すことに注意しよう。

  • インデックス(ステージ)

これもリポジトリと同じように概念的な領域だ。ファイルを変更等した際、変更したよーという記録をリポジトリに登録する。これをcommitというがcommitの前にaddという操作を含む(もう一度改めて説明する)。addはcommitしたい対象を選定するという操作だが、この操作を行われたファイル等はインデックスステージに入ることになる。但し実際にどこかのディレクトリに入るという訳ではない。

とにかくcommitの対象を一時的に置いておく領域がインデックスである。

Gitのコマンド

  • clone(クローン)

cloneコマンドによってGitHub上のリモートリポジトリをローカルに複製することで共同開発がスタートする。もし自分1人の開発の場合は当然リモートリポジトリには何のデータもないが、基本的にGitHubのアカウントを作成するとその場(Web上)でリポジトリを試しに作成することになるはず。大体READMEを書かされてREAMDのみが含まれるリモートリポジトリが作成できる。そのためこのREADMEのみが含まれるリモートリポジトリをクローンすることで、手元にローカルリポジトリが作成できる。

その他Gitを大々的に使うという訳でなくても、単にコードのダウンロードとしてgit clone <url>を使用することも可能。実際T先輩のlammpsインストールではこのようにしてzipファイルをダウンロードしている。

  • branch(ブランチ)

ブランチというのもGitを使う上では重要な概念となる。このブランチが共同開発の肝である。

ブランチとは履歴の流れを分岐して記録していくためのものである。分岐したブランチは他のブランチの影響を受けないため、同じリポジトリ中で複数の変更を同時に進めていくことができる。そのため複数人での開発に適している。具体的に説明していこう。

../_images/branch.jpg

電脳世界「git branch コマンドでブランチを作成する方法」より図を引用

例えばXさん、Yさん、Zさんの3人で開発を行うとする。Xが中心となって開発を進めてAからBへと更新を行った。そのタイミングでYとZも開発に加わった。しばらくX, Y, Zは独立に開発を行い、AがBからC、Dへと更新をした。その後Yさんの開発が終わったのでXさんの開発していたDにC'を統合した。さらにZさんも開発が完了したのでDから更新したEにC''を統合した。

このように各々が同じソースを使って別々のものを作り、その過程では相手に影響を与えずに最後に統合するという流れがGitを用いた開発の主な流れである。この流れこそがブランチである。

またXさんが開発を進めた本家や源流とも言うべきブランチをGitではmasterブランチmainブランチと呼ぶ。

さらにYさんやZさんのようにmasterブランチから派生して開発を始めることを「ブランチを切る」といい、branchコマンドはこのブランチを切る、すなわち新しいbranchを開始するためのコマンドである。

尚、ブランチを切って新たなブランチを作る際のブランチの名前は各々が勝手に決めることができるがこのホームページを作る場合は自分のGitHub名をつけたブランチを作成して開発を進めてもらう。

  • checkout

基本的にはブランチを切り替えるコマンドとして使用する。リモートリポジトリからクローンしてローカルリポジトリを作成した際にはmasterブランチになっている。このまま開発を進めると、本元をいじることになる(誤ってmasterブランチで開発を進めていたとしてもローカルリポジトリのものをリモートに統合しなければ害は出ないが)。

そのためbranchコマンドで作成したブランチに切り替えて開発を行う。

  • addとcommit

addとcommitについては下の図がかなり分かりやすい。

../_images/addcommit.png

ネビ活より図を引用。(なるべく差し替えます)

分かりやすいのはcommitの方だろう。commitは単にローカルリポジトリにどのような変更を行ったかという変更履歴を登録するだけである。すなわちローカルリポジトリの更新だ。

対してaddは、commitすべきファイルとして準備する段階である。図のようにcommit対象を選定してまとめた状態、あるいはまとめて入れた領域をインデックスまたはステージという。addなんてしなくても最初からcommitすればいいじゃんと思う人もいるだろうし、実際筆者もそう思っている。が、この方が都合がよいことがあるのだろう。

  • push

pushはローカルリポジトリの内容をリモートリポジトリにアップロードするときに使用する。先ほどcommitでローカルリポジトリの更新を行ったが、それをリモートリポジトリにも反映するということである。

そもそもブランチはローカルリポジトリとリモートリポジトリで別々に分かれている。 例えばmasterブランチしか存在しないリモートリポジトリからクローンして手元にローカルリポジトリを作成したとする。この場合ローカルにもmasterブランチしか存在しない。ここでブランチを切って新たにonefive13というブランチを作成したとすると、ローカルのポジトリではonefive13のブランチが作成される。この状態でファイルを編集してadd, commit, pushを行うことでリモートリポジトリにもonefive13のブランチが作られ、編集結果がそのブランチにおいて反映される。

  • pull, fetch, merge

この辺りのコマンドをちゃんと使っていない&調べれていないのでとりあえず簡単に書いておきます。

自分が開発したものに誰かがさらに開発を進めた場合、ローカルリポジトリが例えばver1.0なのに対しリモートリポジトリはver3.0なんてことが起こりうる。この場合ver1.0に手を加えるよりも、一度ローカルも3.0に更新した後に自分で開発を進めるべきである。その更新に使用するのが上記のコマンドである。

fetch: リモートリポジトリのorigin/masterの最新情報をローカルに更新する。但し情報を更新するのであってファイル等を更新する訳ではない。

merge: fetchでとってきた更新情報をもとに実際にファイルを更新する。

pull: fetch + mergeである。ならpullを使えばよくてfetchなんて要らないと思うかもしれない。その通りである。この辺りも使用してみないと良さが分からない...。

補足

上の説明でoriginって何?と思った人もいるかもしれない。originとはリモートリポジトリのクローンを行った場合にそのクローン元のURLのことである。