この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
こんにちは、shimadaです。
オープンソースの世界では着々と普及が進んでいる分散バージョン管理システム(DVCS)ですが、 商用開発の現場では、スケジュールの制約や実績、メンバーの習熟度の問題から、 実際のプロジェクトにはなかなか導入できないのが実情ではないでしょうか。
バージョン管理システムは、個人でちょこちょこいじってもノウハウは蓄積できません。なぜなら、チーム開発でしか起こらないコンフリクトやマージといった作業が、個人作業では発生しないからです。
僕らのチームでも、興味はあっても採用のきっかけがないという状況でした。
そこで、まずはDVCSをチームで使ってみるための入り口として、仕様書やスケジュールなどのドキュメントをDVCSで管理してみようというのが今回の試みです。
業務用のドキュメントはソースコードの他に、仕様書、設計書、スケジュールなどいろいろあります。 これは社内ではファイルサーバで共有・管理されています。
これらの管理にDVCSを導入するためのポイントは、
- 通常業務で使うこと
- 使う余裕のある人から段階的に導入できること
- 使っていない人が不自由を感じないこと
- バージョン管理システムの基本的なメリットを生かせること
- DVCSの基本的な概念や操作を体で覚えられるようになること
といった点です。これらをクリアできるような方法を考えなければいけません。
ひとくちにDVCSといっても、今ではいろいろなソフトウェアがリリースされています。 僕のイチ押しはGitなのですが、試してみたところ日本語のファイル名がエスケープされてしまって実用になりませんでした。 そこでいろいろ実験した結果、日本語ファイル名でもそこそこ実用になりそうなMercurialを使うことにしました。
まずプロジェクトで使っているファイルサーバのディレクトリをマウントしたあと、Mercurialのリポジトリにするためのコマンドを実行します。
% hg init
これで、ディレクトリの下の .hg/ 以下にリポジトリが作成されます。
% cat >.hgignore
syntax: glob
._*
.DS_Store
^D
Macでファイルサーバにファイルを作ると、メタ情報を格納するための隠しファイルを作成するようです。 Windowsから見るとディレクトリがかなりごちゃごちゃした感じになってしまいます。 そこで、.hgignoreというファイルを作ってMercurialからは無視するように設定します。 Macの作るメタ情報は、’.DS_Store’ と ‘._元ファイル名’ の2種類で、これらをはじくように設定します。
% hg addremove
Mercurialでは、作業ディレクトリを自動でスキャンして、新しいファイルをadd, なくなっているファイルをremoveしてくれる便利な「addremove」というコマンドが備わっています。
Subversionでは、ファイルを作成したり削除したりした場合、コマンドラインからひとつずつ add/remove する必要がありました。こういう作業をコマンド一発でやってくれるのは地味に便利です。
% hg commit -m 'initial commit'
最後にコミットすればプロジェクト用のディレクトリにあるファイル一式をリポジトリに登録完了です。
つぎにローカルで作業するためのクローンを作成します。
% hg clone 《ファイルサーバのディレクトリ》 《ローカルのディレクトリ》
マウントしたファイルサーバをリポジトリとして使うと、サーバーを建てなくても ローカルと同じ手軽さで clone/push/pull を行えるので便利です。
あとは、ローカルのディレクトリでファイルを作ったり更新したりして、 作業が一区切りしたときに
% hg commit -m 'コミットメッセージ'
% hg push
この二つのコマンドでファイルサーバ側に作業したチェンジセットを送信します。
ただし、まだ Mercurial を導入していないメンバーはファイルサーバのファイルを直接編集したりしていますので、pushする前に必ずファイルサーバのディレクトリに cd して
% hg status
を実行してファイルが更新されていないか確認します。
特にワープロや表計算ソフトのドキュメントは、開いたままだと一時ファイルやロックファイルが作られるので、 そのままの状態でコミットしてしまうと面倒なことになります。 チーム内で声を掛け合って、ファイルを開いている人はいませんか、と確認したりしています。
% hg addremove
% hg commit
これでまずファイルサーバ側で更新されたファイルをリポジトリにコミットします。 そのあとローカル側のpushを実行します。そのあと、ファイルサーバの作業ディレクトリをリポジトリに同期します。
% hg update
これで、自分の更新した内容がファイルサーバに反映されたことになります。
最初、自分ひとりだけが Mercurial を使い始めたときは、ローカルでコミットしてサーバでアップデートして、とかなりまだるっこしい作業を続けていました。
でも、ある時メンバーのひとりが、重要なスケジュール表のファイルを間違って削除してしまったのです。 ここで、バージョン管理の強みが生かされました。
% hg update
これだけで、消えてしまったファイルが復活しました。やっておいてよかった、としみじみ思った瞬間です。 また、他のメンバーにドキュメントをバージョン管理するメリットを印象づけるよい機会となりました。
今、僕のプロジェクトチームでは、コアメンバーは皆ドキュメントの更新にMercurialを使っています。「いま仕様書の変更をコミットしました」 「じゃあpullして確認します」
今はこんな感じで作業が進んでいます。 一人一人のローカル環境に、リポジトリのミラーが作られるという分散バージョン管理の基本も、使っているうちに飲み込めてきています。
「あれ、headが二つできてしまった」
「コミットする前にpullしておかないとそうなるんだよね」
「とりあえずマージしておけば大丈夫だよ」
そろそろプロジェクトでは、システムの実装に作業がシフトしつつあります。 ドキュメント管理には大活躍のMercurialですが、ソースコード管理は実績とノウハウの豊富なSubversionを使う方針です。
でも。
メンバーの間では、
「git svnっていいらしいね」
「GitとMercurialってどのくらい違うのかな」
「ああ、Gitにはステージングっていう概念があって……」
「ほほう、それは便利そうだ!」
などと、話が弾んでいます。社内のプロジェクトでGit/Subversionの併用事例が増えていくのは時間の問題じゃないかな、と個人的には思っています。