イケててヤバいGit入門

この投稿はGREE Advent Calendar 2013 20日目の記事です。

プロデューサーの皆さん、みりっほー。進捗どうですか?私はダメです。ごめんなさい。(´・ω・`)
WG事業部の二宮です。今日はアイマス駆動開発の話をしようかと思ったのですが、急遽Gitの使い方の話に変更しました(Inspired by 堀口先生)。

アイマス駆動開発の話が気になる方は、是非一緒に飲みに行きましょうw

※この記事では、ツールにGitやGitHubを利用することを想定しております。

Gitをスマートに使いたい

グリーでは、基本的にA successful Git branching model有志の方による日本語訳)にのっとって開発しています。

Gitについて基本的な考え方の部分は堀口さんの記事で言及されているので、私は現場で具体的にどのような使い方をしているのかについて書きたいと思います。

とはいえかくいう私も今年春からまともに使い始めた口なので、「それはあかんやろ」「こっちの方がスマートだぜ」等のご意見も歓迎です。

全般の設定(Git)

クライアント側(実際にgitコマンドを叩く環境上)のセットアップを行いましょう。

最初に下記のコマンドにより、commitしたときの名前やメールアドレスを設定しておきます。

もっとも実際の情報はホームディレクトリ以下の.gitconfigに書かれるのでこれを編集してもという向きもありますが、せっかくコマンドが用意されているのでこれを使った方がかっこいいと個人的には思います。

必要に応じて.DS_StoreやThumb.dbといった何かのタイミングで紛れそうなやつらをgitignoreしておきます。

また、GitHubに登録した公開鍵と対になる秘密鍵をホーム/.sshディレクトリ以下に配置しておきます。

開発の準備(Git/GitHub)

Git共通の設定が終わったら、開発の準備を行います。

初期作業

まずはGitHub上でオリジナルのリポジトリを自分のスペースにforkします。その時のリポジトリの状態をまるっと複製するわけですね。なお、ここで複製したリポジトリはオリジナルから派生させた自分のものなので自由にいじることができます。やったNE!

そしてそれを自分自身の開発環境にcloneしてきます。

開発環境上のリポジトリはローカルリポジトリと呼ばれ、git commitなど基本的な変更はこの開発環境上のリポジトリに対して行われます。この時点で各リポジトリの関係は、以下のようになっています。

20131220_ac2013_01

これがもし、下のようにオリジナルのリポジトリからcloneしたとします。

この場合、各リポジトリの関係は、以下のようになっています。

20131220_ac2013_02

git cloneした元のリポジトリがoriginとなることがお分かりいただけたでしょうか。

コードに改修を行った場合、ローカルリポジトリにその変更が反映されることは前述した通りです。では、ローカルリポジトリの状態をリモートリポジトリに反映させるにはどうしたら良いでしょう。

そうですね、この履歴をリモートリポジトリに反映させるにはgit pushすればよいです。逆にオリジナルのリモートリポジトリに変更が加えられた場合、これを取得するためにgit pull(git fetch + git merge)してくればよいです。

といったところで、先ほどの図だとリモートリポジトリが自分のものとオリジナルのものの二つあることにお気づきでしょうか。

Gitでは、git cloneしたリモートリポジトリがoriginとして命名されています。このことは以下のように調べることができます。forkした自分のリポジトリをcloneした場合は次のようになっているはずです。

これがもし、オリジナルのリポジトリをcloneした場合は次のようになっているでしょう。

ここでは、forkした自分のリモートリポジトリをcloneした(前者のパターン)として書いていきます。

20131220_ac2013_03

この場合、ローカルリポジトリとオリジナルのリポジトリの間でgit fetch(git pull)/git pushすることができないので、次のように登録するとよいでしょう。

コマンドを実行した後の状態を下図に示します。

20131220_ac2013_04

gree/(プロジェクト名).gitがチームで開発しているリポジトリ、hiroaki-ninomiya/(プロジェクト名).gitが自分のリポジトリというイメージです。

なお、余談で最初にオリジナルのリポジトリをcloneしてきていた場合の注意ですが、

20131220_ac2013_02

自分が関わるプロジェクトの場合、オリジナルの名前をoriginのままにしておくと事故の元です。git push -fなどしてしまうと、デフォルトでoriginが設定されてしまうからです。やはりこの場合もオリジナルのリポジトリの名前をupstreamとかにしておくとよろしいです。事故ると悲しいです。

改修の開始

さて、いよいよ開発を始めるにあたり、Git管理下に置かれているディレクトリに移動してdevelopブランチに切り替えておきましょう。

ここでいわゆるfeatureブランチを作成するのですが、オリジナルのdevelopブランチに変更があった場合、自分のリポジトリのdevelopブランチより歴史が進んでいることがあります。

20131220_ac2013_05

というより、実務では大抵進んでいるので、前述の設定をした直後でなければ次のコマンドで最新の状況を取得しておきましょう。

20131220_ac2013_06

任意で、GitHub上の自分のリポジトリに反映させてもよいでしょう。

20131220_ac2013_07

developブランチを最新の状態にしたらそこからfeatureブランチを作ります。実際の命名規則はチームによりけりのようですが、これまで見てきたところではチケット番号を入れたり、日付と概要を入れたりしていました。developブランチで以下のコマンドを実行し、コード改修のためのブランチを切りましょう。

featureブランチを作るところまでいったら、あとは改修に専念しましょう。必要に応じてgit addやgit commitなどを行ってください。

イケててヤバいPull Requestを出すためのパターン

Pull Requestを出すために、まずはGitHub上の自分のリポジトリに変更を反映させなければなりません。改修を行ったブランチをそのままpushするだけです。

が、時と場合、チーム文化によってはこの基本パターンが不適切となることがあります。以下、参考としてPull Requestを出すためのいくつかのパターンを紹介します。

squashするパターン

ただ、あまりにcommitが多すぎるときはcommit一つにまとめた方がスマートな場合もあります。やり方としては、改修後一旦developブランチにチェックアウトして、Pull Request用のブランチを切りなおした後、そのブランチに変更をマージしてcommitすることでcommitを一つにまとめます。

rebaseするパターン

オリジナルのリポジトリに改修が入っている場合、rebaseした方が良いこともあります。具体的には以下の手順を行います。

developブランチをfeatureブランチにmerge --no-ffするパターン

また、改修範囲が大きい場合は、むしろfeatureブランチにdevelopの最新状況をmergeした方が良いかもしれません。(--no-ffをつけることでmergeした履歴を残します)。 やり方としては、developブランチを最新の状態にした上で以下のコマンドをfeatureブランチ上で実行します。

無事、Pull Requestを通過しmergeされたら、いよいよリリースです。お疲れ様でした。

まとめ

Gitって、すごいですよね。 知れば知るほどあれも使ってみたい、これも使ってみたいが出てきてアイマスと同じくらい楽しいです。

さて、明日はアゴひげがダンディーな九岡さん@mumoshu)です。氏とは奇しくもこの三連休でenchant.jsを使って共闘することになりました、よろしくお願いします!

それでは皆さん、みりおっつーでした。2014年もアイマスですよ、アイマス!