Git
svn
初心者
バージョン管理
新人プログラマ応援

【新人向け】これだけは知っておいて欲しい基礎知識 バージョン管理編

Opening

今回はバージョン管理ツールについて
個人で開発をしている分にはあったら嬉しい程度のツールですが、複数人で開発をする場合は必須(のはず…いまだに共有ドライブで開発しているのは自殺行為だと思います)のツールなので、コマンドを覚えるだけでなく、どういう運用をすべきか考えられるレベルを目指しましょう。
バージョン管理システムは色々ありますが、当記事ではGitとSVNについて説明します。

Appendices

そのうち書き足していくつもりです。

Body

バージョン管理システムとは

まずは、バージョン管理システムの概要について

バージョン管理は、特定のファイルに対して加えられていく変更を保存し、後からその当時の状態に戻れるように変更履歴を残します。ここでいう変更履歴とは5W1Hのような情報を指していて、「いつ」「誰が」「どのように」ファイルを変更したかを記録していくことが大切です。特にシステム開発など、複数人が同一のファイルを頻繁に更新するような状況で、ファイルをバージョン管理する必要がある場合に活用されます。
対象となるファイルの種類に制限はなく、ソースコードに限らずさまざまなフォーマットのドキュメントや画像・動画ファイル、音楽ファイルなども管理できます。変更履歴を逐一記録しておけば、内容を過去の状態に戻すこともできるようになり、ファイルの扱いやすさが飛躍的に向上します。

Git

続いて、現在デファクトスタンダードなバージョン管理システムであるGitについて

Gitとは?

Gitは分散型のソースコード管理システムです。ソースコードに対して加えられた変更点を記録し、任意の時点のコードを復元するバージョン管理機能や、ほかの開発者がソースコードに加えた変更を自分のソースコードに取り込むマージ機能、ほかの開発者が公開しているソースコードを自分の作業環境にコピーするクローン機能といった、ソフトウェア開発において有用な多数の機能を備えています。

細かな使い方については、公式ドキュメントを読むのが一番だと思います。
(他にも良記事はいっぱいありますが、細部が間違っていて苦労した経験があるので…)
バージョン管理の用語についてもリンクを載せたかったのですが、だいたいセットで間違った内容がくっついていたので、公式ドキュメントを読みながら勉強しましょう。

ホスティングサービス

Gitではホスティングサービスを利用してリモートリポジトリを建てるのが一般的なので、どんなサービスがあるのか押さえておきましょう。
個人的には、エンタープライズだとGitLabが使いやすいんじゃないかなぁと思っています。
ただ、GitHubほどネット上に良記事は転がっていないので、マージリクエストなどの運用方法について記事を書きたいところ。

GitHub

ソーシャルコーディングの草分け的存在となった、プロジェクトホスティング+SNSのサービスです。
法人利用(Organization plans)は個人でプライベートリポジトリを持つよりも高いですが、ビジネス利用に最適化されている(公式サイト)とのこと。
セキュリティ上の理由でGitHubにソースコードが置けない場合には、社内ネットワーク上において使うGitHub Enterpriseという選択肢もあります。

GitLab

GitLabはGitHubのクローンプロジェクト。MITライセンスで公開されており、無料で使えます。
GitHubクローンとしてかなり忠実に作られているため、GitHubに慣れたユーザでも違和感なく使うことができます。
ユーザごとにサーバを用意してインストールするのが特徴で、GitHub Enterpriseほどの費用がかからないのはうれしいところ(メンテナンスコストは別途見積もりましょう)

ブランチモデル

Gitにはブランチモデルが複数あります。
「必ずどれかに従ってブランチを切らなければいけない」というわけではありませんが、各々のプロジェクトに適したブランチの切り方を考えるためにも、以下の3つのプラクティスについて勉強しておきましょう。
(普段「GitLab flowのような何か」を採用しているのですが、使っているうちにGit-flowとの違いがわからなくなってきてしまったので、もう少し勉強して記事にまとめておきたいと思います。)

Git-flow

Git-flowはGitブランチを活用するために最初に提案されたフローの1つで、大変注目されました。masterブランチとは別にdevelopブランチがあり、その他にfeature、release、hotfixというブランチがあります。developブランチでの開発作業を進めた後に、releaseブランチを作成し、成果は最終的にmasterブランチへマージされます。Git-flowはよくできた標準モデルですが、複雑なために2つの問題があります。1つは開発者がmasterブランチではなく、developブランチを利用しなくてはいけないことです。2つ目の問題は、hotfixブランチとreleaseブランチがもたらす複雑さです。

GitHub flow

Git-flowをよりシンプルにしたのがGitHub flowです。GitHub flowではfeatureブランチとmasterブランチしか使いません。シンプルでわかりやすいフローで、多くの開発チームが採用し成功を収めています。Atlassianブログでも類似した戦略が勧められていますが、それはfeatureブランチをリベースするやり方です。全てをmasterブランチにマージし、こまめにデプロイすることで、デプロイ待ちのコードの量を最小限にできます。これは無駄のない継続的デリバリのベストプラクティスにも則っています。しかしGitHub flowにも、デプロイ、環境、リリース、インテグレーションについて問題があります。

GitLab flow

GitHub flowでは、featureブランチをマージするたびに本番環境へデプロイ出来ることを想定します。しかしそれはSaaSアプリケーションでは可能ですが、大抵の場合はできません。リリース時間をコントロールできない例の1つはiOSアプリケーションで、AppStoreのバリデーションをパスする必要があります。また別の例としては、デプロイの時間枠(平日午前10時~午後4時、オペレーションチームがフル稼働の場合)があるのに、その時間外にコードをマージする場合です。そういう場合には、デプロイしたコードを反映させたproductionブランチを作成します。masterブランチからproductionブランチにマージして新しいバージョンをデプロイできます。本番環境のコードを知るためにはcheckoutでproductionブランチに切り替えればいいわけです。

SVN

お次は、Subversionについて
Subversion自体は嫌いではないですが、Subversionに固執するメンバーに嫌な思いをさせられているので記事のチョイスはてきとーです。
「ブランチ」や「タグ」、「チェックアウト」など、用語の意味や動作がGitと異なるものがあるので注意が必要です。

歴史的には広く使われているバージョン管理システムの一つにCVSがあった。CVSにはディレクトリの移動の管理やネットワーク対応の点、不可分な更新などの点で難があった。これらCVSの問題点を解決すべく開発されたのがSubversionである。
Subversionは集中型(クライアント・サーバ型)であるが、その後、GitやMercurialやBazaarなどの分散型のバージョン管理システムが登場するようになった。例えば、Linuxカーネルの管理にはGit、Mozilla Firefoxの管理にはMercurial、MySQLの管理にはBazaarが使われている。

ブランチモデル

正確にはブランチモデルではありませんが、Gitのブランチモデルに対応するような、SVNのフォルダ構成の考え方について
SVNのクライアントツールは下記のフォルダ構成を前提にしていることが多いので、特別な理由がない限りは標準のフォルダ構成にしておきましょう。
また、branch-es、tag-sとsが付くように、それぞれのフォルダはbranch、tagをグルーピングしたフォルダになります。
branchesの下でbranchを分けず、それより下の階層でbranchを分けるのは標準から外れるのでやめましょう。
(ツールによってはブランチ作成やマージにひと手間掛かるようになるので辛さが増します。)

trunk

trunk(トランク)は、開発の中心(メインライン)となるディレクトリで、ほとんどのファイルをここに格納します。通常は開発中の最新バージョンを格納しておきます。Gitでいう、masterブランチのようなものですね。後述するbranchesのひとつと考えることもできます。最低限トランクさえあれば開発を進めていくことができますので、初心者の方はまずここからはじめてみましょう。

branches

branches(ブランチ)は、トランクから分岐した別のツリーです。ブランチ(枝)という名前は、トランク(幹)から枝分かれすることからきています。トランクとは別に開発を進めたいときに、トランクからブランチを作ります。ブランチを作るということは、トランクディレクトリをブランチとして、「branches」ディレクトリ内にコピーすることです。別々のディレクトリとして存在しますので、もちろん履歴も別々のリビジョンを持つことになります。

tags

tags(タグ)は、ある特定時点のトランクに名前をつけたものです。Subversionのリポジトリは履歴を保持しているため、いつでも過去のファイルを自由に取り出すことができます。しかしリビジョン番号では、取り出したい履歴がいくつのリビジョンなのかすぐにはわかりません。そこでタグとして名前をつけておくことで、必要なときにタグを参照してすぐに取り出せるようにします。タグの実態は、tagsディレクトリ内にコピーされたトランクディレクトリです。通常、一度作成したタグを変更することはありません。デフォルトでは、ファイルは読み取り専用になっていませんので、誤って変更してしまわないように注意しましょう。

Git vs. SVN

「結局GitとSVNってどっちが良いの?」という質問に対しては、基本的にGitを採用しておけば間違いないと思っています。
集中管理方式と分散管理方式の違いや学習コストなどで比較されることが多いと思いますが、そもそも特別な理由がない限りはデファクトスタンダードな技術・ツールを採用する方が辛さは少ないと思っています。
SVNであれば特定フォルダだけローカルに落として作業することが簡単にできたりと、SVNなりの良さはあります。が、Qiita内の記事を読んでいれば分かるように、環境構築の話ではGitを採用することを前提としている記事が多かったり、不具合やエラーの対応方法が簡単に検索に引っかかったりと、利用しているユーザーが多い技術・ツールほど良質なドキュメントが多く存在します。(その分間違った内容の記事を目にする機会も多いですが)

参考:
Git 特定のフォルダのみcloneする - Qiita

以下、蛇足ですがGitとSVNでよく比較される内容について個人的な意見を書いていきます。

学習コスト

GitはSVNより学習コストが掛かると説明している記事は多いですが、個人的な意見としてはむしろ今からSVNを学ぶ方が学習コストは高いと思っています。
Gitと比較してSVNの方が学習コストが掛からないと言われるのは、SVNでは複雑な運用をすることが少ないという文化に起因していると思っています。SVNでチケット毎にブランチを作成して、コードレビューを設けてマージをし、CIまで回そうと思うと参考になるドキュメントを探すのも一苦労です。
既にSVNを利用しており事情があってGitに移行できない等でもない限り、Gitを学べば良いと思っています。

ローカルコミット

SVNと比較してGitの便利な点としてよく挙げられているローカルコミットですが、個人的には手間でしかないと思っています。
開発途中のソースをコミットできるという利点は、ブランチを細かく作成する運用をしていればSVNでも同じことができます。また、複数人で開発している場合、(当たり前ですが)ローカルコミットはローカルリポジトリにしか反映されません。開発メンバーが事故や病気で急に数週間不在になったり、端末が故障したりした場合、ローカルコミットの内容を拾うのは難しくなります。チームでバージョン管理システムを使うのであれば、リモートリポジトリに反映させなければ意味がありません。基本的には、ブランチを細かく作成し、日々リモートに反映させるのが理想だと思います。ただ、そうした運用をするとコミットログが荒れてしまうので、rebaseで後からコミットログを分かり易く編集できるGitの方が優れていると思います。

Closing

以上です。