こんにちは。プログラマー小野です。
予告通り、今回も引き続きGitについて書きたいと思います。
Gitコマンドの説明、Gitクライアントの紹介とコンクリフトについて、ですね。
先月の記事はこちら。
Gitリポジトリの複製『 git clone 』
おさらいになりますがGitのファイル管理では、まずリモートリポジトリ(中心リポジトリ)を自分の作業環境に複製し、複製されたリポジトリを経由してファイルの更新を反映させたり、逆に自分以外のメンバーの更新分を取り込んだりします。
自分の作業環境に複製されるリポジトリは「ローカルリポジトリ」と呼ばれ、このローカルリポジトリを作成するコマンドが git clone
です。
ターミナル(macの場合)を開き「 git clone 」に続けてリモートリポジトリのURLを入力して実行すると、カレントディレクトリにリモートリポジトリのクローンが作成されます。
前回同様リモートリポジトリは社内サーバーまたはVPSに配置されている前提ですので、リモートリポジトリのURLは環境構築されたエンジニアの方が教えてくれます。
以下のような感じですね。
変更内容の記録『 git commit 』(と、その前に『 git add 』)
ローカルリポジトリがクローンできたらファイルを変更します。
ここで言う「変更」は、以下すべてを含みます。
- 新規ファイルを作成する
- 既存のファイルを編集する
- 既存のファイルを削除する
例として、既に存在する 書類/見積書.pdf を編集して上書き保存すると共に 書類/WEBサイト要件.txt というファイルを新規追加するケースを見てみましょう。
ちなみにGitではローカルリポジトリ(.git)の存在する階層(ここでは「example.com」ディレクトリ)を起点としてファイルを識別します。
前回の記事では「ローカルリポジトリへの変更履歴の記録(git commit)」という触れ方だったので割愛されていましたが、実際には前段階としてコミットに含めるファイルを追加する git add
コマンドを実行する必要があります。
見積書.pdf と WEBサイト要件.txt は、それぞれ編集済みで保存されている状態でターミナルのカレントディレクトリを「example.com」に移動させ、以下のコマンドを実行します。
これで編集した 見積書.pdf がコミットに含まれることになりました。
(コミット自体はまだ実行されていません)
確認するには git status
コマンドを実行します
緑字で「 modified: 書類/見積書.pdf 」と表示されますね。
なお、 git add
でコミットに含めるファイルを追加することは「ステージング」や「ステージする」と表現されます。
という訳で引き続き WEBサイト要件.txt の方もステージし、再度 git status
コマンドを実行すると
今度は「 new file: 書類/WEBサイト要件.txt 」の行も緑字に変わっています。
ちなみに、ステージするファイルを明示的に指定するということは、変更してもステージしなければコミットされない(意図的にバージョン管理に含めないこともできる)ということでもあります。
では、いよいよコミットを実行します。
「 -m 」に続くダブルクォーテーションの中身は「コミットメッセージ」と呼ばれ、コミット日時と共にバージョン管理の履歴にコメントを残すことができます。
自分の行った作業をチームメンバーと共有するため、あるいは自分自身のための作業履歴として「何のため(why)に何(what)をどう(how)した」を明確に記しておくと後々重宝します。
逆に面倒だからとテキトーなコミットメッセージ(「更新」とか「修正対応」とか)だらけだと闇が深まることになりますよ、、、
ローカルリポジトリの変更をリモートへ反映『 git push 』
ここまでの操作でリポジトリに作業履歴が記録されたのは、自分自身の作業環境のローカルリポジトリに対してのみです。
一人プロジェクトであればこれでも構いませんが、今回の例はチームでバージョン管理されたファイルを共有するプロジェクトですので、ローカルの変更をリモートへ反映させて他のメンバーと共有可能な状態にするために git push
コマンドを実行します。
以上で自分の行った更新が他のメンバーと共有可能な状態となりました。
次は逆の立場で別の人の更新を自分のローカルリポジトリに取り込んでみます。
リモートリポジトリの差分をローカルに取り込む『 git pull 』
初回のクローン、あるいは前回の同期以降に自分以外のメンバーによって何らかの変更がプッシュされた場合には、その差分を自分のローカルに取り込んで最新の状態にする必要があります。
後述のコンクリフトを避けるため、DropboxやGoogleドライブと違って同期は自動では行われないようになっているので、git pull
コマンドで明示的に同期を実行します。
ファイル群が最新の状態に更新されました。
コミット履歴も確認できます。
GitクライアントのGUIツール
さて、ここまでターミナルだのコマンドだの不穏なキーワードが飛び交って不安になっている非プログラマーの方も多いかと思いますが安心してください。
Gitの基本はコマンド操作ですが、優秀なGUI(Graphical User Interface)ツールがたくさん用意されていますので、これまで見てきたすべての操作は通常のアプリケーション同様、マウスとキーボードの操作で代替可能です。
Gitクライアントは各プラットフォーム(Windows、Mac、Linux等々)向けに無数にリリースされていますので、吟味して好みのアプリを選んでもらえれば良いと思いますが、ここではかいつまんで2つだけご紹介します。
まずBitbucketを運営しているAtlassianが開発するGitクライアントSourceTreeです。
各操作(コミット、プル、プッシュ)のボタンやコミット履歴、ソースの差分等がひとつの画面上ですべて確認できるレイアウトと、ブランチの枝分かれがグラフィカルに視認できるのが良さげですね。
ふたつ目はGitHub Desktopです。
名前の通り、こちらの開発元はGitHubですが、GitHubにホストしたリポジトリ以外も扱うことができます。
若干使い方にクセがありますが、慣れれば気にならない程度ですよ。
コンクリフトは(そんなに)怖くない
複数人でファイルを共有していると、タイミングによっては同じファイルを別々の人が同時に更新してしまうことが起こり得ます。
社内サーバー上のファイルを上書き保存して、同時に開いて先に保存した別の人の更新分を消し飛ばしてしまった経験が一度や二度はあるんじゃないでしょうか。
Gitでも同じ状況は当然発生しますが、上記のような場合には自分の更新分をプッシュする際に「競合が発生しています」と教えてくれてプッシュは実行されず、有無を言わさずにファイルが上書きされる事態は回避されます。
(あとは先に更新された方と自分で確認し合って人力で差分を埋めるということになりますが)
以上はたとえばExcelの書類のようなバイナリファイルの場合で、対象がプログラムのソースコードのようなテキストファイルだった場合には少し事情が変わってきます。
バージョン管理システムでは、テキストファイルなら文字単位で変更履歴を把握できるので、たとえば同一のファイルに対する変更が競合したとしても、明らかに別の箇所に対する変更であればGitが判断して自動で(それも相当な精度で)双方の更新分を混ぜてくれるんですね(用語としては「マージ」と呼ばれています)。
そして、Gitがどうしても判断できない箇所(まったく同じ行に対する変更が競合した場合など)に関してだけ、人力でのマージが求められます。
ただし、その場合も自分の変更箇所と、競合した別の誰かの変更箇所が並べて比較できるよう表示されるので、「どちらが残すべき変更なのか」を判断した上で適切な形でマージ(競合の解消)してコミットすれば事無きを得る訳です。
開発規模や運用方法にもよるとは思いますが、リモートへのプッシュを溜め込み過ぎない限りは、そうそうコンクリフトは起こらない(起こったとしても自動でマージされる)ので、私自身はGitにしてからコンクリフトに対する恐怖心がだいぶ和らぎました。
お互いの差分はGitが文字単位で抽出してくれていますし、どうしようも無い場合はロールバックすることもできる訳ですから、必要以上に恐れることはないと思います。
最後に
2回に渡ってお送りしたGitのススメでしたが、いかがでしたか?
多少なりとも「何だかGitって便利そうかも」という気分になってもらえたら幸いです。
Git未体験の方も、初めて聞いた非プログラマーの方も、新しいツールだからとネガティブにならずに、まずは興味を持って触ってみてもらいたいです。
具体的な使い方は社内のエンジニアやプログラマーの方に質問すれば教えてくれるはずです。
技術者は基本「教えたがり」ですから。