(57)【要約】【課題】バージョン管理において複数のブランチのマージを効率化する。【解決手段】情報処理装置１０は、それぞれ自ノードが有する情報に応じた識別子が付与される複数のノードを含むバージョン管理グラフ１３に対して、既存のノードが有する情報を編集することを許容する。情報処理装置１０は、バージョン管理グラフ１３に含まれるブランチ１３ａとブランチ１３ｂとをマージするとき、履歴情報１４に基づいて、ブランチ１３ａに含まれるノードＢが参照するデータｂとブランチ１３ｂに含まれるノードＣ＋が参照するデータｃとから生成された過去のマージ結果のデータｘを検索する。情報処理装置１０は、検索されたデータｘを用いて、ブランチ１３ａとブランチ１３ｂとをマージしたときの新たなマージ結果のデータｙを生成する。【選択図】図１
2014191672.tif 000002
【特許請求の範囲】
【請求項１】
コンピュータに、
それぞれが複数のバージョンのデータの何れかを参照しており自ノードが有する情報に応じた識別子が付与される複数のノードを含む、バージョン間の関係を示すバージョン管理グラフに対して、既存のノードが有する情報を編集することを許容し、
前記バージョン管理グラフに含まれる第１のブランチと第２のブランチとをマージするとき、過去に行われたマージについて２以上のバージョンのデータとマージ結果のデータとの対応関係を示す履歴情報に基づいて、前記第１のブランチに含まれるノードが参照する第１のバージョンのデータと前記第２のブランチに含まれるノードが参照する第２のバージョンのデータとから生成された過去のマージ結果のデータを検索し、
検索された前記過去のマージ結果のデータを用いて、前記第１のブランチと前記第２のブランチとをマージしたときの新たなマージ結果のデータを生成する、
処理を実行させるプログラム。
【請求項２】
検索された前記過去のマージ結果のデータを参照する他のノードを前記バージョン管理グラフに追加し、前記他のノードを含む前記バージョン管理グラフに基づいて、前記過去のマージ結果のデータを利用するマージ方法を決定する、
請求項１記載のプログラム。
【請求項３】
前記履歴情報は、前記２以上のバージョンのデータに含まれる２以上のサブデータと前記マージ結果のデータに含まれるマージ結果のサブデータとの対応関係を更に示し、
前記過去のマージ結果のデータが存在しない場合、前記履歴情報に基づいて、前記第１のバージョンのデータに含まれる第１のサブデータと前記第２のバージョンのデータに含まれる第２のサブデータとから生成された過去のマージ結果のサブデータを検索し、
検索された前記過去のマージ結果のサブデータを用いて、前記第１のブランチと前記第２のブランチとをマージしたときの前記新たなマージ結果のデータを生成する、
請求項１または２記載のプログラム。
【請求項４】
前記編集は、一のブランチの中でノードの順序を入れ替えることを含む、
請求項１乃至３の何れか一項に記載のプログラム。
【請求項５】
コンピュータが実行するバージョン管理方法であって、
それぞれが複数のバージョンのデータの何れかを参照しており自ノードが有する情報に応じた識別子が付与される複数のノードを含む、バージョン間の関係を示すバージョン管理グラフに対して、既存のノードが有する情報を編集することを許容し、
前記バージョン管理グラフに含まれる第１のブランチと第２のブランチとをマージするとき、過去に行われたマージについて２以上のバージョンのデータとマージ結果のデータとの対応関係を示す履歴情報に基づいて、前記第１のブランチに含まれるノードが参照する第１のバージョンのデータと前記第２のブランチに含まれるノードが参照する第２のバージョンのデータとから生成された過去のマージ結果のデータを検索し、
検索された前記過去のマージ結果のデータを用いて、前記第１のブランチと前記第２のブランチとをマージしたときの新たなマージ結果のデータを生成する、
バージョン管理方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明はプログラムおよびバージョン管理方法に関する。
【背景技術】
【０００２】
現在、ソフトウェア開発などのプロジェクトにおいては、ソースコードや設計仕様書などの成果物のバージョンを管理するためにバージョン管理システムが利用されることがある。バージョン管理システムは、複数のバージョンのデータを、リポジトリと呼ばれるデータベースに格納して管理する。バージョン管理システムを利用することで、データの更新の経緯を確認することが容易となり、また、最近行った更新を取り消してデータの状態を過去のバージョンに戻すことも可能となる。バージョン管理システムの例としては、Ｇｉｔ，Ｓｕｂｖｅｒｓｉｏｎ，Ｍｅｒｃｕｒｉａｌなどが挙げられる。
【０００３】
バージョン管理システムを利用すると、複数のバージョン系列についての作業が並行して進行するプロジェクトを管理することも容易となる。例えば、あるソフトウェアに対して、既存の機能を効率的に実行できるように修正する作業と、新たな機能を追加する作業とを並行して行うことがある。この場合、バージョン管理システムは、２つのバージョン系列（例えば、バージョン１．ｘ系とバージョン２．ｘ系）のデータを区別してリポジトリに格納する。各バージョン系列は「ブランチ」と呼ばれることがある。
【０００４】
複数のブランチは後でマージされることがある。例えば、既存の機能を効率化したソースコードと新たな機能を追加したソースコードとをマージして、両方のブランチの作業を反映した最新状態のソフトウェアをテストしたいことがある。この場合、例えば、バージョン管理システムは、ブランチが分岐した時点の過去のソースコードを基準として、マージする一方のソースコードの修正内容と他方のソースコードの修正内容とを特定する。そして、バージョン管理システムは、修正内容の衝突がないことを確認して、両方のブランチの修正内容が反映されたソースコードをマージ結果として生成する。
【０００５】
ところで、バージョン管理システムの中には、バージョン間の関係や更新日時やデータ作成者などの書誌情報と、実体データとを分離して管理するものがある。例えば、Ｇｉｔでは、書誌情報を含む「コミット」、ファイルや他のディレクトリの入れ物としてのディレクトリに相当する「ツリー」、ファイル内容を含む「ブロブ」という３種類のオブジェクトがリポジトリに格納される。各オブジェクトには、リポジトリ内で一意に識別できるように、そのオブジェクトが有する情報から算出される識別子が付与される。
【０００６】
このように、書誌情報と実体データとを分離して管理することで、同一内容のデータが重複してリポジトリに格納されるのを抑制できる。例えば、あるバージョンにおける一のファイルと別のバージョンにおける一のファイルとが、同一内容であるとする。この場合、Ｇｉｔではファイルに相当するブロブの識別子が同じになるため、リポジトリには１つのブロブが格納されて２つのバージョンからそのブロブが参照される。
【０００７】
また、書誌情報と実体データとを分離して管理することで、バージョン間の関係などの書誌情報を後から編集することも容易となる。例えば、あるバージョンで機能Ａが修正され、その次のバージョンで更に機能Ｂが修正されたとする。その後、プロジェクト管理の都合上、機能Ａ，Ｂの修正順序が逆になるように修正経緯を変更したいことがある。そこで、例えば、Ｇｉｔではユーザがコミットの順序を入れ替えることができる。このとき、後者のバージョンで機能Ａ，Ｂの両方が修正されていることに変わりはないため、入れ替え後の末尾のコミットが参照するツリーは変化しない。また、例えば、Ｇｉｔではユーザが複数のコミットを統合することもできる。このとき、統合後のコミットが参照するツリーは、統合対象の末尾のコミットが参照していたツリーと一致する。
【０００８】
なお、バージョン管理に関して、ソースプログラムのリリース時における修正内容の取り込みミスおよび取り込み漏れを防止するバージョン管理方法が提案されている。このバージョン管理方法では、複数のソースプログラムの改造が並行して行われるとき、先に完了した改造についてバージョンや修正情報をバージョン管理テーブル記録しておく。そして、後に改造が完了したソースプログラムをリリースするとき、バージョン管理テーブルに記録された修正情報をマージしてそのソースプログラムに取り込む。
【先行技術文献】
【特許文献】
【０００９】
【特許文献１】特開平９−９７１７１号公報
【発明の概要】
【発明が解決しようとする課題】
【００１０】
プロジェクトの進行形態として、複数のブランチの作業を進めながら、バージョン管理システムを用いてそれら複数のブランチを一時的にマージして最新状態の成果物を確認するという形態が考えられる。例えば、複数のブランチの少なくとも一部でソースコードを修正することと、それら複数のブランチをマージして生成される最新状態のソースコードをテストすることとを、繰り返しながらソフトウェア開発を進めることが考えられる。
【００１１】
このとき、複数のブランチをマージする毎にそれらのブランチが分岐した時点を基準にして修正内容を抽出していると、修正量が多くなるにつれてマージ処理の負荷が高くなってしまう。そこで、バージョン管理システムは、過去のマージ結果を記憶しておき、過去のマージ結果とそれ以降の修正内容とから新たなマージ結果を生成するようにすることが考えられる。複数のブランチをマージするにあたりどのような過去のマージ結果を利用することができるかは、リポジトリに格納された書誌情報に基づいて（例えば、Ｇｉｔの場合はコミットの集合が示すコミットグラフを用いて）検索することが可能である。
【００１２】
しかし、前述のように、バージョン管理システムの中には、ユーザが書誌情報を編集できるものがある。マージが行われた後に書誌情報が編集されてしまうと、編集前の書誌情報と編集後の書誌情報との間の同一性が失われるため、再びマージを行うときにその過去のマージ結果を見つけることが容易でなかったという問題がある。例えば、Ｇｉｔではコミットの修正（コミットの入れ替えや統合などコミット間の関係が変化する場合を含む）が行われると、参照するツリーが変化しなくてもそのコミットの識別子が変化する。よって、コミットが修正されてしまうと、どのコミットを対象として過去にマージが行われたかをコミットグラフのみから検索することが難しかった。
【００１３】
そこで、１つの側面では、本発明は、複数のブランチのマージを効率化することができるプログラムおよびバージョン管理方法を提供することを目的とする。
【課題を解決するための手段】
【００１４】
１つの態様では、コンピュータに以下の処理を実行させるプログラムが提供される。コンピュータは、それぞれが複数のバージョンのデータの何れかを参照しており自ノードが有する情報に応じた識別子が付与される複数のノードを含む、バージョン間の関係を示すバージョン管理グラフに対して、既存のノードが有する情報を編集することを許容する。コンピュータは、バージョン管理グラフに含まれる第１のブランチと第２のブランチとをマージするとき、過去に行われたマージについて２以上のバージョンのデータとマージ結果のデータとの対応関係を示す履歴情報に基づいて、第１のブランチに含まれるノードが参照する第１のバージョンのデータと第２のブランチに含まれるノードが参照する第２のバージョンのデータとから生成された過去のマージ結果のデータを検索する。コンピュータは、検索された過去のマージ結果のデータを用いて、第１のブランチと第２のブランチとをマージしたときの新たなマージ結果のデータを生成する。
【００１５】
また、１つの態様では、コンピュータが実行するバージョン管理方法が提供される。
【発明の効果】
【００１６】
１つの側面では、複数のブランチのマージを効率化することができる。
【図面の簡単な説明】
【００１７】
【図１】第１の実施の形態の情報処理装置を示す図である。
【図２】情報処理装置のハードウェア例を示すブロック図である。
【図３】リポジトリに格納されるオブジェクトの構造例を示す図である。
【図４】コミットとツリーとブロブの間の参照関係の例を示す図である。
【図５】ブランチのマージ例を示す図である。
【図６】コミットに対するリベース処理の例を示す図である。
【図７】過去のマージ結果を利用した第１のマージ例を示す図である。
【図８】過去のマージ結果を利用した第２のマージ例を示す図である。
【図９】第２の実施の形態の情報処理装置の機能例を示すブロック図である。
【図１０】マージ履歴テーブルの例を示す図である。
【図１１】第２の実施の形態のマージ処理の手順例を示すフローチャートである。
【図１２】過去のマージ結果を利用した第３のマージ例を示す図である。
【図１３】サブマージ履歴テーブルの例を示す図である。
【図１４】第３の実施の形態のマージ処理の手順例を示すフローチャートである。
【発明を実施するための形態】
【００１８】
以下、本実施の形態を図面を参照して説明する。
［第１の実施の形態］
図１は、第１の実施の形態の情報処理装置を示す図である。
【００１９】
情報処理装置１０は、プロジェクトで作成される成果物のバージョンを管理する。例えば、情報処理装置１０は、ソフトウェア開発プロジェクトで作成されるソースコードやその他の文書（例えば、設計仕様書など）のバージョンを管理する。情報処理装置１０は、例えば、コンピュータを用いて実現できる。情報処理装置１０は、ユーザが操作する端末装置でもよいし、複数の端末装置からアクセスされるサーバ装置でもよい。
【００２０】
情報処理装置１０は、プロセッサ１１およびメモリ１２を有する。プロセッサ１１は、以下に説明するブランチのマージを実行する。プロセッサ１１は、ＣＰＵ（Central Processing Unit）、ＤＳＰ（Digital Signal Processor）、ＡＳＩＣ（Application Specific Integrated Circuit）、ＦＰＧＡ（Field Programmable Gate Array）などを含んでもよい。例えば、プロセッサ１１はメモリ１２に記憶されたプログラムを実行する。また、プロセッサ１１は、複数のプロセッサを包含する「マルチプロセッサ」であってもよい。メモリ１２は、バージョン管理グラフ１３および履歴情報１４を記憶する。メモリ１２は、例えば、ＲＡＭ（Random Access Memory）などの主記憶部である。ただし、ＨＤＤ（Hard Disk Drive）やフラッシュメモリなどの補助記憶部を「メモリ」と呼んでもよい。
【００２１】
バージョン管理グラフ１３は、バージョン間の関係を示すグラフであり、複数のノードを含む。各ノードは、複数のバージョンのデータの何れかへの参照や、他のバージョンに対応する他のノードとの関係（例えば、当該バージョンの元になった親バージョンに対応する親ノードへの参照）などの情報を有する。各ノードには、当該ノードが有する情報のハッシュ値など、当該ノードが有する情報に応じた識別子が付与される。バージョン管理グラフ１３は、並行して作業が進められるブランチ１３ａ，１３ｂを含む。
【００２２】
一例として、バージョン管理グラフ１３はノードＡ，Ｂ，Ｃを含む。ノードＡは、第１のバージョンに対応し、データａを参照する。ノードＢは、第１のバージョンに基づいて作成された第２のバージョンに対応し、データａを修正することで得られたデータｂを参照する。ノードＣは、第１のバージョンに基づいて作成されて第２のバージョンと併存する第３のバージョンに対応し、データａを修正することで得られたデータｃを参照する。ノードＡ，Ｂはブランチ１３ａに属し、ノードＣはブランチ１３ｂに属する。なお、ノードＡ，Ｂ，Ｃが参照するデータａ，ｂ，ｃは、情報処理装置１０に記憶されていてもよいし、情報処理装置１０の外部の記憶装置に記憶されていてもよい。
【００２３】
ここで、プロセッサ１１は、バージョン管理グラフ１３に含まれるブランチ１３ａ，１３ｂをマージする。ブランチ１３ａ，１３ｂのマージは、ユーザからのマージ命令の入力に応じて行われ得る。例えば、プロセッサ１１は、ブランチ１３ａの末尾のノードＢが参照するデータｂと、ブランチ１３ｂの末尾のノードＣが参照するデータｃとから、マージ結果のデータｘを生成する。生成したデータｘは、以下に説明するように後で利用されることがあるため、データａ，ｂ，ｃと同様にリポジトリに保存しておく。また、プロセッサ１１は、マージした２以上のバージョンのデータとマージ結果のデータとの対応関係を履歴情報１４に記録しておく。例えば、プロセッサ１１は、マージしたデータｂ，ｃの識別子とマージ結果であるデータｘの識別子とを対応付けて記録する。
【００２４】
次に、プロセッサ１１は、バージョン管理グラフ１３に対して、既存のノードが有する情報を編集することを許容する。ノードが有する情報の編集には、更新日時やデータ作成者の変更などグラフ構造が変化しない編集が含まれてもよく、ノードの入れ替えや統合などグラフ構造が変化する編集が含まれてもよい。ノードの情報が編集されると、そのノードの識別子は変化する一方、そのノードが参照するデータは変化しない可能性がある。一例として、ブランチ１３ｂに属するノードＣの情報が編集されて、ノードＣがノードＣ＋に変化する。ただし、ノードＣ＋はノードＣと同様にデータｃを参照する。
【００２５】
また、前回ブランチ１３ａ，１３ｂをマージした後に、新たなバージョンに対応するノードがバージョン管理グラフ１３に追加され得る。一例として、ブランチ１３ｂにノードＤが追加される。ノードＤは、第３のバージョンに基づいて作成された第４のバージョンに対応し、データｃを修正することで得られたデータｄを参照する。上記のノードＣの情報が編集された後では、ノードＤはノードＣ＋と関連付けられることになる。例えば、ノードＤはノードＣ＋への参照を含む。ブランチ１３ｂにノードＤが追加されてからノードＣの情報が編集された場合には、ノードＤが有する情報も併せて編集され得る。
【００２６】
そして、プロセッサ１１は、バージョン管理グラフ１３に含まれるブランチ１３ａ，１３ｂを再びマージする。このとき、プロセッサ１１は、履歴情報１４から、ブランチ１３ａに属するノードが参照するデータとブランチ１３ｂに属するノードが参照するデータとから生成された過去のマージ結果のデータを検索する。該当する過去のマージ結果のデータが存在する場合、プロセッサ１１は、その過去のマージ結果のデータを用いて、ブランチ１３ａ，１３ｂについての新たなマージ結果のデータｙを生成する。
【００２７】
例えば、プロセッサ１１は、履歴情報１４から、ブランチ１３ａに属するノードＢが参照するデータｂとブランチ１３ｂに属するノードＣ＋が参照するデータｃとから生成されたデータｘを検索する。そして、プロセッサ１１は、過去のマージ結果のデータｘと前回のマージ後に追加されたノードＤが参照するデータｄとから、新たなマージ結果のデータｙを生成する。なお、履歴情報１４にデータｘが登録されていない場合、プロセッサ１１は、データｂとデータｄからデータｙを生成することになる。過去のマージ結果を利用せずデータｂ，ｄからデータｙを生成する場合と比べて、データｘ，ｄからデータｙを生成する方が、抽出される修正量が少なくなりマージの負荷が軽減される。
【００２８】
第１の実施の形態の情報処理装置１０によれば、バージョン管理グラフ１３に含まれる既存のノードが編集されて当該ノードの識別子が変化しても、履歴情報１４を参照して、過去に何れのデータから何れのマージ結果が生成されたかを特定することができる。よって、複数のブランチをマージするときに、バージョン管理グラフ１３のみから利用可能な過去のマージ結果を探索する場合と比べて、利用可能な過去のマージ結果を発見できる確率が高くなる。このため、修正内容を抽出するための計算量やリポジトリへのアクセス回数を減らすことができ、複数のブランチをマージする負荷が軽減される。
【００２９】
［第２の実施の形態］
第２の実施の形態を説明する。第２の実施の形態の情報処理装置は、ソフトウェア開発プロジェクトで作成されるソースコードのバージョンを管理する。第２の実施の形態のバージョン管理システムとしては、例えば、Ｇｉｔを使用することができる。
【００３０】
図２は、情報処理装置のハードウェア例を示すブロック図である。
情報処理装置１００は、ＣＰＵ１０１、ＲＡＭ１０２、ＨＤＤ１０３、画像信号処理部１０４、入力信号処理部１０５、媒体リーダ１０６および通信インタフェース１０７を有する。ＣＰＵ１０１は、第１の実施の形態のプロセッサ１１の一例であり、ＲＡＭ１０２（または、ＨＤＤ１０３）は、第１の実施の形態のメモリ１２の一例である。
【００３１】
ＣＰＵ１０１は、プログラムの命令を実行する演算回路を含むプロセッサである。ＣＰＵ１０１は、ＨＤＤ１０３に記憶されているプログラムやデータの少なくとも一部をＲＡＭ１０２にロードし、プログラムを実行する。なお、ＣＰＵ１０１は複数のプロセッサコアを備えてもよく、情報処理装置１００は複数のプロセッサを備えてもよく、以下で説明する処理を複数のプロセッサまたはプロセッサコアを用いて並列実行してもよい。また、複数のプロセッサの集合（マルチプロセッサ）を「プロセッサ」と呼んでもよい。
【００３２】
ＲＡＭ１０２は、ＣＰＵ１０１が実行するプログラムやＣＰＵ１０１が演算に用いるデータを一時的に記憶する揮発性メモリである。なお、情報処理装置１００は、ＲＡＭ以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
【００３３】
ＨＤＤ１０３は、ＯＳ（Operating System）やアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。なお、情報処理装置１００は、フラッシュメモリやＳＳＤ（Solid State Drive）などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
【００３４】
画像信号処理部１０４は、ＣＰＵ１０１からの命令に従って、情報処理装置１００に接続されたディスプレイ２１に画像を出力する。ディスプレイ２１としては、ＣＲＴ（Cathode Ray Tube）ディスプレイ、液晶ディスプレイ（ＬＣＤ：Liquid Crystal Display）、プラズマディスプレイ（ＰＤＰ：Plasma Display Panel）、有機ＥＬ（ＯＥＬＤ：Organic Electro-Luminescence）ディスプレイなどを用いることができる。
【００３５】
入力信号処理部１０５は、情報処理装置１００に接続された入力デバイス２２から入力信号を取得し、ＣＰＵ１０１に出力する。入力デバイス２２としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、情報処理装置１００に、複数の種類の入力デバイスが接続されてもよい。
【００３６】
媒体リーダ１０６は、記録媒体２３に記録されたプログラムやデータを読み取る駆動装置である。記録媒体２３として、例えば、フレキシブルディスク（ＦＤ：Flexible Disk）やＨＤＤなどの磁気ディスク、ＣＤ（Compact Disc）やＤＶＤ（Digital Versatile Disc）などの光ディスク、光磁気ディスク（ＭＯ：Magneto-Optical disk）、半導体メモリなどを使用できる。媒体リーダ１０６は、例えば、記録媒体２３から読み取ったプログラムやデータをＲＡＭ１０２またはＨＤＤ１０３に格納する。
【００３７】
通信インタフェース１０７は、ネットワーク２４を介して他の情報処理装置と通信するインタフェースである。通信インタフェース１０７は、ケーブルで通信装置に接続する有線インタフェースでもよいし、無線で基地局に接続する無線インタフェースでもよい。
【００３８】
ただし、情報処理装置１００は、媒体リーダ１０６を備えていなくてもよい。また、端末装置からネットワーク経由で情報処理装置１００を制御できる場合には、情報処理装置１００は、画像信号処理部１０４や入力信号処理部１０５を備えなくてもよい。
【００３９】
図３は、リポジトリに格納されるオブジェクトの構造例を示す図である。
第２の実施の形態のバージョン管理システムは、１つのプロジェクトに関するファイル群が、１つのディレクトリ（ルートディレクトリ）を頂点とする木構造としてファイルシステム上に格納されていることを前提とする。あるディレクトリの配下には、他のディレクトリ（サブディレクトリ）や、ソースコードを記載したファイルが配置され得る。
【００４０】
バージョン管理システムのリポジトリには、「コミット」と「ツリー」と「ブロブ」の３種類のオブジェクトが格納される。コミットは１つのバージョンに対応し、ツリーはある状態の１つのディレクトリに対応し、ブロブはある状態の１つのファイルに対応する。コミットはバージョンに関する書誌情報を表しており、ツリーおよびブロブの集合はファイルシステム上の実体データを表していると言うことができる。
【００４１】
コミットのヘッダには、文字列“ｃｏｍｍｉｔ”と本文のデータ長が記載される。コミットの本文には、何れか１つのツリーのツリーＩＤが、タグ“ｔｒｅｅ”と共に記載される。コミットが参照するツリーは、そのコミットが示すバージョンのルートディレクトリに対応するルートツリーである。また、コミットの本文には、１または複数の他のコミット（親コミット）のコミットＩＤが、タグ“ｐａｒｅｎｔ”と共に記載されることがある。コミットが参照する親コミットは、そのコミットが示すバージョンの元になった１つ前のバージョンを示す。ただし、コミットの中には、最初のバージョンに対応するコミットなど、“ｐａｒｅｎｔ”の欄を含まないもの（参照する親コミットがないもの）もある。コミットの本文には、作成者名や更新日時などの他の情報も含まれ得る。
【００４２】
ツリーのヘッダには、文字列“ｔｒｅｅ”と本文のデータ長が記載される。ツリーの本文には、１または複数の他のツリー（サブツリー）のツリーＩＤが、データ種別がツリーであることを示すタグ“０４００００”と共に記載されることがある。ツリーが参照するサブツリーは、そのツリーが示すディレクトリの直下に配置されたサブディレクトリを示す。また、ツリーの本文には、１または複数のブロブのブロブＩＤが、データ種別がブロブであることを示すタグ“１００６４４”と共に記載されることがある。ツリーが参照するブロブは、そのツリーが示すディレクトリの直下に配置されたファイルを示す。ただし、ツリーの中には、“０４００００”の欄を含まないもの（参照するサブツリーがないもの）や、“１００６４４”の欄を含まないもの（参照するブロブがないもの）もある。
【００４３】
ブロブのヘッダには、文字列“ｂｌｏｂ”と本文のデータ長が記載される。ブロブの本文には、ソースコードなどのファイルの内容が記載される。
各オブジェクトは、ヘッダと本文が圧縮されて１つの圧縮ファイルとしてリポジトリに格納される。このとき、各オブジェクトには１６０ビット（１６進数表記で４０文字）の数値がオブジェクトＩＤとして付与される。リポジトリは、オブジェクトＩＤと圧縮ファイルとを対応付けて保持し、オブジェクトＩＤから所望の圧縮ファイルを抽出できるようにする。リポジトリとして、例えば、キーバリュー形式のデータベースを使用できる。
【００４４】
オブジェクトＩＤとしては、１６０ビットの数値を出力するハッシュ関数を用いて算出した、オブジェクトのヘッダおよび本文のハッシュ値を用いる。すなわち、コミットのオブジェクトＩＤ（コミットＩＤ）には、コミットのヘッダおよび本文のハッシュ値を用いる。ツリーのオブジェクトＩＤ（ツリーＩＤ）には、ツリーのヘッダおよび本文のハッシュ値を用いる。ブロブのオブジェクトＩＤ（ブロブＩＤ）には、ブロブのヘッダおよび本文のハッシュ値を用いる。なお、異なる内容のオブジェクトから同じハッシュ値が生成される確率（ハッシュ値が衝突する確率）は、十分に小さいものとする。
【００４５】
図４は、コミットとツリーとブロブの間の参照関係の例を示す図である。
コミットＡは、ツリーａを参照する。ツリーａはルートツリーであり、コミットＡが示すバージョンにおけるルートディレクトリに相当する。ツリーａは、サブツリーであるツリーａ１とブロブ１を参照する。ツリーａ１は、ブロブ２を参照する。コミットＡから辿ることができるツリーａ，ａ１およびブロブ１，２の集合は、コミットＡが示すバージョンにおけるファイルシステム上の実体データに相当すると言うことができる。
【００４６】
コミットＢは、コミットＡが示すバージョンのデータを修正することで作成された次のバージョンを示し、親コミットであるコミットＡを参照する。また、コミットＢは、ツリーｂを参照する。ツリーｂはルートツリーであり、コミットＢが示すバージョンにおけるルートディレクトリに相当する。ツリーｂは、サブツリーであるツリーｂ１とブロブ１＋を参照する。ツリーｂ１は、ブロブ２およびブロブ３を参照する。コミットＢから辿ることができるツリーｂ，ｂ１およびブロブ１＋，２，３の集合は、コミットＢが示すバージョンにおけるファイルシステム上の実体データに相当すると言うことができる。
【００４７】
コミットＡのバージョンからコミットＢのバージョンへの実質的な変更点は、ブロブ１の内容が書き換えられてブロブ１＋に更新された点と、ツリーａ１の配下にブロブ３が追加された点である。ブロブ１＋の内容はブロブ１と異なることから、ブロブ１＋にはブロブ１と異なるブロブＩＤが付与され、ブロブ１とは別にブロブ１＋がリポジトリに格納される。一方、ブロブ２は内容が変化しないことからブロブＩＤも変化せず、ブロブ２はリポジトリに重複して格納されずにツリーａ１とツリーｂ１から共通に参照される。
【００４８】
また、ツリーｂ１の内容は、ブロブ３への参照が追加されることでツリーａ１から変化している。よって、ツリーｂ１にはツリーａ１と異なるツリーＩＤが付与され、ツリーａ１とは別にツリーｂ１がリポジトリに格納される。ツリーｂの内容は、参照するツリーｂ１のツリーＩＤがツリーａ１と異なり、参照するブロブ１＋のブロブＩＤがブロブ１と異なるため、ツリーａから変化している。よって、ツリーｂにはツリーａと異なるツリーＩＤが付与され、ツリーａとは別にツリーｂがリポジトリに格納される。
【００４９】
このように、ブロブの追加・更新・削除は、ルートツリーからそのブロブへ至る経路上にある全てのツリーに影響を及ぼす。更新されたブロブおよび影響を受けるツリーは、前のバージョンのブロブおよびツリーとは異なるオブジェクトとしてリポジトリに追加される。一方、更新されなかったブロブおよび影響を受けないツリーについては、重複してリポジトリに追加されることなく、前にリポジトリに格納されたものが参照される。
【００５０】
次に、ブランチおよび複数のブランチのマージについて説明する。
図５は、ブランチのマージ例を示す図である。
ソフトウェア開発プロジェクトでは、複数のバージョン系列についての開発が並行して進められることがある。例えば、セキュリティ対策や実行速度向上などを目的として既存のソースコードをメンテナンスする作業と、新たな機能をソフトウェアに追加するために新たなソースコードを書く作業とを、並行して行うことがある。直列の１つのバージョン系列はブランチと呼ばれることがある。複数のブランチのうち、ソフトウェア開発の中心となるブランチは、マスタブランチ（または、メインラインやトランク）と呼ばれ得る。一方、マスタブランチから分岐して作成されたブランチは、フィーチャブランチと呼ばれ得る。フィーチャブランチは、後でマスタブランチにマージされることが予定される。
【００５１】
前述のコミットの集合からは、コミットをノードとしコミット間の参照関係をエッジとして表したコミットグラフを形成することができる。コミットグラフ上では、直列に繋がったコミット系列が１つのブランチに相当する。コミットグラフ上のフィーチャブランチは、マスタブランチに属する何れかのコミットから分岐する。一例として、コミット列Ａ，Ｂ，Ｃ，Ｄというマスタブランチｍｂと、コミットＡから分岐したコミット列Ｅ，Ｆというフィーチャブランチｆｂ１とが、コミットグラフ上に表される。
【００５２】
ユーザは、ブランチ毎に何れか１つのコミットを作業対象のコミットとして参照する。多くの場合、ユーザはコミット列の末尾のコミット（最後に追加されたコミット）を作業対象とする。例えば、マスタブランチｍｂではコミットＤが現在参照され、フィーチャブランチｆｂ１ではコミットＦが現在参照されている。ブランチに新たなコミットを追加するときは、作業対象のコミットの直後に当該新たなコミットが追加される。
【００５３】
マスタブランチｍｂとフィーチャブランチｆｂ１とは、ユーザから入力されるマージ命令に応じてマージされる。例えば、コミットＡはツリーａを参照し、コミットＤはツリーｄを参照し、コミットＦはツリーｆを参照しているとする。ツリーａからはブロブ１，２を辿ることができ、ツリーｄからはブロブ１＋，２，３を辿ることがで、ツリーｆからはブロブ１−，２＋を辿ることができる。すなわち、フィーチャブランチｆｂ１がマスタブランチｍｂから分岐した時点以降、マスタブランチｍｂではブロブ１がブロブ１＋に更新され、ブロブ３が追加されている。また、フィーチャブランチｆｂ１ではブロブ１がブロブ１−に更新され、ブロブ２がブロブ２＋に更新されている。
【００５４】
マージ結果としてのツリーおよびブロブの集合は、マスタブランチｍｂの修正内容とフィーチャブランチｆｂ１の修正内容とを、衝突が発生しないように結合したものとなる。情報処理装置１００は、まず、マスタブランチｍｂの末尾（または、現在の作業対象）であるコミットＤとフィーチャブランチｆｂ１の末尾（または、現在の作業対象）であるコミットＦとから共通に辿ることができるコミットを、コミットグラフから検索する。このとき、コミットＤ，Ｆからの距離ができる限り小さい共通のコミットを探す。ここでは、２つのブランチの分岐点であるコミットＡが共通のコミットとして検索される。
【００５５】
次に、情報処理装置１００は、コミットＤが参照するツリーｄとコミットＡが参照するツリーａとの間で差分をとることで、マスタブランチｍｂの修正内容を抽出する。ここでは、ブロブ１からブロブ１＋への更新とブロブ３の追加とが抽出される。また、情報処理装置１００は、コミットＦが参照するツリーｆとコミットＡが参照するツリーａとの間で差分をとることで、フィーチャブランチｆｂ１の修正内容を抽出する。ここでは、ブロブ１からブロブ１＋への更新とブロブ２からブロブ２＋への更新とが抽出される。
【００５６】
そして、情報処理装置１００は、マージするブランチ間で衝突が発生していない修正内容をマージ結果に採用する。ここでは、情報処理装置１００は、ブロブ３の追加とブロブ２からブロブ２＋への更新とを自動的に採用する。一方、情報処理装置１００は、２以上のブランチで異なる修正が行われたブロブについては、何れの修正を採用するかユーザに確認する。ここでは、情報処理装置１００は、ブロブ１からブロブ１＋への更新とブロブ１−への更新のうち、ユーザからの指示に応じてブロブ１＋への更新を採用する。情報処理装置１００は、採用した修正内容をツリーａに適用し、マージ結果としてツリーｙを生成する。ただし、ブロブ１＋への更新とブロブ１−への更新とが、ファイル内の異なる箇所を更新するものである場合、両者の修正内容をマージするようにしてもよい。
【００５７】
コミットグラフには、生成されたツリーｙをルートツリーとして参照し、コミットＤ，Ｆを親コミットとして参照するコミットＹを、ユーザから見えるように追加することもできる。ただし、第２の実施の形態では、ソースコードのマージとテストとを繰り返す作業形態を想定し、マージを行う毎にユーザから見えるコミットを追加することは行わない。その代わり、情報処理装置１００は、マージ結果に対応するコミットＹおよびツリーｙを、ユーザから見えないコミットおよびツリーとしてリポジトリに保存しておく。ユーザから見えないコミットおよびツリーは、次にマージを行うときに内部的に利用される。
【００５８】
図６は、コミットに対するリベース処理の例を示す図である。
情報処理装置１００は、コミットをリポジトリに追加した後に、ユーザから入力された命令に応じてそのコミットを編集することがある。コミットの編集の例として、同じブランチに属する２以上のコミットの入れ替えや統合などが挙げられる。コミットの入れ替えは、プロジェクト管理の都合上、あるバージョンの修正とその次のバージョンの修正とを、実際に行われた順序とは逆順で行われたものとして取り扱いたいときに行われ得る。コミットの統合は、プロジェクト管理の都合上、あるバージョンの小さな修正とその次のバージョンの小さな修正とを、同時に行われたものとして管理したいときに行われ得る。
【００５９】
ここでは、フィーチャブランチｆｂ１に属するコミットＥ，Ｆを入れ替える例を説明する。コミットの入れ替えは「リベース」と呼ばれることがある。コミットＥはツリーｅを参照しているとする。ツリーｅからはブロブ１−，２を辿ることができる。前述のように、コミットＦはツリーｆを参照している。すなわち、フィーチャブランチｆｂでは、まずブロブ１がブロブ１−に更新され、その後に更にブロブ２がブロブ２＋に更新されている。コミットＥ，Ｆを入れ替えることは、まずブロブ２がブロブ２＋に更新され、その後に更にブロブ１がブロブ１−に更新されたものと取り扱うことを意味する。
【００６０】
コミットＥ，Ｆを入れ替えるリベースが行われると、リポジトリには、コミットＡを親コミットとして参照するコミットＦ＋とコミットＦを親コミットとして参照するコミットＥ＋とが追加される。コミットＦ＋はリベース前のコミットＦに対応し、コミットＥ＋はリベース前のコミットＥに対応する。また、リポジトリには、ルートツリーとしてツリーｆ＋が追加される。ツリーｆ＋からはブロブ１，２＋を辿ることができる。
【００６１】
コミットＦ＋はツリーｆ＋を参照する。これは、先にブロブ２からブロブ２＋への更新が行われたことを意味する。コミットＥ＋はツリーｆを参照する。これは、ブロブ２からブロブ２＋への更新に続いて、更にブロブ１からブロブ１−への更新が行われたことを意味する。このとき、コミットＦ＋，Ｅ＋のコミットＩＤは、コミット間の参照関係が変化したためコミットＥ，ＦのコミットＩＤと異なる。また、コミットＦ＋が参照するツリーｆ＋のツリーＩＤは、先に更新されたブロブが入れ替わったためツリーｅ，ｆと異なる。一方、リベース後の末尾のコミットＥ＋が参照するツリーｆは、リベース前の末尾のコミットＦが参照していたものと同じである。コミットの順序を入れ替えるだけでは、累積された最終的な修正内容は入れ替え前と変わらないためである。
【００６２】
なお、リベース後のコミットＦ＋，Ｅ＋がリポジトリに追加されても、リベース前のコミットＥ，Ｆはすぐにはリポジトリから削除されない。不要になったコミットＥ，Ｆは、定期的なガーベッジコレクションによって後でリポジトリから削除される。ガーベッジコレクションでは、情報処理装置１００は、オブジェクト間の参照関係に基づいて、他のオブジェクトから参照されていない孤立したオブジェクトを検索する。
【００６３】
例えば、リベース後のコミットＥ＋は作業対象としてユーザから参照され、リベース前のコミットＦはユーザから参照されなくなると考えられる。そのため、ガーベッジコレクションでは、コミットＥ＋は削除されず、コミットＦ＋はコミットＥ＋から参照されているため削除されず、コミットＡはコミットＦ＋から参照されているため削除されない。一方、コミットＦは孤立オブジェクトとして削除され、コミットＦが削除されることで孤立オブジェクトになるコミットＥは削除される。また、ツリーｆはコミットＥ＋から参照されているため削除されず、ツリーｆ＋はコミットＦ＋から参照されているため削除されない。一方、コミットＥが削除されることでツリーｅは削除される。
【００６４】
ガーベッジコレクションの周期は、ユーザが情報処理装置１００に設定しておくことができる。周期は、リポジトリの空き容量と情報処理装置１００の負荷とのバランスを考慮して決定することができる。例えば、ガーベッジコレクションの周期を２週間とする。
【００６５】
次に、過去のマージ結果を利用したブランチのマージについて説明する。
図７は、過去のマージ結果を利用した第１のマージ例を示す図である。
一例として、次のような場合を考える。マスタブランチｍｂの末尾がコミットＤでありフィーチャブランチｆｂ１の末尾がコミットＦであるときに、マスタブランチｍｂとフィーチャブランチｆｂ１とがマージされる。そして、マージ結果に対応するコミットＹおよびツリーｙが、ユーザから見えないようにリポジトリに格納される。その後、フィーチャブランチｆｂ１の末尾に、ツリーｇを参照するコミットＧ０が追加される。
【００６６】
マスタブランチｍｂとフィーチャブランチｆｂ１とを再度マージする場合、情報処理装置１００は、マスタブランチｍｂに属する何れかのコミットとフィーチャブランチｆｂ１に属する何れかのコミットとの間で過去にマージが行われたか判定する。過去のマージの判定は、ユーザから見えないコミットも含むコミットグラフに基づいて行われる。ここでは、コミットＤとコミットＦからマージ結果としてコミットＹが生成されていることが検出される。すると、情報処理装置１００は、コミットＤとコミットＧ０に基づくマージに代えて、過去のマージ結果としてのコミットＹと過去のマージ以降にフィーチャブランチｆｂ１に追加されたコミットＧ０とに基づいてマージを行うことを決定する。
【００６７】
コミットＹとコミットＧ０に基づいてマージする場合、コミットＹとコミットＧ０から辿ることができる最も近い共通のコミットは、コミットＡではなくコミットＦになる。そのため、情報処理装置１００は、ツリーｆからツリーｙへの修正内容とツリーｆからツリーｇへの修正内容を抽出し、衝突が発生しないように修正内容をツリーｆに適用すればよい。これにより、最も近い共通のコミットがコミットＡである場合よりも、抽出される修正量が少なくなりマージを効率的に実行することができる。
【００６８】
その後、情報処理装置１００は、新たなマージ結果としてのコミットＺ０とツリーｚを、ユーザから見えないようにリポジトリに追加する。コミットＺ０は、ルートツリーとしてツリーｚを参照し、親コミットとしてコミットＹ，Ｇ０を参照する。なお、生成されるツリーｚは、過去のマージ結果を利用しない場合に生成されるものと同じである。
【００６９】
図８は、過去のマージ結果を利用した第２のマージ例を示す図である。
一例として、次のような場合を考える。マスタブランチｍｂの末尾がコミットＤでありフィーチャブランチｆｂ１の末尾がコミットＦであるときに、マスタブランチｍｂとフィーチャブランチｆｂ１とがマージされる。そして、コミットＹおよびツリーｙが、ユーザから見えないようにリポジトリに格納される。次に、リベースによってフィーチャブランチｆｂ１のコミット列Ｅ，Ｆがコミット列Ｆ＋，Ｅ＋に編集される。その後、フィーチャブランチｆｂ１の末尾に、ツリーｇを参照するコミットＧが追加される。
【００７０】
このとき、リベース後のコミットＥ＋が参照するツリーｆは、リベース前のコミットＦが参照していたものと同じである。よって、マスタブランチｍｂとフィーチャブランチｆｂ１とを再度マージする場合、情報処理装置１００は、図７の場合と同様に過去のマージ結果であるツリーｙを利用できることが好ましい。しかし、コミットグラフ上ではコミットＦとコミットＥ＋の間に同一性がない。単純にコミットグラフを探索するのみでは、マスタブランチｍｂに属する何れかのコミットとフィーチャブランチｆｂ１に属する何れかのコミットとの間でリベース前に行われた過去のマージを検出できない。
【００７１】
そこで、情報処理装置１００は、マージ結果のコミットとは別にツリーレベルのマージ履歴をリポジトリに格納しておく。ここでは、リベース前のマージの際に、コミットＤが参照するツリーｄとコミットＦが参照するツリーｆとからツリーｙが生成されたことをマージ履歴に記録しておく。これにより、情報処理装置１００は、リベース後のマージの際に、ツリーＤが参照するツリーｄとコミットＥ＋が参照するツリーｆとからツリーｙが過去に生成されたことを、マージ履歴に基づいて検出することができる。
【００７２】
すると、情報処理装置１００は、マージ方法をコミットグラフに基づいて判断できるように、ルートツリーとしてツリーｙを参照し、親コミットとしてコミットＤ，Ｅ＋を参照するコミットＹ＋をリポジトリに追加する。コミットＹ＋は擬似的なコミットであり、ユーザからは見えない。以降、情報処理装置１００は、図７と同様の方法で、マスタブランチｍｂとリベース後のフィーチャブランチｆｂ１とをマージする。
【００７３】
すなわち、ユーザから見えないコミットも含むコミットグラフに基づいて、コミットＤとコミットＥ＋からマージ結果としてコミットＹ＋が生成されていることが検出される。すると、情報処理装置１００は、コミットＤとコミットＧに基づくマージに代えて、コミットＹ＋とコミットＧとに基づいてマージを行うことを決定する。コミットＹ＋とコミットＧから辿ることができる最も近い共通のコミットは、コミットＥ＋になる。そのため、情報処理装置１００は、ツリーｆからツリーｙへの修正内容とツリーｆからツリーｇへの修正内容を抽出し、衝突が発生しないように修正内容をツリーｆに適用する。
【００７４】
その後、情報処理装置１００は、新たなマージ結果としてのコミットＺとツリーｚを、ユーザから見えないようにリポジトリに追加する。コミットＺは、ルートツリーとしてツリーｚを参照し、親コミットとしてコミットＹ＋，Ｇを参照する。また、情報処理装置１００は、ツリーｄ，ｇからツリーｚが生成されたことをマージ履歴に記録する。
【００７５】
次に、情報処理装置１００の機能およびマージ処理の手順について説明する。
図９は、第２の実施の形態の情報処理装置の機能例を示すブロック図である。
情報処理装置１００は、リポジトリ１１０、コミット追加部１２１、コミット編集部１２２、マージ部１２３およびガーベッジコレクタ１２４を有する。コミット追加部１２１、コミット編集部１２２、マージ部１２３およびガーベッジコレクタ１２４は、例えば、ＣＰＵ１０１に実行させるソフトウェアのモジュールとして実現される。
【００７６】
リポジトリ１１０は、バージョン管理に関するデータを記憶するデータベースである。リポジトリ１１０としては、例えば、データをキーとバリューの組として管理するキーバリュー形式のデータベース（キーバリューストア）を用いることができる。リポジトリ１１０は、公開オブジェクト記憶部１１１、内部オブジェクト記憶部１１２およびマージ履歴記憶部１１３を有する。これら３つの記憶部は、例えば、ＲＡＭ１０２またはＨＤＤ１０３に確保した記憶領域として実現することができる。
【００７７】
公開オブジェクト記憶部１１１は、ユーザから見ることができるオブジェクトを、オブジェクトＩＤと対応付けて記憶する。内部オブジェクト記憶部１１２は、ユーザから見ることができない内部処理のためのオブジェクトを、オブジェクトＩＤと対応付けて記憶する。リポジトリ１１０としてキーバリューストアを用いた場合、オブジェクトＩＤがキーに相当し、オブジェクトがバリューに相当する。前述のように、記憶されるオブジェクトにはコミットとツリーとブロブが含まれる。各オブジェクトは、ヘッダと本文が圧縮されて１つのファイルとして記憶される。マージ履歴記憶部１１３は、マージ元のツリーとマージ結果のツリーとの対応関係を示すツリーレベルのマージ履歴を記憶する。
【００７８】
コミット追加部１２１は、ユーザからコミット命令を受け付ける。すると、コミット追加部１２１は、バージョン管理を行うファイルシステム上のファイル群から、ディレクトリ構造を維持するようにツリーおよびブロブの集合を生成する。そして、コミット追加部１２１は、生成した各ツリーおよび各ブロブのオブジェクトＩＤを算出し、オブジェクトＩＤと対応付けてツリーおよびブロブを公開オブジェクト記憶部１１１に格納する。ただし、既に存在するものと同じツリーおよびブロブは重複して格納されない。
【００７９】
また、コミット追加部１２１は、生成したツリー群のうちルートツリーを参照するコミットを生成し、生成したコミットのオブジェクトＩＤを算出し、オブジェクトＩＤと対応付けてコミットを公開オブジェクト記憶部１１１に格納する。ユーザが作業中のブランチに少なくとも１つのコミットが存在する場合、今回追加するコミットは、当該ブランチにおいて現在作業対象となっているコミットを親コミットとして参照する。
【００８０】
コミット編集部１２２は、ユーザからリベース命令など、既存のコミットを編集する命令を受け付ける。すると、コミット編集部１２２は、公開オブジェクト記憶部１１１に記憶されたコミットを編集し、編集したコミットのオブジェクトＩＤを算出する。そして、コミット編集部１２２は、編集前のコミットとは別に編集したコミットを、オブジェクトＩＤと対応付けて公開オブジェクト記憶部１１１に格納する。また、コミットの順序を入れ替える場合などコミットの編集がツリーに影響する場合、コミット編集部１２２は、影響内容を判定してツリーを生成し、公開オブジェクト記憶部１１１に格納する。
【００８１】
マージ部１２３は、ユーザからマージ命令を受け付ける。すると、マージ部１２３は、前述のような方法で複数のブランチをマージする。すなわち、マージ部１２３は、マージ履歴記憶部１１３に記憶されたマージ履歴を参照して、利用可能な過去のマージ結果を検索する。利用可能な過去のマージ結果がない場合、マージ部１２３は、公開オブジェクト記憶部１１１に記憶されたツリーやブロブに基づいてマージ結果を生成する。一方、利用可能な過去のマージ結果がある場合、マージ部１２３は、内部オブジェクト記憶部１１２に記憶されたツリーやブロブも利用してマージ結果を生成する。
【００８２】
そして、マージ部１２３は、マージ結果のコミットおよびツリーを内部オブジェクト記憶部１１２に格納する。また、マージ部１２３は、マージ履歴記憶部１１３に記憶されたマージ履歴に、マージ元ツリーとマージ結果のツリーとの対応関係を記録する。
【００８３】
ガーベッジコレクタ１２４は、ユーザによって設定された周期でガーベッジコレクションを行う。ガーベッジコレクタ１２４は、公開オブジェクト記憶部１１１および内部オブジェクト記憶部１１２に記憶されたオブジェクトの間の参照関係を辿り、これらオブジェクトのうち他のオブジェクトから参照されていない孤立したオブジェクト（不要なオブジェクト）を検出する。そして、ガーベッジコレクタ１２４は、公開オブジェクト記憶部１１１および内部オブジェクト記憶部１１２から、孤立したオブジェクトを削除する。
【００８４】
図１０は、マージ履歴テーブルの例を示す図である。
マージ履歴テーブル１１４は、マージ履歴を登録するテーブルであり、リポジトリ１１０のマージ履歴記憶部１１３に記憶される。マージ履歴テーブル１１４は、親ツリーおよびマージ結果の項目を含む。親ツリーの項目には、マージされた２以上のルートツリーのツリーＩＤが列挙される。マージ結果の項目には、マージ結果として生成されたルートツリーのツリーＩＤが記載される。例えば、マージ履歴テーブル１１４には、親ツリーとしてのツリーｄ，ｆとマージ結果としてのツリーｙとが対応付けられて登録される。
【００８５】
図１１は、第２の実施の形態のマージ処理の手順例を示すフローチャートである。
（Ｓ１０）マージ部１２３は、マージする複数のブランチそれぞれについて、末尾のコミット（または、作業対象のコミット）から共通のコミットに向かって、コミット列を辿る。そして、マージ部１２３は、ブランチ毎に、コミットが参照するルートツリーのツリーＩＤをコミットの順序に従って列挙したツリーＩＤの列を生成する。
【００８６】
例えば、図８の例の場合、マージ部１２３は、マスタブランチｍｂについて、コミット列Ｄ，Ｃ，Ｂ，Ａに対応するツリー列ｄ，ｃ，ｂ，ａを示すツリーＩＤの列を生成する。また、マージ部１２３は、フィーチャブランチｆｂ１について、コミット列Ｇ，Ｅ＋，Ｆ＋，Ａに対応するツリー列ｇ，ｆ，ｆ＋，ａを示すツリーＩＤの列を生成する。
【００８７】
（Ｓ１１）マージ部１２３は、ステップＳ１０で生成した複数のツリーＩＤの列それぞれから１つずつツリーＩＤを選択して得られるツリーＩＤの組の中から、マージ履歴テーブル１１４の親ツリーの項目に登録されているツリーＩＤの組を検索する。このとき、ツリーＩＤの列の前方から優先的に（すなわち、新しいバージョンのツリーのツリーＩＤから優先的に）マージ履歴テーブル１１４の親ツリーの項目と比較していく。
【００８８】
（Ｓ１２）マージ部１２３は、マージ履歴テーブル１１４の親ツリーの項目に登録されているツリーＩＤの組が検出されたか判断する。例えば、図８の例の場合、ツリー列ｄ，ｃ，ｂ，ａとツリー列ｇ，ｆ，ｆ＋，ａから、マージ履歴テーブル１１４の親ツリーの項目に登録されたツリー組＜ｄ，ｆ＞が検出される。検出された場合は処理をステップＳ１３に進め、検出されなかった場合は処理をステップＳ１６に進める。
【００８９】
（Ｓ１３）マージ部１２３は、検出されたツリーＩＤの組に対応するマージ結果のツリーＩＤをマージ履歴テーブル１１４から取得する。そして、マージ部１２３は、取得したツリーＩＤをもつツリーが、内部オブジェクト記憶部１１２に存在するか判断する。当該ツリーが存在しない場合としては、ガーベッジコレクションによって当該ツリーが内部オブジェクト記憶部１１２から削除された場合が考えられる。存在する場合、処理をステップＳ１４に進める。存在しない場合、処理をステップＳ１１に進め、ツリーＩＤの列の後方に向かって条件を満たすツリーＩＤの組を検索していく。
【００９０】
（Ｓ１４）マージ部１２３は、ステップＳ１１で検出されたツリーＩＤの組に対応するコミットの組を、複数のブランチのコミット列の中から特定する。そして、マージ部１２３は、特定したコミットの組を親コミットとして参照し、ステップＳ１３で確認したマージ結果のツリーをルートツリーとして参照する擬似的なコミットを生成する。マージ部１２３は、生成した擬似的なコミットを内部オブジェクト記憶部１１２に格納する。ただし、マージ結果のコミットが既に存在する場合は重複して格納しなくてよい。
【００９１】
（Ｓ１５）マージ部１２３は、前述のような方法で、過去のマージ結果のコミットを考慮してマージ方法を決定する。このとき、マージ部１２３は、公開オブジェクト記憶部１１１に記憶されたユーザから見えるコミットと、内部オブジェクト記憶部１１２に記憶されたユーザから見えないコミットの両方を含むコミットグラフを使用する。図８の例の場合、マージ部１２３は、コミットＤとコミットＧの間のマージに代えて、コミットＹ＋とコミットＧの間でマージを行うと決定する。これにより、過去のマージ結果のツリーｙを利用して、マスタブランチｍｂとリベース後のフィーチャブランチｆｂ１とがマージされることになる。その後、処理をステップＳ１７に進める。
【００９２】
（Ｓ１６）マージ部１２３は、過去のマージ結果のコミットを考慮せずにマージ方法を決定する。このとき、マージ部１２３は、内部オブジェクト記憶部１１２に記憶されたユーザから見えないコミットを含まないコミットグラフを使用してもよい。
【００９３】
（Ｓ１７）マージ部１２３は、ステップＳ１５またはステップＳ１６で決定したマージ方法に従ってマージ結果のツリーを生成し、生成したツリーを内部オブジェクト記憶部１１２に格納する。また、マージ部１２３は、マージ結果のツリーを参照するマージ結果のコミットを生成し、生成したコミットを内部オブジェクト記憶部１１２に格納する。このコミットは、マージ対象とした２以上のコミットを親コミットとして参照する。図８の例では、コミットＤ，Ｇの間のマージに代えてコミットＹ＋，Ｇの間のマージが行われたため、マージ結果のコミットＺはコミットＹ＋，Ｇを参照している。
【００９４】
（Ｓ１８）マージ部１２３は、マージする複数のブランチそれぞれについて、ユーザから見える末尾のコミット（または、作業対象のコミット）が参照するツリーを特定する。そして、マージ部１２３は、特定したツリーの組（親ツリー）のツリーＩＤとマージ結果のツリーのツリーＩＤとを対応付けて、マージ履歴テーブル１１４に登録する。図８の例の場合、ツリーｄ，ｇが親ツリーになりツリーｚがマージ結果のツリーになる。
【００９５】
第２の実施の形態の情報処理装置１００によれば、過去のマージ結果のツリーを利用して複数のブランチをマージすることができる。よって、ブランチが分岐した時点を基準にして修正内容を抽出する場合よりも、計算量やリポジトリへのアクセス回数を減らすことができ、複数のブランチをマージする負荷が軽減される。
【００９６】
また、コミットグラフに過去のマージ結果のコミットを追加することで、複数のブランチそれぞれの末尾のコミット（または、作業対象のコミット）から辿れる共通のコミットを容易に探索でき、過去のマージ結果を利用したマージ方法を効率的に判定することができる。更に、ツリーレベルのマージ履歴を参照することで、リベースなどコミットの編集が行われて編集の前後でコミットの同一性がなくなっても、実質的に利用することが可能な過去のマージ結果のツリーを検出してコミットグラフに反映させることができる。よって、過去のマージ結果を利用できる確率が向上し、マージ処理を効率化できる。
【００９７】
［第３の実施の形態］
第３の実施の形態を説明する。前述の第２の実施の形態との違いを中心に説明し、第２の実施の形態と同様の事項については説明を省略する。第３の実施の形態の情報処理装置は、ルートツリーレベルで過去のマージ結果を利用することができないときであっても、サブツリーレベルで過去のマージ結果を利用できるようにする。第３の実施の形態の情報処理装置は、図２，９と同様のブロック構成として実現することができる。以下では、図２，９で用いたものと同じ符号を用いて第３の実施の形態を説明する。
【００９８】
図１２は、過去のマージ結果を利用した第３のマージ例を示す図である。
一例として、次のような場合を考える。コミットグラフ上には、マスタブランチｍｂおよびフィーチャブランチｆｂ１，ｆｂ２が表されている。マスタブランチｍｂはコミット列Ａ，Ｂ，Ｃ，Ｄを含む。フィーチャブランチｆｂ１，ｆｂ２は、マスタブランチｍｂのコミットＡからそれぞれ分岐したブランチである。フィーチャブランチｆｂ１はコミット列Ｅ，Ｆを含み、フィーチャブランチｆｂ２はコミット列Ｈ，Ｉを含む。
【００９９】
まず、マスタブランチｍｂとフィーチャブランチｆｂ１とがマージされ、マージ結果のコミットＹおよびツリーｙがユーザから見えないようにリポジトリに格納される。このとき、マスタブランチｍｂのコミットＤは、ルートツリーとして図５に示したツリーｄを参照し、フィーチャブランチｆｂ１のコミットＦは、ルートツリーとして図５に示したツリーｆを参照している。ツリーｄ，ｆをマージしてツリーｙを生成するにあたり、情報処理装置１００は、サブツリーであるツリーｄ１，ｆ１をマージしてツリーｙ１を生成する。
【０１００】
その後、マスタブランチｍｂとフィーチャブランチｆｂ２とがマージされ、マージ結果のコミットＸおよびツリーｘがユーザから見えないようにリポジトリに格納される。このとき、フィーチャブランチｆｂ２のコミットＩは、ルートツリーとしてツリーｉを参照している。ツリーｉからは、ブロブ１，２＋，４およびツリーｆ１を辿ることができる。ツリーｘからは、ブロブ１＋，２＋，３，４およびツリーｙ１を辿ることができる。
【０１０１】
ツリーｄ，ｉをマージしてツリーｘを生成するにあたり、情報処理装置１００は、ルートツリーレベルでは先のマージ結果を利用できない。しかし、サブツリーレベルでは、ツリーｄ１，ｆ１をマージしてツリーｙ１を生成するため、先のマージ結果を一部利用できる。そこで、情報処理装置１００は、サブツリーレベルのマージ履歴も保持する。
【０１０２】
図１３は、サブマージ履歴テーブルの例を示す図である。
サブマージ履歴テーブル１１５は、サブツリーレベルのマージ履歴を登録するテーブルであり、リポジトリ１１０のマージ履歴記憶部１１３に記憶される。サブマージ履歴テーブル１１５は、サブツリーおよびマージ結果の項目を含む。サブツリーの項目には、マージされた２以上のサブツリー（コミットが参照するルートツリー以外のツリー）のツリーＩＤが列挙される。マージ結果の項目には、マージ結果としてのサブツリーのツリーＩＤが記載される。例えば、サブマージ履歴テーブル１１５には、マージ元としてのツリーｄ１，ｆ１とマージ結果としてのツリーｙ１とが対応付けられて登録される。
【０１０３】
図１４は、第３の実施の形態のマージ処理の手順例を示すフローチャートである。
ステップＳ１０〜Ｓ１８は、図１１に示した第２の実施の形態のマージ処理と同じである。第３の実施の形態のマージ処理では、情報処理装置１００は、ルートツリーレベルで利用できる過去のマージ結果が存在しないと判断したとき、ステップＳ１２とステップＳ１６の間において以下に説明するステップＳ２０〜Ｓ２３を実行する。
【０１０４】
（Ｓ２０）マージ部１２３は、マージする複数のブランチそれぞれについて、末尾のコミット（または、作業対象のコミット）が参照するルートツリーを特定する。そして、マージ部１２３は、複数のルートツリーそれぞれの配下からサブツリーを１つずつ選択して得られるサブツリーの組を示すツリーＩＤの組の中から、サブマージ履歴テーブル１１５のサブツリーの項目に登録されているツリーＩＤの組を検索する。このとき、木構造のルートに近い方から優先的に（すなわち、ルートからリーフに向かって）検索していく。
【０１０５】
（Ｓ２１）マージ部１２３は、サブマージ履歴テーブル１１５のサブツリーの項目に登録されているツリーＩＤの組が検出されたか判断する。例えば、図１２の例の場合、ツリーｄの配下のサブツリー群とツリーｉの配下のサブツリー群から、サブマージ履歴テーブル１１５に登録されたツリー組＜ｄ１，ｆ１＞が検出される。検出された場合は処理をステップＳ２２に進め、検出されなかった場合は処理をステップＳ１６に進める。
【０１０６】
（Ｓ２２）マージ部１２３は、検出されたツリーＩＤの組に対応するマージ結果のツリーＩＤをサブマージ履歴テーブル１１５から取得する。そして、マージ部１２３は、取得したツリーＩＤをもつサブツリーが、内部オブジェクト記憶部１１２に存在するか判断する。当該サブツリーが存在しない場合としては、ガーベッジコレクションによって当該サブツリーが内部オブジェクト記憶部１１２から削除された場合が考えられる。存在する場合、処理をステップＳ２３に進める。存在しない場合、処理をステップＳ２０に進め、木構造のリーフに向かって条件を満たすサブツリーの組を検索していく。
【０１０７】
（Ｓ２３）マージ部１２３は、ステップＳ２１で検出したツリーＩＤをもつサブツリーについてマージ処理を省略すると決定する。この場合、マージ結果の木構造における１つ上位のツリーが過去のマージ結果のサブツリーを参照するようにすればよい。
【０１０８】
なお、第３の実施の形態では、マージ部１２３は、ステップＳ１８においてマージ履歴テーブル１１４に加えてサブマージ履歴テーブル１１５も更新する。すなわち、マージ部１２３は、マージ元のルートツリーから辿れるサブツリーとマージ結果のルートツリーから辿れるサブツリーとの対応関係を特定し、サブマージ履歴テーブル１１５に登録する。
【０１０９】
第３の実施の形態によれば、第２の実施の形態と同様の効果が得られる。更に、第３の実施の形態によれば、ルートツリーレベルで過去のマージ結果を利用することができないときであっても、サブツリーレベルで過去のマージ結果を利用することができる。よって、複数のブランチのマージを更に効率的に実行することができる。
【０１１０】
なお、前述のように、第１の実施の形態の情報処理は、情報処理装置１０にプログラムを実行させることで実現することができる。また、第２および第３の実施の形態の情報処理は、情報処理装置１００にプログラムを実行させることで実現することができる。
【０１１１】
プログラムは、コンピュータ読み取り可能な記録媒体（例えば、記録媒体２３）に記録しておくことができる。記録媒体としては、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、ＦＤおよびＨＤＤが含まれる。光ディスクには、ＣＤ、ＣＤ−Ｒ（Recordable）／ＲＷ（Rewritable）、ＤＶＤおよびＤＶＤ−Ｒ／ＲＷが含まれる。プログラムは、可搬型の記録媒体に記録されて配布されることがある。その場合、可搬型の記録媒体からＨＤＤなどの他の記録媒体（例えば、ＨＤＤ１０３）にプログラムを複製して（インストールして）実行してもよい。
【符号の説明】
【０１１２】
１０  情報処理装置
１１  プロセッサ
１２  メモリ
１３  バージョン管理グラフ
１３ａ，１３ｂ  ブランチ
１４  履歴情報
【図１】
2014191672.tif 000003
【図２】
2014191672.tif 000004
【図３】
2014191672.tif 000005
【図４】
2014191672.tif 000006
【図５】
2014191672.tif 000007
【図６】
2014191672.tif 000008
【図７】
2014191672.tif 000009
【図８】
2014191672.tif 000010
【図９】
2014191672.tif 000011
【図１０】
2014191672.tif 000012
【図１１】
2014191672.tif 000013
【図１２】
2014191672.tif 000014
【図１３】
2014191672.tif 000015
【図１４】
2014191672.tif 000016