[解決済み] mercurialやgitからcvsにリビジョン履歴をエクスポートするには?
質問
私は、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つ。
-
git リポジトリのルートディレクトリにいることを確認してください。 それ以外の場所にいる場合は、新しい
cvsimport
を実行しようとするので、これまた時間がかかります。 -
必ず自分の
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 に完全に移行することが現実的でない場合の次善の策であることがわかりました。
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] リモートのGitブランチをチェックアウトするには?
-
[解決済み] Git リポジトリを以前のコミットに戻すにはどうすればよいですか?
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] Git で、ステージされていない変更を破棄するにはどうしたらいいですか?
-
[解決済み] ファイルをリセットしたり、特定のリビジョンに戻したりするにはどうすればよいですか?
-
[解決済み】"git pull" でローカルファイルを強制的に上書きするには?
-
[解決済み】ローカルのGitブランチの名前を変更するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
gitlab をアップロード ! [リモート拒否] dev -> dev (受信前のフックが拒否されました)
-
gitlabの紹介と使い方
-
git push please tell me who you are or git fatal: empty ident name (for <>) not llowed.
-
git push issues
-
git reports an error fatal: unable to auto-detect email address (got 'Administrator@MS-20180504MMDH.(none)')
-
[解決済み] Gitの本番環境へのプッシュ(FTP)
-
[解決済み] GitHubで、既存のレポを追加するときにすべてのブランチをプッシュするにはどうしたらいいですか?
-
[解決済み] .gitignoreで特定のファイルを除外する
-
[解決済み] Git git reset」後にコミットメッセージを再利用/保持するには?
-
[解決済み] GitHubのウェブサイト上でディレクトリやフォルダの名前を変更するには?