• ログインログイン
  • 新規登録新規登録

MENU

ゼロから始めるMacintosh開発環境構築(OS X Mavericks編)ーこれからプログラミングを始める人のためにー(5)

連載ゼロから始めるMacintosh開発環境構築(OS X Mavericks編)

プログラミング初心者からでも始められる、Macintoshの開発環境構築についての解説記事です。Xcodeの設定やUNIXのコマンド解説など、初心者が一通り覚えておくべき内容です。

前回までのプログラミング学習コラムに続き5回目の勉強内容です。

第5回 「Gitコマンドはプログラマの公用語」

これから2回に渡って分散型バージョン管理システム「Git」と、代表的なGitレポジトリである「GitHub」を紹介します。これらのシステムはプログラマが成長していく過程で大きな役割を果たしてくれる、訓練施設とも言えるものです。うまく利用すればプログラミング能力をグングン伸ばしていくことも可能です。今回はまず「Git」の基礎について学んでいきます。

■ 2つの役割を持つ「Git」

プログラミングに慣れてくると、自分の作ったプログラムを改良したくなります。でもせっかくちゃんと動いていた自作の大事なプログラムに直接手を入れてしまい、うまく動かなくなってから「ああ、以前のバージョンをとっておけばよかった」と思うことも出てくるでしょう。後悔先に立たず、ですね。

そんな時に役立つのがバージョン管理システムです。編集中の文書を保管し、「何日前のバージョン」などと指定して戻すことができるようになっています。Macユーザであれば、Time Machine機能などを使ったことがあるかもしれません。あれ、便利ですよね。筆者も何度もうっかり上書き保存から助けられています。

プログラミングの世界では「Git」というバージョン管理システムが超メジャーです。しかしGitはもともと分散型バージョン管理システムとして作られたものなので、個人でプログラミングを始めた初心者にとってはちょっと敷居の高い部分があります。

GitはLinuxの作者であるリーナス・トーバルズ氏によって、その大規模なLinuxカーネル開発作業をスムーズに進めるために作られたものです。Linuxカーネルは世界中のプログラマたちによって24時間365日開発・改良され続けています。ですからGitには分散型のバージョン管理機能が必要だったのです。

プログラミングを最近始めた初心者の方にとっては、この分散型というのがピンと来ないかもしれません。仕事などで共同開発に慣れている人にとってはGitの学習コストは少ないようですが、個人だとそうも行かないでしょう。ここは一つ個人用途に絞ってGitを学びましょう。そう、まずはバージョン管理をしっかり行うことです。そしてその保存先をリモートで管理することによって、少しだけ分散型の雰囲気を味わうことにしましょう。一人二役を演じればいいわけです。

Gitそのものの動きについて、わかりやすく解説しているサイトが「サルでも分かるGit入門」です。

サルでも分かるGit入門

この「入門編」のページの最初のファイル一覧を見て、筆者は思わず吹き出してしまいました。最新バージョンの書類を他と区別できるようにと無駄に長いファイル名の書類がたくさん出来上がってしまったこの状態、えっ、なんで私の書類フォルダの中身を知ってるの?とビックリ。ほんとにサル先生がおっしゃるように「もうどれが何だかわからんばい・・・」という状態です。

みなさんのソースプログラムがそうなってしまわないよう、開発用の作業ディレクトリをさっそくGitの管理下に置くことにしましょう。

Git本体はこの連載の第2回目でHomebrewからインストールしましたね。バージョンを確認しておきましょう。

$ git --version

2013年12月現在ですと1.8.5ですね。ではまず初めに一度だけ、設定作業を行いましょう。ユーザ情報や文字のカラー化についてコマンドで設定します。

$ git config --global user.name "あなたのユーザ名"
$ git config --global user.email "あなたのメールアドレス"
$ git config --global color.ui auto

Gitではテキスト編集を行うことがあるので、せっかくですからエディタをSublime Textに設定しましょう。

$ git config --global core.editor "subl -n -w"

次に練習目的の開発作業用ディレクトリを作成しましょう。今回はホームディレクトリの下に「ex_project」というディレクトリを作成します。さらにそのディレクトリをGit管理下に置くためにgit initコマンドで初期化を行います。

$ cd ~
$ mkdir ex_project
$ cd ex_project
$ git init

これで今後はディレクトリ下のファイル変更は全て追跡されていきます。

さて、今回は「前の状態に戻れるように」バージョン管理を活用するのでした。ならば今回のコマンドはなるべくやり直しが出来るように説明していきましょう。例えば今のgit initコマンドを違うディレクトリで実行してしまうと後で厄介なことになります。もしgit initをなかったことにしたい場合は、同じディレクトリ上で、

$ rm -r .git

とやれば大丈夫です。正しいディレクトリに移ってからgit initし直しましょう。

今回は勉強ですので、元に戻すコマンドは全て一度試して、再び先ほどの作業をやり直してから先へ進む、つまり毎回1歩下がって2歩進みます。面倒ですがこれでやっていきましょう。今回間違っていないくても rm -r .git を実行してもう一度git initしましょう。

さて、ここからは多くの用語が飛び交います。「リポジトリ」「コミット」「ワークツリー(ワーキングツリー)」「インデックス」という言葉について、まず先ほどの「サルでも分かるGit入門」の図などを見てしっかりイメージしてください。先にイメージできてからコマンドを打つと理解が深まります。

特にファイルの状態を表す次の3つの段階について、しっかり頭に入れておきましょう。

  1. ワーキングツリー
  2. インデックス
  3. リポジトリ(HEAD)

なんで3段階もあるのでしょうか。初心者にとっては混乱の元ですね。でも後でこれが効いてくるのです。今は我慢して付いて行きましょう。

まず、先ほど作ったex_projectディレクトリにファイルを一つ作成します。作成されたファイルは「1.ワーキングツリー」下に置かれたことになります。

$ subl db_test.php

内容は前回のdb_test.phpと同じにしましょう。コピーしてきてもO.K.です。

<!--?php <br ?--> $link = mysql_connect('localhost', 'root', '');
if (!$link) {
die('接続失敗!
'.mysql_error());
} else {
echo '接続成功!';
}
?&gt;

Sublime Textで保存したら次のコマンドで状態を確かめてみます。

$ git status

「status」とある通り、ファイルの状態を表すコマンドです。頻繁に使うので省略形を登録しておいたほうがいいかもしれません。

$ git config --global alias.st "status"

こうしておくと、今後は、

$ git st

だけで状態が確認できます。(今後の説明では混乱のないよう省略形ではなく、コマンド全体を示します。)

今のgit statusの結果には赤い文字がありましたね。

db_test.php

これは「1.ワーキングツリー」下に変更が生じていることを示しています。この変更をなかったことにしたい場合は、今回は新規作成なので、単純にdb_test.phpを削除すればO.K.です。

$ rm db_test.php

ではもう一度db_test.phpを作り直してから次の段階に進めてみます。

$ git add db_test.php

またgit statusします。今度はメッセージの文字が黄緑色になりました。

new file: db_test.php

これは「2.インデックス」の状態に移ったということを意味しています。今回はファイルが新規追加されています。「ステージングされた」「ステージした」という言い方もします。

この作業をなかったことにしたい場合は、実はメッセージにやり方が書いてあります。アンステージという言葉が出てきます。

  (use "git rm --cached <file>..." to unstage)

ということで一歩下がってみます。

$ git rm --cached db_test.php
$ git status

赤い文字に戻りましたね。一瞬db_test.phpがなくなってしまったかと焦りますが、db_test.php自体はちゃんと残っています。アンステージして1段階前のワーキングツリーの状態に戻っただけです。もう一度git add db_test.phpして黄緑色のメッセージを確認しておいてください。

では次の段階に進みましょう。

$ git commit

最初の設定が効いているので、Sublime Textが起動しましたね。ここで空白行になっている1行目にコミットメッセージを入力します。今回の変更作業を端的に説明します。今回ははじめての新規作成なので、「First commit」としておきましょう。

First commit
(以下「#」から始まるコメント行が続く)

コメント行は保存される時無視されます。ファイルを保存してSublime Textのウィンドウを閉じると、ターミナルに制御が戻ってくるので、またgit statusをしてみましょう。

nothing to commit, working directory clean

というメッセージが出ました。コミットが完了して新規ファイルが「3.リポジトリ」に登録された、つまりまた一段階進んだことになります。全てのインデックスがコミットされリポジトリに登録されると、ワーキングツリーがクリーンな状態になるわけです。

ここでいったんGitのログを取ってみましょう。

$ git log

コミット後のgit logの画面

図. コミット後のgit logの画面。一行目が40桁のID。最下行がコミットメッセージ。

リポジトリのコミット情報が見えます。一行目に40桁の暗号みたいなのも見えますが、これはGit内部で使われる重複しないIDで、オブジェクト名ともいいます。このオブジェクト名でコミットの識別ができます。もちろん人間は一番下のコミットメッセージでも識別できるので、毎回メッセージは変えましょう。

ここでもう一つキーワードを覚えましょう。一度コミットをすると、リポジトリを指すのに「HEAD」というキーワードが使えるようになります。現在の位置のことを表しています。一つ前のコミットは「HEAD^」というキーワードで表せます。

3段階を一回りしてHEADができました。ここではやり直しをせずに、もう一回りしてみましょう。今度は新規作成ではなくファイルに修正を加えていきながら新たな3段階を踏んでいきます。

db_test.phpを編集します。

$ subl db_test.php

実はこのPHPプログラムには問題があります。mysql_connect()関数は古い関数で、今では非推奨なのです。詳しい説明は省略します。今回はこれをmysqli_connect()関数に修正し、mysql_error()関数はmysqli_connect_error()関数に修正します。

<?php
 $link = mysqli_connect('localhost', 'root', '');
 if (!$link) {
 die('接続失敗!<br>'.mysqli_connect_error());
 } else {
 echo '接続成功!';
 }
?>

今回の修正箇所は赤い部分の2箇所です。保存してSublime Textのウィンドウを閉じたらまたgit statusしてください。

modified: db_test.php

今回のメッセージの赤い文字に「modified:」という文字が加わりました。今回のワーキングツリーでは新規作成ではなく修正なのでmodifiedになります。

これをなかったことにしたい場合、メッセージを良く読むと先ほどとは違うやり方が書いてあります。

  (use "git checkout -- <file>..." to discard changes in working directory)

というわけで、また試してみましょう。一歩下がります。

$ git checkout -- db_test.php

これで修正前、つまり前回のコミット直後に戻れました。ワーキングツリーはクリーンですね。

もう一度先ほどの修正を加えて赤いメッセージを確認して下さい。それから先に進みます。今度はインデックスですね。git addコマンドを使います。

$ git add db_test.php

これでステージングされました。キーワードに慣れましょう。これをなかったことにしたい場合、またメッセージを見ると前回の時と違いますね。今回はHEADが存在するのでそれを指定します。

  (use "git reset HEAD <file>..." to unstage)

やってみましょう。

$ git reset HEAD db_test.php

git statusがまた赤いメッセージに戻りましたね。

次にもう一度ステージングして黄緑色のメッセージを確認したら、今度は2回目のコミットです。

$ git commit

今度のコミットメッセージは修正箇所がわかるようにしましょう。Sublime Textで空白の一行目に以下のメッセージを入力します。

Modified: mysql_connect() function -> mysqli_connect()
(以下コメント行)

Sublime Textで保存してウィンドウを閉じたらコミット完了です。さっそくリポジトリを確認しましょう。

$ git log

コミットが2つになりましたね。2つのコミットメッセージやタイムスタンプを確認してみてください。

では今の作業をなかったことにしてみましょう。つまり2回目のコミットの直前に戻します。ステージングがされている状態ですね。

$ git reset --soft HEAD^

「HEAD^」は一つ前のコミットという意味です。前回、つまり1回目のコミットの時はその前の「HEAD^」がありませんでした。今回は2回目実行後なので現在位置が「HEAD」、1回目が一つ前ですから「HEAD^」。この「HEAD^」を使って一つ前のコミットの状態に戻れます。コマンド実行後git logをとってみましょう。コミットが一つしかありませんね。git statusをとるとちゃんとステージング直後、つまり黄緑色のメッセージがあります。

ではもういちどgit commitで2回目のコミットを実行してワーキングツリーをクリーンな状態にします。git logでコミットが2つあることを確認して下さい。

2回目のコミット完了後のgit log画面

図. 2回目のコミット完了後のgit log画面。最新のものが上に来る。

ここでgit diffコマンドを実行してみましょう。diffコマンドは2つのファイルの差分を取るコマンドです。つまり変更の箇所を示してくれます。

$ git diff HEAD^ HEAD

2つのコミットの間の差異をわかりやすく表示してくれます。

2回目のコミット完了後のgit diff HEAD^ HEADの画面図. 2回目のコミット完了後のgit diff HEAD^ HEADの画面。「-」が削除行、「+」が追加行。

さらにgitkコマンドというのも使えます。

$ gitk

Gitの状態をグラフィカルに示してくれます。2つのコミットを選択してみてください。状態の変化がよくわかると思います。gitkでの確認が終わったらウィンドウを閉じて、ターミナルに戻ります。

gitkの画面。画面一番上の欄でコミットを選べる。

図. gitkの画面。画面一番上の欄でコミットを選べる。最新の2回目のコミットを選択。

この後何度か修正作業を進めるとコミットが増えていきます。途中をすっ飛ばしてずっと前のコミットに戻りたい場合、先ほどの40桁のIDを指定すれば戻ることができます。IDは40桁全部を指定する必要はなく先頭の数文字で大丈夫です。例えば最初のコミットに戻りたくてそのIDを調べたら5f0962f2de・・・だった場合、

$ git reset --hard 5f096

とすればそこまで戻ることができます。その後の変更が消えてしまうのでいわゆるGitでいうところの「危険なコマンド」なのですが、コラボレーション時には危険であっても個人のプロジェクトであれば自己責任で実行できます。git logには日付の情報もあるので、先頭の方で触れた「何日前のバージョン」に戻る、といったこともできるわけです。

さて、Gitでは今まで見てきたように3段階の状態でファイル変更を管理します。ずいぶんめんどくさかったですよね。でも実際の開発では次のようなことが考えられます。

一つのGit管理下のディレクトリで4つのソースプログラムファイルを管理していたとします(「aaa.php」「bbb.php」「ccc.php」「ddd.php」)。

今回4つとも修正が入ったとします。そしてaaa.phpとbbb.phpは新機能の追加、ccc.phpとddd.phpはある不具合のバグフィックスだったとします。この場合はコミットを2つに分けてコミットメッセージで区別できるようにすべきです。でも4つとも同時に修正を始めても構いません。

そしてバグフィックス作業が済んだら、ccc.phpとddd.phpの2つを先にステージングしてからコミットします。コミットメッセージには2つのファイル名も入れておきます。次に残った2つを修正後ステージングして同様にコミットします。コミットが2種類に分かれました。どのファイルに対してどんな作業をしたのか、git logのコミットメッセージを見ればすぐにわかるようになっています。もちろん日時もバッチリです。git diffを取れば修正箇所もすぐに分かります。どうです?便利でしょ?

こういった便利さは、少しでも開発の規模が増してくるとすぐにありがたみがわかってきます。早いうちに慣れておくべきです。3段階の管理をめんどくさがらず、当たり前だと思えるようにしておけば、プログラマとしては一歩前進です。なぜならGitはもはやプログラマの世界共通言語とも言えるくらい普及してきているからです。もちろんこの分野でもアンチGit派という人たちはいます。でもその人たちもなぜか異様にGitに詳しかったりします(笑)。つまり共通言語ではあることには変わりありません。それくらい普及しているのです。

さてここまでは全てローカルの作業でした。まだリモートのリポジトリには触れてません。Gitの狙いは本来コラボレーションにあります。リモートに存在するリポジトリに対して操作していくことにGit本来の面白さがあります。個人作業であってもその面白さは味わえます。その一部だけですが次回に体験してみましょう。リモートにはあの有名なGitHubを使っていきますのでお楽しみに。

完全無料!

1で登録完了!

エンジニアの仕事・年収や選考ノウハウ記事が読めるほか、
会員にはプログラミング講習やES・面接対策などリアルな無料サポートも充実。
ここだけの求人情報も多数。

今すぐ新規会員登録
Page Top