7

シナリオは次のとおりです。

14 個の個別の git リポジトリに変換したい大きな CVS リポジトリがあります。プロセスのcvs2git一部は問題なく、大きなリポジトリ repo.git につながります。

14 個の git リポジトリのそれぞれについて、メイン リポジトリのクローンを作成し、次のコマンドを実行します。

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

ただし、このコマンドの前に、git filter-branchあるディレクトリから別のディレクトリにファイルを移動するためにコミットを書き直す必要があるため、いくつかの git リポジトリに対して別のコマンドを実行する必要があります。は--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 時間かかります!) refs を消去し、次を使用します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

gitk で見られる不連続性

それらのいくつかのタグのおかげで、それらのコミットがまだ存在していることは確かです。この場合、適切なコミットのタグを削除せずにそれらのタグを削除することは可能ですか?

タグが理由でない場合、何か考えはありますか?

詳細については、refsディレクトリのコンテンツ (subdirectory-filter によって取得された git リポジトリ内) が空です:

$ 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ブランチとタグがgit リポジトリのファイルにリストされていることがわかりました。

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

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

4

2 に答える 2

2

私はあなたがこれで打たれているに違いない:

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

    • cvs2git は単一のソースからブランチを作成しようとしますが、方法がわからない場合は、複数のソース ブランチから「マージ」を使用してブランチを作成します。異常な状況では、ブランチのマージ ソースの数が任意に大きくなる可能性があります。結果の履歴は、任意のファイルがブランチに追加されるたびに、ソース ブランチ全体が宛先ブランチにマージされたことを意味しますが、これは明らかに正しくありません。(別の方法として、マージを省略すると、一部のコンテンツが 1 つのブランチから別のブランチに移動されたという情報が破棄されます。)

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

  • CVS のブランチ名とタグ名が正当な git 名であるかどうかのチェックはありません。他にも確認すべき git 制約が存在する可能性があります。cvs2git を参照

変換後の新しいディレクトリまたは大きなリポジトリの refs ディレクトリを表示していますか? 大きなリポジトリをフィルタリングして分割する前に、単一の大きなエクスポート リポジトリのタグを削除できます。

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

于 2013-07-28T20:51:16.670 に答える