web-dev-qa-db-ja.com

git-filter-branchを使用して複数のディレクトリを抽出します

現在、トップレベルのサブフォルダーに複数のプロジェクトが含まれている大きなリポジトリがあります。たとえば、/a/b/c/dなどです。

次に、そのリポジトリを2つの異なるリポジトリに分割します。1つは/a/bを含み、もう1つは/c/dを含みます。

単一のディレクトリを抽出するのに最適なgit filter-branch --subdirectory-filterを知っていますが、一度に複数のディレクトリを抽出することはできないようです。

git filter-branch --Prune-empty --tree-filterも知っています。これにより、すべてを削除できますが、2つのディレクトリが必要でした。存在する可能性のあるすべてのトップレベルディレクトリを手動で指定する必要があるため、これは完全には正しくないと感じます。

大きなリポジトリから2つのディレクトリを抽出するためのより良い方法はありますか?

PS:もちろん、git filter-branch以外のものを使用した良い解決策は問題ありません。 ;)

23
michas

使用する

git filter-branch -f --Prune-empty --tree-filter 'bash preserve-only.sh a b' -- --all

ここで、preserve-only.shは次のとおりです。

IFS=':'
GLOBIGNORE="$*"
rm -rf *

これにより、すべてのブランチのすべてのコミットからab以外のすべてが削除されます。これは、指定されたディレクトリを正確に抽出することと同じです。

実際の分割を完了するには、rm -rf a bのようなフィルターを使用して、最初の実行で抽出されなかったすべての変更を取得できます。


更新:--index-filterを使用して処理を高速化しようとしているときに、さらに簡単な解決策が見つかりました。

git filter-branch -f --Prune-empty --index-filter \
  'git rm --cached -r -q -- . ; git reset -q $GIT_COMMIT -- a b' -- --all

これはすべてを削除し、その後、指定されたディレクトリを復元します。

46
michas

このためにtree-filterよりも良い方法を私は知りません。したがって、必要なすべての情報がすでにあります。今それをするだけです!

2つのブランチを作成することから始めます。

git branch br1
git branch br2

次に、ブランチごとにチェックアウトしてから、tree-filterを使用してフィルタリングします。

次に、それらをプッシュアウトするか、クローンまたはプルインすることにより、それらを別々のディレクトリに分割できます。

0
JB.

私はこれが好きです

git filter-branch -f --Prune-empty --tree-filter "ls -I a -I b | xargs rm -rf"  -- --all
0
Alex R