git filter-branchでリポジトリのディレクトリ構成を変更する

シェアする

  • このエントリーをはてなブックマークに追加

スポンサードリンク

git filter-branchとは

例えば、以下の構成のGitのリポジトリがあったとします。ここで、A1、B1、C1はそれぞれディレクトリです。

Repository --+-- A1 --+-- B1 --+-- C1

この構成を以下に変更したいとします。

Repository --+-- B1 --+-- C1

ただし、条件として、最初からA1存在せずに、最初からB1がリポジトリのプロジェクトルートにあったかのようにしたいです。

バージョン管理システムでは、歴史を保持しているので、過去をなかったことにするのは、基本NGなはずなのですが、Gitには、歴史の書き換えをサポートする強力なコマンド、git filter-branchというコマンドが存在します。

git filter-branchは、歴史を書き換えてくれる、最強のコマンドです。上記のケースの場合、以下のコマンドを実行します。

$ git filter-branch -f --subdirectory-filter A1/B1/ -- --all

このようにすることで、A1に代わってB1が新たなプロジェクトルートになります。

リポジトリのログを見てみても、あたかもA1は最初から存在せずに、B1が最初からプロジェクトルートであったかのように見えます。

当然ですが、これを実行したら、もはや元には戻れません(もう一度、git filter-branchを使えば、元には戻れます)。そのため、最新の注意を行って実行する必要があります。

スポンサードリンク

複数のディレクトリ構成を変更して失敗する

次に以下のケースを考えてみます。

Repository --+-- A1 --+-- B1 --+-- C1
+
+-- A2 --+-- B2 --+-- C2

このディレクトリ構成を以下のように変更してみたいとします。

Repository --+-- A1 --+-- C1
+
+-- A2 --+-- C2

先ほど使った、git filter-branchのオプションであるsubdirectory-filterは、残念ながら、1つのディレクトリしか抽出してくれません

そこで、tree-filterというオプションを使ってみます。

$ git filter-branch --tree-filter 'mv A1/B1/C1 A1' HEAD
Rewrite xxxx(1/206)mv: cannot stat 'A1/B1/C1': No such file or directory
tree filter failed: mv A1/B1/C1 A1

こんなエラーが表示されました。

スポンサードリンク

複数のディレクトリ構成を変更に成功した方法

その後、なかなか解決できません。仕方がないので、Stack Overflowに質問してみました。
Stack OverflowはIT系のエンジニアなら誰でも知っている質問コミュニティサイトです。
2014年12月には日本語版もオープンしていますが、まだまだコミュニティとしては未成熟なので本家に質問してみます。

http://stackoverflow.com/questions/28320492/how-can-i-move-multiple-directories-in-a-git

どうやら意味が通じず「変更したい構成にして、そのままコミットしたらいい」とか返事が返ってきましたり、結局、解決できません。

一日、トライして以下のコマンドでうまくいくことが分かりました。

$ git filter-branch --tree-filter "ls A1/B1 | xargs -i -t mv A1/B1/{} A1 | sh" HEAD

イマイチ、納得できないのと、エレガントではないけれど、これでうまくいったので良しとします。

まとめ git filter-branchによる歴史の書き換え

私はVCS(バージョン管理システム)については、古くはSCCS、VSS、CVS、Subversionと使ってきました。
その中でも、歴史を書き換えるコマンドがあるバージョン管理システムと出会ったのはGitが初めてです。
それぐらい、git filter-branchは衝撃的なコマンドでした。
ただ、使い方によっては、とても危険なので慎重に使わないといけません。
とは言え、過去をなかったことにして、リポジトリの再構成が出来ることは、サーバー管理者にとって、とても便利です。
これで巨大なリポジトリでも手軽に階層構造を操作することができます。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です