1. ホーム
  2. git

[解決済み] mercurialやgitからcvsにリビジョン履歴をエクスポートするには?

2022-12-08 02:33:21

質問

私は、cvs を使用するプロジェクトのコードで他の人と一緒に作業するつもりです。私たちは分散型 vcs を使用して作業を行い、終了時または時々、私たちのコードとすべての改訂履歴を cvs にコミットしたいと考えています。私たちは、プロジェクトの cvs リポへの書き込みアクセス権を持っていないので、あまり頻繁にコミットすることができません。改訂履歴を cvs にエクスポートするには、どのようなツールを使用すればよいでしょうか。現在、私たちは git または mercurial を使用することを考えていましたが、それがエクスポートを容易にすることができれば、他の分散型 vcs を使用することができます。

どのように解決するのですか?

幸いなことに、まだ CVS を使わざるを得ない私たちのために、git はあなたがやりたいことを正確に行うためのかなり良いツールを提供しています。 私の提案 (そして私たちが $work で行っていること) を紹介します。

最初のクローンを作成する

使用する git cvsimport を使って、CVS のリビジョン履歴を git リポジトリにクローンします。 私は以下のような起動を使用しています。

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

-A オプションはオプションですが、CVS から取り込んだリビジョン履歴をより git ライクに見せるために役立ちます ( man git-cvsimport をご覧ください)。

CVS リポジトリのサイズと履歴によりますが、この最初のインポートには非常に長い時間がかかるでしょう。 何かが実際に起こっているという安心感を得たいのであれば、上記のコマンドに -v を追加することができます。

このプロセスが完了すると、あなたは master ブランチが作成され、CVS の HEAD が反映されます (ただし git cvsimport はデフォルトで最後の 10 分間のコミットを無視するので、中途半端なコミットを捕捉することはありません)。 その後 git log などを使えば、あたかも最初から git を使っていたかのように、リポジトリの全履歴を調べることができます。

設定の微調整

将来、CVS からの増分インポート (およびエクスポート) をより簡単にするための、いくつかの設定上の微調整があります。 これらは git cvsimport のマニュアルページには書かれていませんので、予告なしに変更される可能性がありますが、参考までに。

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

これらのオプションはすべてコマンドラインで指定できるので、このステップを飛ばしても安全です。

インクリメンタルインポート

後続の git cvsimport は最初の呼び出しよりずっと速いはずです。 しかし、これは cvs rlog を実行します (ファイルだけが Attic にしかファイルがないものでも)、数分かかることがあります。 上記の推奨設定を指定すれば、あとは実行するだけです。

% git cvsimport

デフォルトを指定するようにコンフィグを設定していない場合は、コマンドラインで指定する必要があります。

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

いずれにせよ、注意すべき点は2つ。

  1. git リポジトリのルートディレクトリにいることを確認してください。 それ以外の場所にいる場合は、新しい cvsimport を実行しようとするので、これまた時間がかかります。
  2. 必ず自分の master ブランチにいることを確認し、変更をローカル/トピックブランチにマージ(またはリベース)できるようにします。

ローカルでの変更

実際には、常にブランチ上で変更を行い、マージするのは master にマージすることだけをお勧めします。 あなたはブランチ上で好きなワークフロー (マージ、リベース、スクワッシュなど) を使用できますが、もちろん標準的なリベースのルールが適用されます: 他の誰かがあなたのブランチの変更を基にしていた場合、リベースしないでください。

変更を CVS にエクスポートする

git cvsexportcommit コマンドを使うと、単一のコミットを CVS サーバにエクスポートすることができます。 単一のコミット ID を指定できます (あるいは man git-rev-parse ). そして diff が生成され、CVS チェックアウトに適用され、(オプションで) CVS にコミットされる際には実際の cvs クライアントを使用して CVS にコミットします。 トピックブランチの各マイクロコミットをエクスポートすることもできますが、一般に私は最新の master を実行し、その単一のマージコミットを CVS にエクスポートします。 マージコミットをエクスポートする際には、差分を生成するためにどの親コミットを使うのかを git に伝えなければなりません。 また、マージが fast-forward であった場合はうまくいきません (以下の "HOW MERGE WORKS" のセクションをご覧ください)。 man git-merge のセクションを参照してください)、早送りマージを行うには --no-ff オプションを使用する必要があります。 以下はその例です。

# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD

これらのオプションが何を意味するかは のマニュアルページをご覧ください。 . を設定するオプションがあります。 -w オプションを設定するオプションもあります。

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

何らかの理由でパッチが失敗した場合、私の経験では、(残念ながら) 変更したファイルを手動でコピーして cvs クライアントを使ってコミットした方がよいでしょう。 しかし、このようなことは起こらないはずです。 master が CVS で最新であることを確認してから、トピックブランチをマージしてください。

何らかの理由でコミットが失敗した場合 (ネットワークやパーミッションの問題など)、エラー出力の最後にターミナルに出力されるコマンドを受け取り、それを CVS の作業ディレクトリで実行することができます。 それは通常このようなものです。

% cvs commit -F .msg file1 file2 file3 etc

次に git cvsimport (を実行すると、エクスポートしたコミットのパッチがローカルリポジトリに再インポートされるのを確認できるはずです。 CVS コミットは異なるタイムスタンプを持ち、おそらく異なるコミッター名を持つので、両者は異なるコミット ID を持つことになります (最初の cvsimport で著者ファイルを設定したかどうかによって異なります)。

CVS クローンを作成する

もし、複数の人が cvsimport を行う必要がある場合、cvsimport を行う単一の git リポジトリを用意し、他のリポジトリはすべてクローンとして作成するのが効率的でしょう。 これは完璧に動作し、クローンしたリポジトリは上で説明したように cvsexportcommits を実行することができます。 しかし、1つだけ注意点があります。 CVS のコミットが異なるコミット ID で戻ってくるため (前述)、クローンしたブランチが中央の git リポジトリを追跡しないようにしたいのです。 デフォルトでは、このように git clone がリポジトリの設定を行いますが、これは簡単に修正できます。

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

これらの設定を削除した後は、中央リポジトリから新しいコミットを取り込みたいときに、どこから何を取り込むかを明示的に指定する必要があります。

% git pull origin master


全体として、このワークフローは非常に管理しやすく、git に完全に移行することが現実的でない場合の次善の策であることがわかりました。