Subversionを使用し続けているプロジェクトがGitに移行することを考えてみた

# このページについて
中央集権型バージョン管理のCVSとSVN、分散バージョン管理のGit両方を各プロジェクトで使用してきた経験から、新規開発、保守開発でSVNを使用し続けているプロジェクトがGitを使うメリットについて考えて書いてみるページです。
あくまでも経験を下に主観で書いていきますので、いやいやその考え方は間違っているよ！とか、これも書いといて！というのがあれば、コメントやら編集リクエストなどください。

# 想定読者
* Gitを使ってみたいけど、保守開発だからSVNからGitに乗り換えるのなんて無理だよ！と半ば諦めている方
* SVNからGitに乗り換える提案をしたいから、乗り換えることで生じるメリット・デメリットが知りたいよ！という方
* うちはSVNで構成管理をしてきたんだ！Gitなんか誰も使ったことないから何かあったら誰が責任取ってくれるんだ！と使用を許してくれない上司を説得したいという方

# はじめに
このページはSVNからGitに移行すると幸せになることを記載するもので、
SVNを否定するものではありません。SVNも素晴らしい仕組みだと思っています。

# Gitで管理するものに向かないもの
Gitの良さに触れる前に向かないものを書いておきます。

Gitも全知全能の構成管理システムではありません。管理に向かないものもやっぱりあります。
それはバイナリファイルです。
（テキストの比較に特化しているのですが、バイナリにはあまり力を入れてないみたいで、昔はバイナリファイルを破壊したという噂も・・・）
つまりMS Officeなどで作られた設計書の類いはGitでの管理に向きません。
私自身、ソースコードはGit、ドキュメントはSVNと使い分けています。
もし、設計書をXMLや、Markdown言語などのテキストベースだけで書いてるよ！
ってところがあれば設計書もGitで管理して大丈夫だと思います。
（そのような取り組みをしている方がいたら事例を是非知りたいです）

# SVNについておさらい
言わずと知れた中央集権型のバージョン管理システムです。
日本のシステム開発現場で一番使われているのではないでしょうか。
ファイルをロックせずに編集・コミットが行えるということで当時は画期的な仕組みだったみたいです。

## メリット
* ファイルをロックせずに編集可能
* とはいえ、ロックしたい場面ではファイルのロックを行える
* 開発者が皆同じソースの状態を共有できる（中央集権型で享受できる最大のメリットだと思います）

## デメリット
* ブランチを作った場合、最後に行うマージ作業は超苦痛な作業であることが殆ど
* 誰かのミス（コミット漏れだったり、バグだったり）が開発者全員の迷惑に繋がる可能性を孕んでいる
* つまり、プロジェクトの方針によっては自由にコミットできずに、ローカル環境に未コミットなファイルが増えていく可能性がある
* この結果、意味のないコミット単位（例えば、Aの不具合修正をまとめてコミットするのが意味のあるコミットだが、これにBの不具合修正が混ざったりすること）でのコミットになり、いざというときに元に戻すのが苦痛、もしくは不可能となる

意味のあるコミット単位でコミットさせたいというのは、どのプロジェクトでも同じだと思いますが、現実はコミット漏れなどが発生するので不可能だと感じています。

SVNのデメリットを完璧とは言いませんが、おおよそ解決してくれるのがGitです。

# Gitについて

最初に述べたように、分散バージョン管理システムです。
これだけだと意味不明ですね。

Gitの最大の特徴は、自分専用のリポジトリをローカルPCに持つということです。
SVNは１つのリポジトリに対して、開発者みんなで編集・コミットし合っていきますが、
Gitでは１つのマスタリポジトリから、開発者自身が開発を行うローカルPCへリポジトリをまるっとコピー（Gitではcloneといいます）してその上で開発していきます。
まるっとコピーというのは、他の人のコミットやそのメッセージなどを含むリポジトリの状態すべてです。
日々の作業内容はローカルPC上のGitリポジトリにコミットし、作業が一段落したところでマスタリポジトリへ反映して開発を進めていきます。

## メリット、デメリット
私が思うGit導入のメリット、デメリットを書いてみます。

### メリット
* ブランチ間のマージが容易<BR>
-> 競合が起きないように構成管理計画を立てて実行していれば、マージは一瞬です。<BR>
SVNで苦労してマージする工数が浮きます。<BR>
SVNのマージ作業は生産的な活動とは云えないので、ここの工数が浮けばエンジニアが生産的な活動をする時間が増え、エンジニア自身の仕事の満足度も上がるのではないかと思います。（満足するかしないかは、浮いた時間で行う仕事の内容がそのエンジニアの興味範囲にあるかどうかが大きいですが。。。そういうタスクを宛てがってあげてください。）
* 開発者間でモジュールの受け渡しが容易<BR>
-> SVNだと場合によってはリポジトリではなく、ファイルサーバなどにファイルを置いてモジュールを受け渡すところを、Gitではモジュールを置いたブランチを連携して、モジュールを渡したい開発者にマージしてもらえば良くなります。
これにより、不確定な状態のモジュールをリリースブランチやtrunkに載せることなく、モジュールを実際に使う開発者に動作確認してもらえます。動作確認してNGだった場合は、モジュール修正後、再度同じブランチに上げましょう。
* 他の開発者のミスで影響を受けない。<BR>
-> Gitは開発者本人がブランチを切って開発することが基本になります。（最終的にマージを行うベースのブランチから更にブランチを切って開発を行うので。）<BR>
このため、異なる開発者が同じブランチで開発を行うことはあまりありません。つまり、ミスコミットでアプリが動かないんですけど。。という被害を受けるリスクが激減します。
* 必然的に意味のあるコミット単位になる。<BR>
-> 開発が一段落したところ（基本は画面Aの開発が終わったタイミングなど）で、ベースブランチにマージを行うため、マージがSVNで云うところの意味のあるコミットになります。
GitHub上でブランチへマージを行う場合は、プルリクエスト（マージするための最終チェックのお願い、OKならマージされる）で行うと思いますが、この承認行為が意味のあるコミット単位になります。
* リポジトリを別端末にバックアップしないといけないことが多数だと思いますが、Gitを使うと開発者のローカルPCにリポジトリをコピーしたものが置かれるので、バックアップストレージもしくはサーバが不要になる可能性があります。（自分とこの会社では開発者の端末でも構わないので、バックアップ用のサーバなどの余計な費用が削れました。）
* ソフトの受け入れが楽。<BR>
-> SVNを使用している現場では、オフショアなどの成果物の受け入れはExcel管理台帳を元に受け入れ担当者が大量のソースをマージしているところが多いのではないかと思います。<BR>
Gitを使用することで、マージが楽なのは勿論ですが、受け入れ用のブランチにソースを上げさせて、受け入れ側がそのブランチを使って動作確認を行えるようになります。<BR>
Excel管理台帳も必要なく、その場で動作確認、確認OKならベースブランチに取り込みができるというのは、大きなメリットです。
* コードレビューがしやすい
-> これはリポジトリサーバをGitHubなどのWEB画面で管理するシステムを使用している場合に、コードレビューがしやすくなります。
具体的には、プルリクエストというベースブランチへのマージのお願いを依頼するのですが、これを行うと、変更ファイルごとに変更箇所の差分をWEBで閲覧でき、より良い書き方があればWEB上で対象のコード（ラインに対して）直接コメントを書いてプルリクエストを送ってきた開発者に修正を依頼できます。
また、動作確認したい場合はブランチがリポジトリサーバ上に上がっているため、そのブランチをチェックアウトして動作確認も行えるので、想定どおりの動きをしているかどうかを確実に確認できます。（この辺はテストコードを書くプロジェクトであれば、テストコードで確認することになります。）

* CIに向いている
-> SIの現場でもJenkinsやTravis CIなどのCI環境を構築・運用しているプロジェクトがかなり増えました。
Gitを使用して、以下のようなブランチを切って開発するとCIをもう一段活用できます。

<pre>
1. 開発用マスタブランチ
2. リリース前動作確認用ブランチ（WEB系でよくステージングと云っているものです）
3. 本番環境リリース用ブランチ
</pre>

上記のブランチ構成とすることで、
<pre>
1.開発用マスタブランチでCIを回し、自動テストがすべて成功したら<BR>
2.リリース前動作確認用ブランチにマージを実行、ここでもCIを回し自動テストを実行し結果がすべて成功したら、リリース前動作確認用環境で打鍵確認し、それが完了後<BR>
3.本番環境リリース用ブランチにマージし、リリースする。
</pre>
みたいな活用ができます。
これは、テストがOKになったものを横のブランチ（開発用マスタブランチ -> リリース前動作確認用ブランチ -> 本番環境リリース用ブランチ）にスライドさせていくことで、
マージ漏れを防ぎつつ、動作完了したものをリリースブランチに載せることができます。
SVNとCIを連携させても、CIをここまで活用するのは至難の業だと思いますが、Gitを使うことですごく簡単にこのレベルのCIを構築することができます。

* SubversionでできることはGitを使えば全てできる<BR>
ブランチ運営しない（みんな同じブランチの上で開発する）ことも勿論可能です。
とりあえずGitに触れさせるには、Subversion的に使わせるのも良いと思います。
また、新規開発の開発初期時は、特に動くコードもないのでSubversion的に使うことはザラにあります。
※ある程度プロダクトコードが出来上がってきてからブランチ運営に変える。


### デメリット
* 自由度が高い<BR>
->このページでは使い方には触れていませんが、Gitについて調べると超自由だな。。。ということが判ると思います。SVN的なノリで運用しようとすると痛い目に遭うので、現場ではきちんとルールを作って開発者に遵守させる必要があります。
* 学習コストがかかる<BR>
-> SVNとはそれ相応に異なるため、初学のコストは高いです。とはいえ、１〜２週間使い続けていれば、ごく普通に使えるようになると思います。<BR>
※CVSからSVNに乗り換えるくらいに思っていると痛い目に遭う

# Gitに乗り換えると幸せになれると思うことのまとめ
ここまで書いてきたことを整理してみます。

* ブランチのマージの苦痛から解放される。
* マージに宛てていた時間がカットされるため、本業に集中できる時間が増える。
* モジュールの受け渡しが容易になるため、開発スピードは上がりやすい。
* モジュールの受け渡し時に、開発者間でのコミュニケーションが必然的に増えるため、聞きやすい環境が出来上がる（異なる会社で構成されたメンバだとやっぱり壁ができやすくコミュニケーションが滞りがちになりますが、コミュニケーションを取らないといけない環境に追い込むことができます）
* 聞きやすい環境ができると、モジュールの使い方などで認識齟齬が起こりづらくなり、モジュール開発者が意図しない使い方をされてしまうリスクが低減できる。
* コードレビューがしやすいので、コードレビューを行う癖が付く。

# SVNからGitに乗り換えるには
Gitについて色々書きましたが、SVNからGitに移行するためには、役職者を説得する必要があるので、そこについても考えてみます。
SVNを使用しているプロジェクトが対象ですが、新規開発でGitをはじめて使用する場合にも共通する部分があると思います。

## 役職者が気にすること
まず、新しいものを使用する際に役職者が気にしそうなことを挙げてみます。

* 誰かGitとやらを使える人間がいるのか
* Gitを使うとSVNに対して、どう優位に立てるのか。
* SVNからGitに切り替えるのは難しくないのか。
* 何かあったら誰が責任を取ってくれるのか。

この辺でしょうか。
２つ目の「Gitを使うとSVNに対して、どう優位に立てるのか。」については、既に記載しました。<BR>
定量的な判断材料があれば尚好しですが、ここではそこまでは書けません、というかプロジェクト各々の抱える問題なので判りません。
４つ目については、こんなことを言われたら憤りを感じずにはいられませんが、OSSでソース公開されているんだから見て何とかするわ！とでも云ってあげれば良いでしょう。それは半分は冗談として、本当に困ったらStackOverflowやGitHubのgitリポジトリにissueを上げましょう。（Gitはもう十二分に実績のあるツールなので、ソフト的な問題で何かあることはないと思います。問題が出るなら使い手の問題になると思います。）

１つ目と３つ目がクリアできれば説得できそうです。
個別に考えてみます。

### 誰かGitとやらを使える人間がいるのか
これはGitを入れたいと思ったあなたがなるのが一番の近道です。
社内外でGitを使える人を連れてきても良いですが、やりたい本人が使えることをアピールできた方が話が速いです。（人を連れてこようとすると、スキルマッチした人間を探さないといけないので敷居が高くなります）

じゃあ、Gitを使うにはどうしたら良い？ということになりますが、
これはGitHubを使いましょう。
GitHubは無料で使えるのでGitの練習にはうってつけです。
GitHubをマスタリポジトリにして、Git cloneでローカルPCにリポジトリをコピーしてあれこれ触ってみましょう。
言語系のハンズオンに参加しても、最近はGitHubを使うことが多いみたいなので、GitHubを使用したことがない人には懇切丁寧に使い方を教えてくれると思います。

また、GitのGUIクライアントを使う場合は、Eclipseプラグインはバグでリポジトリを破壊したなど良い噂を聞かないので使わない方が良いでしょう。
GitのGUIクライアントはSourceTreeを使うのが良いでしょう。
ライセンス認証しろと云ってきますが、無料なので登録してあげてください。

[GitHub](https://github.com/)
[SourceTree](https://ja.atlassian.com/software/sourcetree/overview/)

### SVNからGitに切り替えるのは難しくないのか。
結論を云うと容易です。
SVNからGitに変換をかけるgit-svnを使用します。

git-svnでSubversionリポジトリをGitリポジトリに変換したものをローカルPCに持ってきて、これを新しいGitを置くサーバに挙げてあげればGitリポジトリの完成です。
git-svnを使用すると、SVN上でのコミットログもすべて取り込まれるため、今迄行ってきた管理が無になることもありません。
以下のページの通りにやればできます。
[git-svnでSVN→Gitへの移行をやってみたログ](http://qiita.com/hidekuro/items/4727715fbda8f10b6b11)

Gitの練習でGitHubを使いたくない場合は、git-svnでローカルに持ってきたリポジトリを、さらにローカルの別ディレクトリにcloneしたものを使用しても良いでしょう。
ローカルでさらにcloneしたものを使うのは、誤ってサーバに挙げてしまわないためで、
誤ってしまった場合も、ローカルのgit-svnで作ったGitリポジトリがおかしくなるだけで済むためです。

## GitHubの代替ツール
会社によってはインターネット上のサービスは使えないと思います。
そんなときにはGitBucketを使いましょう。
GitBucketはGitHubクローンのWEBアプリです。
使い勝手もほぼGitHubです。
導入もGitBucket用のwarファイルをTomcatやjettyにデプロイしてあげれば動くので簡単です。
-> GitHub社からクレームが入ったらしく、今後はGitHubクローンは辞めるそうです。
段階的にGitHubからは離れて行くそうです。
そうするとどのツールを使用しても変わらないので、他のツールも挙げておきます。

* GitLab
* BitBucket
* GitBucket

どれを使ってもプルリクエストはあるので、先ずはビジュアル的に好きなものを選んで使ってみたら良いと思います。

# 最後に
SVNからGitに切り替えるのは技術的には容易です。
うまく上司を説得できれる手助けになれば。。
そして、これを読んでGitに挑戦したい、切り替えたいと思う人が出てくると嬉しいです。