torutkのブログ

ソフトウェア・エンジニアのブログ

ソースコードのバージョン管理スタイルを見直す

先月、Subversionを使ってきたチームにGitを導入して苦戦したことを日記に書きました。
ソースコード管理ツールをSubversionからGitへ変更して感じたこと - torutkの日記

それ以降、うまくGitを使うにはどうしたらよいかを考えてきました。まだ決定打(ベストプラクティス)はありませんが、思考の整理をすべく日記にします。

Subversionを現状どう使っているのか?

まず、Subversionでの開発作業におけるソースコードのバージョン管理のしかたについて、コミットしてもよい条件の観点で分類してみます。

管理スタイル コミット縛り 備考
自由 なし ファイル共有サーバーの延長
緩い統制 ビルドが通ること バージョン管理の入り口
品質統制(1) テストが通ったこと
品質統制(2) レビューが通ったこと

もっとも原始的なスタイルは、いつでも自由にコミットできることです。今日はそろそろ帰るからコミットしておこう、などが典型です。リポジトリへのコミットに縛りがないので、コンパイルが通ったかどうかの確認は開発者へお任せ状態です。
開発者の個人環境ではさすがにコンパイルは通っている(と信じている)のですが、同時に何人もコミットしていると、リポジトリ上の整合がとれているか(コンパイルがとおるか)は神頼みなスタイルです。
実はこのスタイルが多いのではないかと思っているのですが・・・(身の回りだけ?)

緩い管理スタイルは、ビルドが通ることの確認をコミット時に義務付けるものです。確認にはいくつか方法がありますので、実行手順にはいろいろバリエーションがあります。たとえば、コミットをフックしてサーバー側でビルドを実行するCI(継続的インテグレーション)環境を用意する方法、コミット前にリポジトリへ追随(svn update)させ、クリーンビルドを実施してからOKであればコミットする方法、そのほかにも、いろいろな方法があるかと思います。

品質のチェックポイントをコミットに課すスタイルがあります。実践したことがないのですが、世の中の事例ではユニットテストが通ったらコミットできるというルールを設けているもの、コードレビューが通ったらコミットできるというルールを設けているものがありました。

開発者視点

Subversion環境では、コミット縛りが厳しくなればなるほどコミット頻度が減り、コミットできるようになるまでの期間が長くなります。コミットができない期間は、開発者のローカルな環境で修正作業を続けなくてはなりません。すると、


C:\Users\torutk\Documents\projectA
+-- SensorView
+-- SensorView_20140215
+-- SensorView_ユニットテスト追加中
+-- SensorView.bak
+-- SensorView_イベントハンドル書き換え版
:
なんてことが起きてしまいます。「あれ、SensorView.bakっていつの時点のバックアップだっけ?」など。バージョン管理ツールを導入していながら、バージョン管理ツールのないときの作業に戻ってしまっています。最近の統合開発環境IDE)は、バージョン管理ツールがなくてもローカルの修正履歴を持つのである程度のやり直しが可能となっています。この機能のおかげでローカルの作業がある程度バージョン管理ツールの支援なくてもこなせるようになります。

Subversionにもブランチ機能があり、個人用のブランチ(トピックブランチ)を作ることができますが、ブランチを作って後でマージするのは面倒ですから、ローカルの上で安直にディレクトリコピーしてしまいます。

ローカル上でSubversionを使う手も考えられますが、Subversionは(前のバージョンまでは)各ディレクトリに.svnという管理ディレクトリを作るので、リモートとローカルと異なるリポジトリ用の作業を同じ場所ですることができません。それに面倒ですし。

そういった状況から、コミットできない期間が長くなってしまう品質統制をかけると悲鳴(ブーイング)が上がります。現実的な妥協点がコミットのビルド縛りです。なので、Subversionを使ったバージョン管理環境ではビルド縛りが多いのかと思います。

コミット縛りによってSubversionにコミットできるまでの期間、バージョン管理ツールの恩恵がない中での作業を余儀なくされてしまいます。ですが、それを不便と思う意識はそれほどないようです。

管理視点

管理視点からは、上の方は「問題が起きたら対処すればよい」という事後処置型、下の方は「問題が起きないように仕組みを講じる」という事前予防型です。品質管理目線ではもちろん予防型が望ましいのですが、プロジェクトあるいは組織の体質が「問題が起きたら対処する」場合、事前予防型の施策はなかなか浸透しないです。
開発環境構築、ビルド、構成管理の専門チームがなく、みんなスケジュールに追われて開発作業に没頭している片手間でなんとか構成管理し、ビルドしていたりする実状では、とてもレビュー体制、計画(リソース配分)は整わないです。

という状況だと、最低困らない程度の縛りとしてやはりビルドが通ることがコミット縛りになるのかもしれません。

Gitをうまく活用する

GitHubの「プルリクエスト」文化はレビューを促進する?

Gitの開発ワークフローで注目を集めているのが「プルリクエスト」です。

各開発者がある時点の共有リポジトリをベースラインとしてそこに1つの機能(1つの修正)を加えるところは従来どおりです。しかし、その結果を開発者がリポジトリに直接反映するのではなく、しかるべき責任者に「プルリクエスト」を送るというものです。「プルリクエスト」を受けた責任者は、その内容を確認し、妥当であればリポジトリに反映します。妥当でない場合は差し戻します。ここでコードレビューが必然的に発生します。これは、バージョン管理において、コミット縛りに「コードレビュー」を要求する管理スタイルに該当します。

開発者にとっては、レビューが妥当になるまでチームで共有するリポジトリに反映されないので、従来のSubversionではコミット期間が長くなる問題がありましたが、Gitを使っている場合はローカルで個人的なブランチにいかようにでもコミットすることができるので、ローカル上でのソースコード修正にバージョン管理ツールの支援が得られます。

そして、開発者個人での作業が完成した時点でその機能の責任者に「プルリクエスト」を送ります。共有リポジトリへの反映は責任者の作業なので、開発者は共有リポジトリへのマージ作業は不要です。責任者はコードレビューをして妥当と判断したらそれを共有リポジトリへマージします。
コンフリクトが生じたら(それはたぶん別な開発者と変更が競合したことになるので)、差し戻します。

このGit(GitHub流)のプルリクエストを導入すると、コミットできない期間が長引いてもローカル作業に支障は少なく、また、開発者各自が難しいバージョン管理ツールのマージ作業をする必要もなくなります。
GitHubではなく、Gitだけでもプルリクエストは可能です(ワークフローなので)。トピックブランチを共有リポジトリにpushして、何らかの連絡手段でマージ依頼をする(RedmineとGitを連携していればチケットのワークフローに含めたり、Redmineのコードレビュープラグインでレビュー依頼を出すなど)ことで実現可能です。

ただし、管理上の負担(コードレビューする体制、マージ作業の発生)が課題として残ります。これは必要な作業なのでいままで無視してきたプロジェクト管理側の問題なのかもしれませんが・・・

プルリクエストを取り入れることは仕事の仕方を変えること

ツールとしてのGitと、ワークフロー(作業手順)でのプルリクエストを取り入れることで、ソフトウェア開発に品質統制(コードレビュー)を加えることが出来るようになります。しかし、ワークフローを変えることはすなわち仕事の仕方を変える必要があります。

レビュー文化の未熟な組織にとっては、「いままでコードレビューしなくても大きな問題なくできてきたじゃないか」などとうそぶく人もいるかもしれませんし、「レビューを要求されるなら、その分工数が増えるので請求も増えます」と品質活動をコストに転換することもあるかもしれません。

一方、レビュー文化が根付いている組織にとっては、それまでの作業にツールサポートが得られるので便利に感じることと思います。

プルリクエストを取り入れないときのGitの促進

やはり、共有リポジトリへコミットできるレベルになるまでローカルで開発作業を行うときに、バージョン管理ツールの支援を受けることが一番ですが、プルリクエストの導入に比べるとメリットが少し薄いかもしれません。

ソースコードの開発作業(機能、修正ごとの小作業)の着手時に原則トピックブランチをローカルに作成し、そのトピックブランチ上で作業を完成させたら共用リポジトリのメインブランチの最新情報をローカルに取り込み、トピックブランチをローカルのメインブランチにマージして、競合があれば解決してリモートにプッシュする、という一連の作業をする必要があります。(文章で書くだけでも随分かかりますね)

とはいえ、開発時のいろいろな試行錯誤(バグの原因箇所究明のためにあちこちログをいれる、実験レベルのコードを書いて確認する、リファクタリングをしていく、など)をやっては戻し、また別なやり方でやっては戻し、とする際はバージョン管理ツールがあると楽になります。

そのためには、最初にある程度Gitをつかいこなすトレーニングが必要になります。そうでないと、Gitではうまくできないから手作業でソースディレクトリのコピーをとっておく、といった旧来なやり方に戻ってしまいます。