バージョン管理初心者がGitとSourceTreeで既存プロジェクトのバージョン管理をしてみた

f:id:watass:20141020203524p:plain


技術ブログは毎度毎度3日坊主が続いていたので、はてなで週一くらいのペースで更新したいなーと思っている今日この頃です。
何かと話題のGithubとかGitとかのバージョン管理ですが、そもそもWeb開発一年目、今まで書いてきたプログラムはローカルでバリバリ走らせるようなCやらC++やらな私としましては、バージョン管理ド初心者なわけです。
とはいえど、今までちょっとWebアプリ開発や、チーム開発に携わった身としては、バージョン管理って大事だなーとうすうす感じてはいたので、バージョン管理もSVNもわからない俺がすでに作成したプロジェクトをGitで管理するためにやった諸々をまとめておこうと思います。



そもそもバージョン管理って何よ

まぁなんとなくはわかると思うんですが、例えば、あるプログラムの機能追加とか、バグフィックスとかいろいろやっている間に、どこをいつ直したのか!?みたいになって取り返しのつかない状況になることもあると思います。そんな状況を救うのがバージョン管理ソフトのApache Subversion (SVN)だったり、Gitだったりするわけです。
基本的には、バージョン管理したいプログラム郡をリポジトリと呼ばれる更新データ群をまとめておくものに登録しておき、そこへ修正内容をいろいろ登録していく感じです。

ところで、SVNとGitの違いはなにか?というと、集中管理型か、分散管理型かなんですが、今の流行りは分散管理のGitなんですね。これもざっと説明すると、サーバ上のプログラムを複数人のエンジニアが弄らないといけないようなシチュエーションで、一つのファイルをそれぞれが好き勝手にいじると、一方の修正は反映されたのに、もう一方の修正は反映されていない・・・なんていう残念な事態になりかねないわけです。
更新するときに、周囲のエンジニアに向かって「今からindex.php修正しまーーーす!!いじらないでくださーーーい!!」なんて言っていては、あまりにも原始的と言わざるを得ないですし、大規模なプロジェクトになるとそうもいかないでしょう。

これを解決するのがGitなわけです。すごいよGit。かわいいよGit。


Gitで分散バージョン管理ができる理屈

ごたごた言わずにyum install gitでいいんだよ!という男らしいスタンスも嫌いじゃないんですが、この辺の理屈をしっかり理解していないと、どんどんドツボにハマる感じというか、実際ハマっていたので、個人的に理解した理屈というか、イメージをここで書いておきます。

まず、Gitのリポジトリにはローカルリポジトリリモートリポジトリがあって、本番環境のリポジトリがリモートリポジトリで、修正作業をやりたい人は、リモートリポジトリをコピーしてローカルリポジトリとして保存し、ローカルリポジトリに修正内容を保存していきます。
これによって、複数人で修正を行う場合にも、修正する内容は個々人のローカルリポジトリに反映されていくので、index.phpを修正しますよと社内をうろかつなくても済むわけです。
なお、ローカルリポジトリの修正内容は、ある程度修正内容が固まった段階で、プッシュすることによってリモートリポジトリに反映されます。

・・・とまあ、この辺りはGitについてググれば出てくる話なんですが、個人的に一番ハマったベアリポジトリノンベアリポジトリの説明をしておきたいと思います。
これもよくわかっていないっちゃあいないんですが、ベアリポジトリ更新履歴の情報だけを保持するリポジトリで、ノンベアリポジトリは更新履歴と実ファイルを含むワークツリーも含むという感じみたいです。
じゃあとりあえず大は小を兼ねる、ということで、ノンベアリポジトリでやればいいじゃん、と思うかもしれないんですが、ノンベアリポジトリはローカルからプッシュできない?みたいなんですね。
なので、ローカルリポジトリの修正内容はベアリモートリポジトリにプッシュし、ノンベアリモートリポジトリはベアリモートリポジトリから修正内容をプルすることで、ノンベアリモートリポジトリ内の実ファイルに、初めて修正内容が反映される、ということです。
これを知らず、ベアリポジトリにプッシュしまくって、なんで反映されてないんや!と騒ぎ立てていましたので、どうか他の方は同じ過ちを繰り返さぬよう・・・


Gitを導入する環境

さくらVPS上に構築されたWEBサーバ (153.121.61.78)においてあるindex.phpMacクライアントからGitを使ってバージョン管理します。
なお、各種環境、バージョン情報は以下の通りです。

サーバOS:CentOS 6.5
クライアントOS:Mac OS X 10.9.1
Git:version 1.7.1
SorceTree:version 2.0.2


Gitのインストール (WEBサーバ側)

まず、サーバ側にGitをインストールします。

# yum install git

Webサーバ側のGitの用意はこれだけ。
リポジトリの作成はこの後でやります。


SourceTreeのインストール (クライアント側)

Gitはコマンドラインからやってもいいんですが、Windowsとかだとそうもいかないので、Macを使っているものの、Gitクライアントである、SourceTreeを使っていきます。SourceTreeはWindows版もあるのでぜひ。

まずは以下のWebサイトでOSにあわせてインストール
https://www.atlassian.com/ja/software/sourcetree/overview

f:id:watass:20141020213617p:plain

起動すると、Githubなどのアカウント設定が出てきますが、今回はパスします。
後からでも登録できますので、ご安心を。
ローカルパスの設定などもデフォルトでいいと思います。もちろん変えてもOKです。

f:id:watass:20141020214004p:plain

この画面が表示されれば、クライアント側のインストールは完了です。


リモートリポジトリの作成 (ベアとノンベア)

Gitのインストールが済んだら、早速リポジトリを作成していきます。
まず、サーバ上のバージョン管理対象ディレクトリに移動して、git initをします。
なお、今回の対象ディレクトリは/home/watass/gittestとします。

$ cd /home/watass/gittest
$ git init
Initialized empty Git repository in /home/watass/gittest/.git/

これでリポジトリの作成は完了です。
作成したリポジトリの状態をgit statusで見てみましょう。

$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	index.php
nothing added to commit but untracked files present (use "git add" to track)

Untracking filesにindex.phpが入っていることがわかると思います。
gittestディレクトリにはindex.phpしか配置していないのですが、リポジトリを作成しただけではindex.phpのバージョン管理はできないんですね。
なので、このindex.phpをバージョン管理の対象とするためには、リポジトリのインデックスに追加するgit addコマンドを実行する必要があります。

$ git add index.php

また、いちいちすべてのファイルを指定するのは面倒くさい、というエンジニアらしい人は以下のコマンドで現在のディレクトリ配下すべてをインデックスに登録することができます。

$ git add .

早速git statusで見てみましょう。

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#	new file:   index.php
#

new fileとしてindex.phpがトラッキング対象として追加されていますね。
加えて、現在のindex.phpが(現状では)最終バージョンであることを知らせるために、リポジトリにコミットをします。

$ git commit -m 'registration index.php'

'registration index.php'はコメントなので、適当に書いてください。
ここまでやったらもう一度git statusを見てみましょう。

$ git status
# On branch master
nothing to commit (working directory clean)

これでOKです。
ちなみに、これで作成されたリポジトリノンベアリポジトリであり、こいつにプッシュしようものなら refusing to update checked out branch だの updating the current branch in a non-bare repository だの怒られてしまうわけです。

f:id:watass:20141020220439p:plain

ということで、このリポジトリとは別に、サーバ上にローカルからプッシュするための更新情報だけを管理するリポジトリ、ベアリポジトリをノンベアリポジトリからクローンする形で作成します。なお、ベアリポジトリは/home/watass/gittest.bareにおきます。

$ cd /home/watass/gittest.bare
$ git clone  --bare /home/watass/gittest .

これでOK。ノンベアリポジトリとベアリポジトリの作成が完了しました。
これからは、ローカルからのプッシュはベアリポジトリに対して行い、実ファイルへの反映はベアリポジトリからノンベアリポジトリへのプルによって行います。


リモートリポジトリをローカルリポジトリへクローンする

サーバ上にリポジトリを作成したので、SourceTreeでこれをローカルにコピーします。
SourceTreeの「新規リポジトリ」から「URLからクローン」を選択します。

f:id:watass:20141020221929p:plain

クリックすると「リポジトリをクローン」と表示されますので、サーバ上のGitソースURL、保存先のローカルパス、ローカルリポジトリの名前を設定します。
このとき、ソースURLは以下のようなフォーマットで指定します。

ssh://[ユーザ名]@[接続先IP]:[ポート番号][リポジトリパス]

今回の例でいうとこんな感じです。

ssh://watass@153.121.61.78:22/home/watass/gittest.bare

基本的にはディレクトリパスを指定するだけでOKです。指定するのはベアリポジトリであることを忘れないようにしてください。
正しく指定できれば、ローカルにノンベアリポジトリをクローンできます。
こんなウインドウが立ち上がったらクローン完了です。

f:id:watass:20141020222756p:plain

このとき、クローンするときに指定したローカルパスにバージョン管理の対象のファイルがあることを確認してください。
ここまででローカルリポジトリへのクローンは完了です。


ローカルリポジトリへのコミット

早速バージョン管理の真髄を体験してみましょう。
まず、クローンしてきたindex.phpをクライアントで編集します。

[編集前]

<html>
<head>
<title><?php echo 'Git test'; ?></title>
</head>
<body>
</body>
</html>

[編集後]

<html>
<head>
<title><?php echo 'Git test for Mac'; ?></title>
</head>
<body>
</body>
</html>

タイトルをほんのちょっとだけ変えてみました。
編集を保存すると、SourceTreeの先ほどの画面が変化したことがわかると思います。

f:id:watass:20141020223832p:plain

ここで、左下の窓には修正したファイル群が表示されています。
ここから修正内容をコミットしたいファイルだけを選択することができますので、今回の場合はindex.phpチェックボックスにチェックを入れます。

f:id:watass:20141020224719p:plain

これでコミット対象となるファイルが左上の窓に移動しました。左上の窓にはコミット対象とするファイル群がステージングされています。
後は、下のテキストボックスにコミットコメントを記述して、コミットすればローカルリポジトリへのコミットが完了します。その過程で、ユーザ情報を求められるかもしれませんが、適当にアドレスとか名前とか登録してください。


ベアリモートリポジトリへのプッシュ

次に、ローカルリポジトリの変更内容をリモートリポジトリにも反映します。
左メニューの「ブランチ」をクリックしてみてください。

f:id:watass:20141020225430p:plain

こんな感じにプッシュできる変更があるよ!と表示されます。
ちなみに、この画面から今までのコミットログとかが読めます。
とりあえずさっさとプッシュしちゃいましょう。上メニューのプッシュボタンをクリック。

f:id:watass:20141020230013p:plain

プッシュ先のブランチとか聞かれるのでとりあえずOK。
これでプッシュは完了します。が、まだ実ファイルには反映されていないので注意。


ノンベアリモートリポジトリへのプル

最後に、ベアリポジトリに反映されたコミットログを実ファイルに反映させます。
サーバにログインして、ノンベアリポジトリのディレクトリへ移動し、git pullを実行します。

$ cd /home/watass/gittest
$ git pull origin master

これでgittest配下のindex.phpに編集内容が反映されていることを確認してください。
やっとここまでできたー。


まとめ

  • Gitは基本的に、addしてcommitしてpushしてpull
  • Gitの魅力はローカルリポジトリを使った分散バージョン管理
  • リモートリポジトリはベアとノンベアに注意

つか、はてな記法いいっすね〜
ソースコードを綺麗に書くのは、結構苦労してたんですけど、すごいさくっとできました。


Git is 難しい

とりあえず簡単なところまではできましたが、まだまだ勉強するべきことは多々ありますね。
後、ベア、ノンベアに悩まされた結果、順番が前後しまくったこともあったので、適当なこと書いてある部分もあるかもしれません。何かありましたらご指摘いただけると助かります。
というか、割りと雑に書いてある部分があるので、また近々記事修正します・・・

しかし、Gitっていろいろできるし、初心者向けは全部コマンドオンリーでやってるから、結構初心者向けには難しいんじゃないかな〜。
Githubとかは結構情報豊富なんだけど、サーバ上でやる例が少ないきがする。


参考にした記事


ベアリポジトリとノンベアリポジトリ:理論編〜GitでWordpressのテーマを管理 | トリコロールな猫
# Gitの理屈で一番参考になりました。ハマりも解消してくれました。ありがとうございます。
サルでもわかるGit入門 〜バージョン管理を使いこなそう〜 | どこでもプロジェクト管理バックログ
# おなじみGit初心者向けサイト
Git初心者のためのGit入門 - Qiita
# Gitってわけのわからないワードが多すぎるので、非常に参考になります。
【保存版】SourceTreeでGitの使い方まとめ1 個人開発編 | プログラミング備忘録 | 俺日記
# SourceTreeの使い方で非常に参考になりました。ケース別に書いてあるのがわかりやすいです。
リモートリポジトリへの git push に失敗した場合 (remote rejected) - まじめにゆいがどくそん
# ベアリポジトリの存在を知らせてくれました。
Git - Gitのインストール
# やっぱり基本的なコマンド操作はこちらから見るとわかりやすいです。