2013-07-26 10 views
7

このシナリオは次のとおりです。git filter-branchは切断された履歴につながった:古いコミットを取り除く方法?

私は14の異なるgitリポジトリに変換したい大きなCVSリポジトリを持っています。 プロセスの一部であるcvs2gitは問題なく、大きなリポジトリリポジトリにつながります。 14 Gitのレポのそれぞれについて

、私はメインのレポのクローンを作成し、私は、次のコマンドを実行します。

git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --subdirectory-filter "sub/directory" -- --all 

しかし、このコマンドの前に、私はいくつかのgitリポジトリのために別のgit filter-branchコマンドを実行する必要があるためディレクトリから別のファイルに移動するためにコミットを書き直さなければなりません。 --tree-filterは私が使用するオプションです。ここで実行したコマンドラインの例です。

script_tree_filter="if test -f rep/to/my/file && test -d another/rep ; then echo Moving my file ; mv rep/to/my/file another/rep; fi" 
git filter-branch -d /tmp/rep --tag-name-filter cat --prune-empty --tree-filter '$script_tree_filter' -- --all 

プロセスの終わりに(14500のコミット:!それは約1時間かかります)私はレフリーをきれいにし、git gcを使用します。

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 
git reflog expire --expire=now --all 
git gc --prune=now 

最後に私は1.2Goのサイズのリポジトリを取得します(それはまだ明らかに大きすぎます)。コミットを見ると、古いものがまだたくさんあることがわかります。それらは、--subdirectory-filterコマンドの後にもうここにはいけないファイルとディレクトリに関するものです。 gitk --allに見られるように、コミットの歴史の中で

は、不要なコミットと良いものの間に不連続性があります:

discontinuity seen in gitk

私はそれらのコミットが原因で、まだ存在していることをかなり確信していますタグを付けてください。この場合、良いコミットのタグを削除せずにこれらのタグを削除することは可能ですか?

タグが理由でない場合は、何か考えてください。詳細については、(サブディレクトリフィルタによって得られたgitリポジトリ内)refsディレクトリの内容が空である

$ ls -R refs/ 
refs/: 
heads original tags 

refs/heads: 

refs/original: 
refs 

refs/original/refs: 
heads tags 

refs/original/refs/heads: 

refs/original/refs/tags: 

refs/tags: 

ブランチやタグがファイルに記載されていることを、私を見つけたpacked-refs

d0c675d8f198ce08bb68f368b6ca83b5fea70a2b refs/tags/v03-rev-04 
95c3f91a4e92e9bd11573ff4bb8ed4b61448d8f7 refs/tags/v03-rev-05 

ファイルに817個のタグと219個のブランチがリストされています。

+1

'git gc'はタグrefsを.git/packed-refsにパックするので、空のディレクトリになります。私はなぜタグが古いコミットを指しているのかは分かりませんが、各フィルタブランチopは '--tag-name-filter'を使っています.... – torek

+1

この記事の4つのコマンドに従ってクリーンアップしましたか? ?http://stackoverflow.com/a/7966852/11343 – CharlesB

+0

'reset hard'を除いて、私の質問で述べたように3つのコマンドを実行しました(' rm -rf .git/refs/original/'は私は裸のリポジトリを持っているので同じ方法)。私はgcの '--agentive'オプションを使用しませんでしたが、私は試してみることができません(私は何も変わらないと思います)。 – Frodon

答えて

5

私が使用した方法を変更することで問題を解決することができました。cvs2git:CVSベース全体を変換してからsubdirectory-filterコマンドを使用する代わりに、私はそれぞれのサブモジュールを変換しました。各リポジトリは今完璧な歴史を持ってい

# Module 1 
cvs2git --blobfile=blob_module1 --dump=dump_module1 /path/to/cvs/base/path/to/module1 
# Module 2 
cvs2git --blobfile=blob_module2 --dump=dump_module2 /path/to/cvs/base/path/to/module2 

cvs2git --blobfile=blob --dump=dump /path/to/cvs/base 
# Module 1 
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module1" -- --all 
# Module 2 
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter "path/to/module2" -- --all 

:私の場合、これは、18種類のcvs2gitコマンドを起動するために導きました。

なぜ以前の方法がうまくいかなかったのですか?私の推測では、cvs2gitはすべてのサブモジュールと混同されていた(そのうちのいくつかは、その歴史の間にディレクトリ名が変更されていた)。

@Michael @CharlesBご回答いただきありがとうございます。

+1

あなたのソリューションを共有するための+1、あなたがそれを解決したことを知ってうれしくなりました – CharlesB

+1

@CharlesB:あなたのサポートに感謝します – Frodon

+2

あなたはこれを解決してくれてうれしいです、なぜあなたはCVS自体から大きなレポを作りましたか?ソリューション - 歓声。 +1も – Michael

2

私はあなたがこれを打たされて賭け:CVSとgitのブランチ/タグモデル間の

  • 違い:CVSは、ブランチやタグは、複数のソースからのソースのリビジョンの任意の組み合わせから作成することができます枝。それは、同時にはなかったファイルのリビジョンを単一のブランチ/タグに追加することさえできます。一方、Gitは、歴史のある瞬間に存在していた完全なソースツリーを1つの単位として分岐またはタグ付けすることしかできません。さらに、gitリビジョンの祖先は、そのリビジョンの内容に影響を与えます。この違いは、gitリポジトリ内の任意のCVS履歴を100%忠実に表現することは基本的に不可能であることを意味します。cvs2gitは次の回避策を使用しています:

    • cvs2gitは、単一のソースからブランチを作成しようとしますが、どのようにそれが理解できないならば、それは複数のソースブランチからの「マージ」を使用してブランチを作成します。病理学的状況では、分岐のマージ元数は任意に大きくすることができる。結果の履歴は、ファイルがブランチに追加されるたびに、ソースブランチ全体が宛先ブランチにマージされたことを意味します。

    • cvs2gitは、単一のリビジョンからCVSタグを作成できると判断できない場合は、作成したCVSタグを削除します。 TAG.FIXUPという名前のタグフィックスアップブランチを作成し、このブランチにタグを付けます。 TAG.FIXUPブランチは、タグに含まれるファイルリビジョンを含むすべてのブランチ間のマージとして作成されます。これには、説明されているのと同じトレードオフが含まれています(これは、既存のリビジョンにタグを付けることのみを許可するために必要な回避策です)。枝のための上記。 TAG.FIXUPブランチは変換の終わりにクリアされますが、(gitの高速インポートファイルフォーマットの技術的な制限のために)削除されません。単一のリビジョンからタグを作成できる状況がいくつかありますが、cvs2gitはそれを認識せず余分なタグフィックスアップブランチを作成します。生成されたgitリポジトリ内でcontrib/git-move-refs.pyスクリプトを実行することにより、変換後に余分なタグフィックスアップブランチを削除することは可能です。

  • CVSブランチとタグ名が有効なgit名であるかどうかのチェックはありません。他のgit制約もチェックする必要があります。 see cvs2git

あなたは、変換後に新しいのdirsのか、大きなレポの参照文献ディレクトリを示していますか?大規模レポをフィルタリングして分割する前に、単一の大規模エクスポートレポのタグを削除することができます。

ディレクトリ内のファイルを削除するだけで、大きなリポジトリ内のタグを削除することができます。これは単なるSHAへの参照です。

+0

refsディレクトリは新しいディレクトリの1つです(サブディレクトリフィルタの後)。すべてのタグを削除することはオプションではありません。私が保存しているディレクトリに関係するものを保存したいのです。 – Frodon

+0

私はすべてのタグを削除すると言っていませんでした。重要ではないものを削除するだけです=不要なタグが問題を引き起こしていると言っていました。 – Michael

+0

トリックは、「良い」タグと「悪い」タグを区別する方法がわかりません。私は現在、それらのタグを持つ空のコミットを削除するために調査中です。 – Frodon

関連する問題