matobaの備忘録

和歌山と東京を往復しつつ活動するエンジニアの記録

バージョン管理システムの違いや仕組みについて調べていた話

数年前の過去の自分のブログ記事を整理していて、説明したい気持ちになったことがありました。*1

というわけでニーズがあるのか分かりませんが、今の時点での知識で説明を書きます。間違えてたり、変な話だったらすいません。

それは、バージョン管理システムの違いや仕組みの話です。

過去の自分が気になっていたこと

過去の自分はこんなことをしていました。

  • バージョン管理システムの違いが気になって調べていた
  • バージョン管理システム間で考え方の違いに戸惑っていた
  • 制作中の音楽のバージョン管理をしたくてモゴモゴしていた

今回は同じようなことを調べているかもしれない人の役に立てば良いなと思います。

ちなみに、ここに書いてある話は、コードだけバージョン管理できたらハッピーになれる人には関係のない話です。コードだけバージョン管理したい人は、GitとGitHubを使えば幸せになれます。

最後に、僕がなぜ、上記のようなことを調べた背景を書いてるので、気になった方は読んでもらえるとありがたいです。

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

とりあえず、こんなバージョン管理システムの話が含まれています。

  • Subversion
  • Mercurial
  • Git
  • 各種アプリ(エディタやDAW)に付属してるバージョン管理システム

僕が使ったことがあるバージョン管理システムの話を中心に広げます。

そもそもの話なのですが、バージョン管理システムで重要なのは、「バージョンとは何か」「バージョンをどうやって管理するか」です。

読者の方は、ソフトウェアエンジニアの方が多いと思うので、ソフトウェアのバージョン管理の話から考えます。

どうやってソフトウェアを管理するか

ソフトウェアのバージョン管理でいうと、一つのバージョンには、コードが記述された複数のファイルの状態とディレクトリ構造が含まれています。

で、どうやってバージョンを管理するか、の話なのですが、例えば、Mercurialはバージョンを直前のバージョンとの差分で管理しています。言い換えれば、データベースには直前のバージョンと直後のバージョンの差分が保存されています。Subversionもこの形式になっています。

各ファイルをdiffしてその差分を記録しているのです。

一方でGitはバージョンをファイルごと管理しています。 変更があったファイルをそのまま保存するのです。差分が一部だったとしてもファイルをそのまま保存します。ちょっとでも差分があれば、それは新しいファイルとして保存していて、差分がどれだけあるか、というのは保存していません。

この話の裏が欲しい人は、GitProのこの辺(Git - Gitの基本)を参照してください。

なぜ、Gitはファイルごと管理するのか

これがどう嬉しいかというと、Gitでは過去のバージョンにHEADを変えたときに、そのリビジョンにサクッと移動できるのです。Linuxでcdコマンドを実行した時と同じような体感で、リビジョンを変更できます。

直前との差分でバージョンを管理していると過去のバージョンを参照しようとしたときにも差分を辿っていかないといけません。複数のブランチで開発していたり、過去の履歴になればなるほど、過去バージョンの参照に時間がかかります。ただし、トータルで見たときのリポジトリの容量は差分で管理した方が少なくなります。必要なリポジトリの容量は、システムの費用に直結します。

これを別の言い方にすれば、過去のバージョンの仕様をコードやコミットログから把握しない前提を作れば、差分管理のバージョン管理を採用する方がトータルコストが下がる、ということです。逆に、差分管理のバージョン管理(SubversionやMercurial)を採用している場合、コードから仕様を把握するためのハードルがGitを使っている時と比べて上がっています。

GitはLinuxカーネルの開発者であるリーナストーバルス氏が、Linuxカーネルを開発するために作ったものです。Gitの略史というものがあるので、裏としてはこちらを参照してください。 see Git - Git略史

Gitは開発者がスムーズに特定のリビジョンを参照できるように作られた。ということを考えたら、どうしてそういう違いが生まれているのかを理解しやすいように思います。

どう使い分けるのですか?

こういう話をしていると、「では、若者(というか、数年前の僕)はSubversionやMercurialはどういうタイミングで使うといいのですか?」とか考えたくなっていました。

僕は今のところ、「とりあえず、Gitを使うようにしてGitを使ったときに発生する問題は、別の方法で対策する」と言うのが時代の流れのように思ってます。

とはいえ、気になる人は気になると思うので、今の僕が考えていることを説明してみます。

Subversionについて

あくまで予想の範疇ですが、Subversionが登場した時代(2000年ごろ)は、「今よりも業界の規模や予算が小さくて、費用を絞らざるを得なかった」とか「エンジニア一人当たりの生産性を上げるより、エンジニアの数を増やして、トータルの生産性を上げようとしていた」と言うのもあるのかもなあと、推察しています。

それから、その前段に「商用バージョン管理システムしかなくて、とりあえずオープンなバージョン管理システムが欲しい」みたいな話があったのかもしれないです。

ちなみに、過去の話がどうしても気になる人は、次のあたりの本を読むと良いかもです。

今は、「エンジニアの数を増やしても、トータルの生産性の上昇は効率が悪いから、できるだけ一人当たりのパフォーマンスをあげたい」とか、「ITがビジネスの中心になっているので、エンジニアの数を一人でも増やして、スピードアップしたい。エンジニアが高給でも雇いたい。開発マシンなんて安い」と言う時代なので、考えなくて良いと思います。

Mercurialについて

あと、Mercurialの歴史については、僕もWikipedia情報ですが、こちらもそもそもがLinuxカーネルの開発者であるMatt Mackall氏が開発を進めていたもので、「ファイルそのものを管理するのではなく、差分を管理すべき」と言うのがコアの主張だったようです。

see: Mercurial - Wikipedia

GitもMercurialも2005年に登場したものです。

これも、あくまで予想の範疇ですが、当時は、今よりもネットワークの速度が遅かったり、ストレージ単価が高かったりしました。あと、GitHubもなくて、オープンソース活動が活発と言う状況でもなかったのだろうなあ、と言うことを省みると「Gitのようなファイル単位で管理する仕組みを導入すると、開発を行うために必要なハードウェアが高価になる。そうすると、オープンソース活動への参加障壁が上がってしまう。Linuxのようなオープンに開発を進めるソフトウェアは、率先して、開発への参加障壁も下げるべきである。だから差分でファイルを管理すべきだ」と言う考えがあったんじゃないかなあ、などと思ったりしました。

ですので、もし、現場でMercurialを使おうとしてたり、使っている職場があるなら、そのベースには「たくさんの人にソフトウェア開発に参加して欲しい」とか「ソフトウェア開発をするの準備費用を下げて、できるだけ多くの人に給料を出したい」みたいな気持ちがある可能性もなきにしもあらずかなあ、と思います。

とはいえ、今はネットワーク速度も上がって、ストレージ単価も下がっていていますし、GitHubもありますので、そう言う話はおいといて、Gitを選ぶと言うことで良いように思います。

ついでのお話

あと、ついでに伝えておくと、少ないないとは思いますが、現在でもMercurialやSubversionを使っているプロジェクトはあるんじゃないかなあ、と思います。

そう言うプロジェクトに遭遇した際に「えっ、Gitを使ってないとかどれだけ時代遅れw」みたいな煽りを入れるのはやめましょう。

MercurialにしてもSubversionにしても、なんらかの問題を解決してきた素晴らしいソフトウェアですし、それらの技術を選定した人にも何らかの考えがあって選んでいるので、敬意を払うのをオススメします。

あと、そもそもソフトウェアが微妙なら途中で捨てられるので、長く続いているプロジェクトはそれだけで価値を生み出しているとも言えます。

と言うわけで、そういう現場に遭遇したら、先人に敬意を払いつつ「おっ、今、流行のDXに最適な題材があるじゃん」と思って、Gitへの移行を頑張るのをお勧めします。

なお、及川卓也氏のソフトウェア・ファーストによるとDXは、「自社プロダクトの成長に関わるコア技術を自分たちが主導権を持って企画・開発できるようにすること」です。Gitは管理より企画や開発のスピードに重きが置かれたツールですので、DXと言う言葉を使えば、Gitに移行しやすいかもしれません。(他人事ですが)

もし、それが嫌でさっさと最新技術だけを使いたいのであれば、速やかにスタートアップに転職するのがお勧めです。ただ、そちらはそちらで最新技術を使い続けるフィールドなので、どちらが幸せかはわからないのですが。

アプリのバージョン管理について

さて、上記の話を踏まえた上で、アプリでのバージョン管理の話をします。

アプリのバージョン管理を考える場合は、何をファイルそのもので管理して、何を構造データとしてデータベースに保存するかを考えることが必要だと思います。

当たり前ですが、次のようなデータは、データベースに保存すると、扱いやすいと思います。

  • プロジェクト名
  • プロジェクトの設定
  • 起動バージョン
  • 導入されているプラグインの種類
  • プラグインの設定情報
  • プロジェクトの中に含まれるファイルのパス一覧

言わずもがなですが、データベースに保存しておくことで、検索がしやすくなりますし、一括更新もできるようになるからです。

あとは、これらの管理は、差分管理ではなくて、要素単位のスナップショットをデータベースに格納していくと検索も復旧も差分抽出もしやすくなるんじゃないかなと思います。diffの場合は比較したいリビジョンを両方持ってきて、diffをとれば良いので、シンプルですし、復旧もある地点以前の最新を持ってくればいいので。

PythonのDjangoのAdmin画面には、変更履歴管理機能がついていますが、参考になりそうな気がします。

それから次のようなデータは、データベースに格納するのはなくて、安価なストレージに配置するのが良さそうです。*2

  • 画像
  • 映像
  • その他ログや時系列データ

当然ですが、一つ一つの情報が大きい上に、人間の視点でちょっと修正するとファイル全体に修正がかかります。一方でスナップショットをとらないと、いざ、特定のバージョンに回帰したいとなったときに、時間がかかりすぎます。そもそも、これらの情報のバージョン管理では、差分が求められることはそうそうないように思います。データだけを比較してdiffをとることは難しいので、基本的に二つのバージョンを出して、人間が見比べる状況になります。

ですので、基本は、常に新しいファイルをストレージに保存することにして、データベースで参照先を管理するのが良いように思います。また、上記のようなメディアデータの保存は、少々重くてUX的によろしくないので、バックグラウンドで常に最新を保存し続けて、ユーザーが保存ボタンを押したら、DBの参照先だけを変えている様子のアプリも散見します。

なお、常に新しいファイルをストレージに追加し続けるパターンだと、ストレージの容量が膨張し続けて辛くなります。それを抑止するための仕組みはいくつかあって、パッと思いつく限り、次のパターンがあります。

  • 過去のリビジョン数に制限をかける(10個しか保持しない)
  • 参照可能なリビジョンの期間に制限をかける(1年分しか見せない)
  • リビジョンを何らかの条件で圧縮する(翌日になると、前日のファイルは一つだけにする。指定した区間のリビジョンをまとめさせる)

ファイルのバージョン管理は、いわばバックアップなので、バックアップをどう言う単位で持っておくか、と言う話と同じ話になります。ついでに言うと、このバージョン管理は、課金ポイントになりやすいように思います。

バージョン管理は、データの保持の仕方によって、使い勝手がかなり変わると思いますので、データをどうもつか、というのが結構重要なポイントだと思います。

そもそも、僕がやりたかったこと

はい。とりあえず今、思い出し分は書いたので、ここからはおまけの僕の話です。

僕は、バージョン管理について、いろいろ気になって調べていたのですが、その背景には「DAW(デジタルオーディオワークステーション)で音楽を作っている時のプロジェクトをスムーズにバージョン管理する仕組みが欲しい」と言う気持ちがありました。

学生時代の私は、DAWを使って音楽を制作していたんですよね。その当時で、50トラック以上のwavファイルをDAWに展開して、制作を進めていました。

waveファイルは、自身が演奏して収録したものから、打ち込みしたmidiデータをレンダリングしたもの、共同制作者から渡されたものもありました。そして、音楽の制作は、自分のものだけでなく、人から依頼された物もあり、クライアントから渡された音素材もあります。

依頼されて制作している場合は、複数バージョンを作った後に、レビューに出して、レビューの後に任意のバージョンから制作を再開する必要が出てきたりします。ここでバージョン管理という概念が必要になりました。

ただ、当時はバージョン管理の機能がなかったので、僕はプロジェクトを丸ごとコピーして、ファイル名でプロジェクトバージョン管理したりしていました。ただ、これの管理がなかなか辛い。特に、途中から編集したりすると、結局どれが最新か分からなくなったりするわけです。辛い。

この問題を僕は解決したかったりしたんですよね。そして時代は流れて、現在では、僕が使っているStudio Oneと言うDAWにはバージョン管理機能がついていて僕はこちらを使っているので、僕の問題は解消されました。

www.mi7.co.jp

ただ、せっかく集めた知識なので、誰かが再利用してくれたらいいな、と言う気持ちを込めて、ここに書きました。

ではでは

*1:ちなみに「この情報は害悪だな」とか「この主張は恥ずかしいな」と思った記事を整理するのが目的なので、その記事は、すでに非公開にしています

*2:映像データは、もうちょっと工夫が必要かと思いますが、本記事では、詳しく話しません