こんにちは。原(@herablog)です。
HTML5 Web Applicationのつくりかた」以来久しぶりの投稿となります。

今回は「Git」をフロントエンジニア向けに導入したお話をさせていただきます。

ソースコード管理システムとしてスタンダードになっているGitですが、機能が豊富で「なんか怖い」と思ってしまいがちです。特にフロントエンドの担当者にとっては距離を感じるものではないでしょうか。サイバーエージェントではGitHub Enterprise導入を期に、フロントエンジニアも利用し、効率・クオリティアップにつなげることができました。Gitを取り入れるメリット、よく使うGitコマンド、実際の現場でどのように使われているのかなどをお伝えします。

Gitを理解するポイント

どこでも一緒 「分散」の感覚

Gitは分散型のシステムであり、すべての環境が対等です。リモートであろうとローカルであろうとすべて同様の操作ができます。ですので、ローカル環境で色々チャレンジして、失敗しながら覚えていくことができます。

ブランチ たくさん作って作業

Gitのブランチはすべてのファイルそのものをコピーするわけではないので、容量を気にせず、気軽に複数のブランチを作成して作業します。作業に応じて適切にブランチを作成することで管理性の向上や、リリーススケジュールに対して柔軟に対応することができます。

ツリーをイメージし、綺麗にする

Gitでの作業ではたくさんのブランチを作成するため、それぞれを都度マージ(統合)させる必要があります。その際に、どのコマンドを使うとどのように取り入れられ、どのようなツリー表示になるかイメージできるようになると面白くなってきます。

Amebaでの開発フローは「git-flow」+ 「Pull Request」
Gitは数多くの機能を提供しているため、使い方は様々ですが、作業フローをまとめた有名なものとして「git-flow」や「GitHub Flow」といったものがあります。Amebaでは以下の理由から「git-flow」を採用しました。

・リリース日を決めた定期的なリリースに向いている
・オープンソースでも比較的採用されているので覚えて損はない

また、ソースコードのクオリティを担保するために、GitHubが提供している「Pull Request」という機能を使ってソースレビューをしています。

ブランチの運用ルール
ブランチは以下のルールにしたがって命名・運用されます。

master (製品版ブランチ)

このブランチは他のブランチからマージされるのみで、このブランチ上では作業しない。すべての内容はこのブランチにマージされたあと本番環境にリリースされる。

develop (作業内容マージ用ブランチ/masterブランチから作成)

作業ブランチの内容をマージし、 作業内容の確認はこのブランチから作成される。

feature/fixブランチ (作業用ブランチ/developブランチから作成)

作業用ブランチ 新規開発時は「feat/」、バグ修正には「fix/」という接頭辞をつけるようにルールを設けている。

release (リリース用一時的ブランチ/developブランチから作成)

リリース前確認用として一時的に作成される。

hotfix (バグ修正用一時的ブランチ/masterブランチから作成)

バグ修正用として一時的に作成される。

branches


Amebaでの作業フロー
作業開始から終了までをまとめると以下の図のようになります。

all


初回のみの作業

1. 共有リポジトリ(ameba)から自分のアカウント内(parsonal)に複製(*Fork)する
2. 自分のアカウント(personal)からlocal(PC内)に複製(**git clone)する
3. 共有リポジトリ(ameba)を「upstream」という名前で登録し、developブランチをlocal(PC内)に複製(**git checkout)する

通常フロー

3'. 初回以外は共有リポジトリ(ameba)の最新状態と同期をとる(**git pull)
4. 3で作成したdevelopブランチから作業用のブランチ(feat/new-menu, fix/tap-timingなど)を作成(**git checkout -b)し、作業する
5. 作業した内容を確定(**git add, git commit)する
6. 他の人が修正し、共有リポジトリに加えられた変更を作業用ブランチに取り込む(**git pull --rebase)
7. 作業したブランチを自分のアカウント内に複製する(**git push)
8. 作業したブランチの変更内容を「*Pull Request」し、コードレビューしてもらう
9. 変更内容に問題がないことを確認し、共有リポジトリ(ameba)のmasterブランチに取り込む(**git merge --no-ff)

リリースフロー

10. 開発環境もしくは本番環境にリリースする

* GitHubが提供している機能です
** Gitが提供している機能です

おおざっぱにいうと、共有リポジトリからファイルを落としてきて(1-3)、作業後(3'-5)、チェックをしてもらい(6-7)、共有リポジトリに取り込みます(9)。


便利なGUIツール「SourceTree」
Gitには様々な機能があり、それらを直感的に理解するのはなかなか難しいものです。普段コマンドラインでの操作に慣れていない場合はなおさらです。そういった場合にはGUIツールを使うと良いでしょう。この記事では無料で利用できるSourceTreeを使用します。

soucetree

http://www.sourcetreeapp.com/

よく使うGitコマンド・GitHub機能
それでは、よく使うGitコマンド・GitHub機能をご紹介しましょう。よりわかりやすくするために、実際の業務フローの流れとともにお伝えします。

Fork

1. 共有リポジトリ(ameba)から自分のアカウント内(parsonal)に複製(*Fork)する
公開用の共有リポジトリとしてGitHubを使用します。プロジェクトのページに行き、Forkボタンを押します。そうするとGitHubの自分のアカウント内に複製されます。

fork01

Forkボタンを押します。

fork02

Fork中にはフォークのイラストが出現します。

fork03

自分のアカウント内に複製されます。


git clone {URL}

2. 自分のアカウント(personal)からlocal(PC内)に複製(**git clone)する
先ほどforkしたリポジトリをcloneしローカル環境に複製します。そうするとmasterブランチができあがります。ここからしばらくローカル環境での作業になります。

clone01

表示されているURLをcloneします。

git clone http://github.sample.com/hara-kazunari/amebame-community.git


clone02

SourceTreeの場合は、[新規作成]からURLを指定します。


git remote add  {name} {URL}

3. [初回時] 共有リポジトリ(ameba)を「upstream」という名前で登録し、developブランチをlocal(PC内)に複製(**git checkout)する

プロジェクトの最新情報を追いかけるために共有リポジトリを「upstream」という名前で登録します。

remote1

表示されているURLをaddします。

git remote add upstream http://github.sample.com/amebame/amebame-community.git


remote_ST

右上の[設定]から追加します。


git checkout -b {branch_name} --track {repository}/{branch}

共有リポジトリを「upstream」として登録した後、upstreamから直接developブランチをlocalに複製します。その際、upstreamの更新情報を常にチェックするために--trackオプションをつけておきます。

git checkout -b develop --track upstream/develop


checkout

右クリックでメニューを出し、chekoutを選択します。


git pull

3'. [初回以外] 共有リポジトリ(ameba)の最新状態と同期をとる(**git pull)
共有リポジトリ(ameba)の最新状態を取り込み、同期をとります。
developブランチは最新の変更を取り込む用として、作業開始時には必ずpullを実行するとよいでしょう。

git pull


pull

・git branch  存在するブランチ、選択中のブランチを確認する
存在するブランチを表示します。選択中のブランチに*印がつきます。

* develop
  master


branch

SourceTreeでは選択中のブランチが太字表示されます。


git checkout -b {branch_name}

4. 3で作成したdevelopブランチから作業用のブランチ(feat/new-menu, fix/tap-timingなど)を作成(**git checkout -b)し、作業用のブランチを作成します。なお、現在選択中のブランチから作成されます。
1機能ごとにブランチを作成すること、機能追加には[feat/]、修正には[fix/]という接頭辞をつけることといったルールを設けています。

git checkout -b feat/new-menu


chekout-b

上部のBranchボタンを押して作成します。


git add {file or directory}, git commit -m "{Comment Message}"

5. 作業した内容を確定(**git add, git commit)する
git addでコミットするファイル・ディレクトリを選択した後、作業内容を記録するためにコミットします。コミットの単位は同一アクションごとにするとよいでしょう。SVNと違いこの時点ではリモートのソースコードには反映されません。あとで変更したり、削除したり、合体させたりできるのでどんどんとコミットできます。

git add ./git commit -m "Insert the new game icon. refs #1234"


commit

[Stage file]を押してコミットする内容を選択したあと、[commit]ボタンを押します。


git pull --rebase {repository} {branch}

6. 他の人が修正し、共有リポジトリに加えられた変更を作業用ブランチに取り込む(**git pull --rebase)
コミットが終わったのでリモートにプッシュしたいところですが、その前に最新の状態を取り込みます。--rebaseオプションを付けることによりdevelopブランチの履歴を保ったまま、その後に自らのコミット内容を追加できます。

git pull --rebase upstream develop


rebase

[Rebase instead og Merge]にチェックを入れます。

branch_rebase

rebaseすると、developブランチの変更を取り込んだ後、feat/fixブランチの変更内容を追加することができます。


git push {repository} {local_branch}:{remote_branch}

7. 作業したブランチを自分のアカウント内に複製する(**git push)
コミットした作業内容をリモートに反映させます。ここではPull Requestをするために自分のアカウントに反映させます。

git push origin feat/new-menu:feat/new-menugit push

clone元にpushするため、{repository} {local_branch}:{remote_branch}は省略することも可能です。

push

pushするブランチを選択します。


Pull Request

8. 作業したブランチの変更内容を「*Pull Request」し、コードレビューしてもらう
作業完了し、自分のアカウント内(origin)にpushしたブランチを共有リポジトリ(upstream)にPull Requestし、コードレビューをしてもらいます。実際のプロジェクトでは「自分以外の誰か」がチェックすることにして、クオリティをアップさせています。

Pull Requestを送る際は、リクエスト先が正しいか、ブランチ名が適切か、コミットメッセージが適切か、コミット単位がきちんと作業ごとに分けられているかを確認し、見る人にとって見やすいPull Requestにするように心がけます。

行単位でコメントすることができ便利です。ここでわかりにくい内容を解説したり、疑問点を議論することもよくあります。


git merge --no-ff {branch}

9. 変更内容に問題がないことを確認し、共有リポジトリ(ameba)のmasterブランチに取り込む(**git merge)
作業が完了したブランチ(ここではreleaseブランチ)をmasterブランチにマージします。この際、--no-ffオプションを付けると各ブランチでの作業がわかりやすくなります。
なお、実際のプロジェクトではこの作業をjenkins Jobにし、自動化しています。

merge

--no-ffオプションをつけると、必ずマージコミットを作成します。こうすることでそれぞれのブランチが独立し、修正内容を追いやすくなります。


おまけ (サンプルを使った予行練習)
Git導入の際、フロントエンジニアからは「なんか怖い」といった声が上がりました。Gitはあくまでツールであるため、一連の流れさえ覚えてしまえば問題ないので、あらかじめ以下のような予行練習をしました。

Mission 1 間違った名前を書き換える

まず最初に、メンバーの各自、自分の名前を正すミッションをこなしました。
ここでは、共有リポジトリからForkし、ローカルへclone、作業ブランチで作業し、Pull Requestするまでの流れを体験します。Pull RequestはMission 作成者(Gitに詳しい人)が行うとよいでしょう。
原 二成
烏山 幸佑
渡邉 美田紀


Mission 2 名前にローマ字表記を追加する

次に、自分の名前の横にローマ字表記を追加します。Mission 1の復習を兼ねています。ここではPull Requestを受ける練習もします。自分の下にある人のPull Requestを受けるルールにします。

原 一成 (hara_kazunari)
烏山 幸佑
渡邉 美田紀


Mission 3 項目を追加する (コンフリクトを解決する)

最後に、自分の名前の下にtwitter ユーザー名を追加します。改行が入るため、コンフリクトが発生する可能性が高くなり、それを解決してPull Requestを送らなくてはなりません。より実践に近い内容になります。

原 一成 (hara_kazunari)
* @herablog
烏山 幸佑
渡邉 美田紀



簡単なまとめになりましたが、いかがでしたでしょうか。
まだまだたくさんの機能や使い方がありますが、基本的には上記の内容を理解すると、ある程度使えるようになると思います。

AmebaではGit + GitHubを取り入れることにより作業スピード、品質共に向上させることができました。とても優れたプロダクトだと思いますので、ぜひ取り入れてみてください。
その際の参考になれば嬉しいです!