2016-01-02 10 views
7

は、あなたがリポジトリを持っているとしましょう*名前を変更します。モジュールを独立させるためにコードをリファクタリングする。 megaProjectディレクトリのファイルは、自分のディレクトリに移動します。 moveを強調 - これらのファイルの履歴は保持されます。GITスプリットリポジトリディレクトリ保存*動きは/歴史

myCode/megaProject 
myCode/moduleA 
myCode/moduleB 

これらのモジュールを自分のGITリポジトリに移動したいとします。独自のmegaProjectだけでオリジナルを残してください。

myCode/megaProject 
newRepoA/moduleA 
newRepoB/moduleB 

filter-branchコマンドは、これを行うためにdocumentatedされますが、ファイルがターゲットディレクトリの外に移動されたとき、それは歴史に従っていません。そのため、履歴は、ファイルが新しいディレクトリに移動されたときに開始され、古いmegaProjectディレクトリにあった履歴は保存されません。

ターゲットディレクトリに基づいてGIT履歴を分割し、このパス以外の履歴に従う方法 - これらのファイルに関連するコミット履歴のみを残し、それ以外は何も残しませんか?

他の多くの答えは、一般的にレポを分割することに重点を置いていますが、分割したり、移動履歴に従ったりすることは言及していません。

答えて

1

クローンされたリポジトリにgit filter-branch --subdirectory-filterを実行すると、そのサブディレクトリ内のコンテンツに影響しないすべてのコミットが削除されます。コミットには、移動前のファイルに影響するものが含まれます。

代わりに、興味のないすべてのファイルを削除するには--index-filterフラグをスクリプトに使用し、他のコンテンツに影響するコミットを無視するには--prune-emptyフラグを使用する必要があります。

は、この良い例でblog post from Kevin Deldyckeをあります:

git filter-branch --prune-empty --tree-filter 'find ./ -maxdepth 1 -not -path "./e107*" -and -not -path "./wordpress-e107*" -and -not -path "./.git" -and -not -path "./" -print -exec rm -rf "{}" \;' -- --all 

何が最後から変更されている場合、このコマンドは効果的に、それぞれが順番にコミットチェックアウト作業ディレクトリからすべての興味のないファイルを削除してからコミットそれをチェックインします(ヒストリを書き換えます)。 /moduleA/megaProject/moduleAなどのファイルを除くすべてのファイルを削除するには、そのコマンドを微調整する必要があります。保存するファイルは/megaProjectです。

1

私はこれを行う簡単な方法は知らないが、それを行うことができます。

filter-branchの問題は、それはあなたが彼らがディレクトリ間で追跡され、あなたのファイルを削除しませんフィルタを作成することができた場合は、各リビジョン

にカスタムフィルタを適用

で動作することです。もちろん、これは自明ではないリポジトリにとっては自明ではないようです。

開始するには:それは簡単なリポジトリだとしましょう。ファイルの名前を変更したことはありません。また、同じ名前の2つのモジュールにファイルを格納したこともありません。あなたがする必要があるすべてはあなたのモジュールfind megaProject/moduleA -type f -printf "%f\n" > preserve内のファイルの一覧を取得し、それらのファイル名を使用してフィルタを実行し、あなたのディレクトリです:

preserve.sh

cmd="find . -type f ! -name d1" 
while read f; do 
    cmd="$cmd ! -name $f" 
done < /path/to/myCode/preserve 
for i in $($cmd) 
do 
    rm $i 
done 

git filter-branch --prune-empty --tree-filter '/path/to/myCode/preserve.sh' HEAD

もちろん、これを難しくする名前の変更です。 git filter-branchが行う素晴らしいことの1つは、$GIT_COMMITという環境変数です。コミットして、それは簡単な例では、単純なpreserveファイルの代わりに使用することができますが、ONUが上になるだろう、ファイル名の履歴を構築するために

for f in megaProject/moduleA 
do 
git log --pretty=format:'%H' --name-only --follow -- $f | awk '{ if($0 != ""){ printf $0 ":"; next; } print; }' 
done > preserve 

:あなたはその後、空想取得し、のようなものを使用することができますあなたは各コミット時にどのファイルが存在すべきかを把握する必要があります。これは実際にコード化するのは難しいことではありませんが、私はまだそれをやった人は誰も見ていません。

+0

研磨場合はクールに見えますが、ASIS適用された場合には動作しません。 – Vasaka

0

私たちは数十のブランチにまたがって数十のプロジェクトで、それぞれのプロジェクトが1-4の他のプロジェクトに依存していて、合計で56kのコミットを行っていました。 filter-branchは1つのディレクトリを分割するのに24時間かかりました。

私は、libgit2sharpとrawファイルシステムへのアクセスを使用して、プロジェクトごとに任意の数のディレクトリを分割し、新しいreposの各プロジェクトに関連するコミット/ブランチ/タグのみを保存するツールを.NETで作成しました。ソースリポジトリを変更する代わりに、設定されたパス/ refのみを持つN個の他のreposを書き出します。

あなたは、これはあなたのニーズに合った場合、それを変更見て歓迎している、などhttps://github.com/CurseStaff/GitSplit

関連する問題