最善の修正は、MercurialのGitサブリポジトリサポートにパッチを適用して、常にGitの再帰オプションを使用することだと思います(たとえばgit clone --recursive
、Gitベースのサブリポジトリのクローンを作成するときgit pull --recurse-submodules && git submodule update
、更新されたGitベースのサブリポジトリをプルした後など)。Git開発者は、サポートしたいワークフローの1つが「サブモジュールを表示したくない」であるため、サブモジュールを自動的に初期化しないことを特に選択したことを知っていますが、「常にすべてのサブリポジトリを初期化する」の方が適している可能性があります。デフォルトのMercurialモードの操作(私はMercurialユーザーではないため、デフォルトのMercurialスタイルがどうなるかについてはよくわかりません)。
subrepo/.gitmodules
それが発生するまで、エントリをエントリに変換することで問題を回避できる可能性があり.hgsub
ます。手動で行うのは簡単ですが、重要な場合はおそらく自動化できます(および/またはgit config
からパスとURLを抽出するために使用します)。大幅に変更されるファイルを扱っている場合、これは魅力的ではない可能性があります(変更されるたびに同期することに非常に注意を払う必要があります)。.git/config
.gitmodules
.gitmodules
.hgsub
.gitmodules
私はこれを4つのリポジトリでテストしました。
- gitsub —「リーフ」リポジトリ(Gitサブモジュールなし)
- gitsuper —Gitの「スーパープロジェクト」。サブモジュールとしてのgitsub
gitsub/
です
- hgsuper2 —水銀の「スーパープロジェクト」。サブリポジトリとしてのgitsuper、
gitsuper/
サブリポジトリとしてのgitsubです。
gitsuper/gitsub
- hgsuper2-clone —クローン化されたMercurialの「スーパープロジェクト」。サブリポジトリとしてのgitsuper、
gitsuper/
サブリポジトリとしてのgitsubです。
gitsuper/gitsub
私はこれらを次のように構築してテストしました:
- gitsubを作成します。いくつかのコンテンツを追加してコミットします。
- gitsuperを作成します。
- コンテンツを追加します。
git submodule add url-of-gitsub gitsub && git submodule init
git commit -m 'added gitsub'
- hgsuper2を作成します。
- コンテンツを追加します。
git clone --recursive url-of-gitsuper gitsuper
echo 'gitsuper = [git]url-of-gitsuper' >> .hgsub
echo 'gitsuper/gitsub = [git]url-of-gitsub' >> .hgsub
gitsuper/.git/config
これらの最後の2つのステップは、と
のビットから自動化できますgitsuper/.gitmodules
。
hg add .hgsub && hg commit -m 'added Git subrepositories'
- hgsuper2のクローンを作成します。hgsuper2からクローンを作成します。
とで適切な内容を取得しgitsuper/
ますgitsuper/gitsub/
。
- 新しいコンテンツを更新してgitsubにコミットします。
- gitsuperを更新します。
- 一部のコンテンツを追加または変更して、ステージングします。
(cd gitsub && git pull origin master)
git add gitsub && git commit -m 'updated gitsuper content (also gitsub)'
- hgsuper2で、Gitサプレポジトリから変更をプルします
。
(cd gitsuper && git pull --recurse-submodules && git submodule update)
のコンテンツはプルによって更新されますgitsuper/
。gitsuper/gitsub/
hg commit -m 'updated gitsuper (and its contents)'
- hgsuper2-cloneにプルします。
hg pull -u
Gitのコンテンツが更新されました。
私のテストは(Mercurial1.8.1とGit1.7.4.1を使用して)機能しましたが、1つのバグに気づきました。Mercurialは、 (Gitがそのサブモジュールで行うように)切り離されたHEADを使用する代わりに、または単に(ie)を使用する代わりに、奇妙な名前のGitブランチを作成してチェックアウトします( origin/master
(ie ))。また、時々少しくさびになり、次のようなエラーが発生するようです。refs/heads/origin/master
master
refs/heads/master
fatal: git checkout: branch origin/master already exists
abort: git checkout error 128 in gitsuper
問題のGitリポジトリ(GitベースのMercurialサブリポジトリgit checkout HEAD~0 && git branch -D origin/master
)に移動し、次のコマンドで削除できるように(最初はHEADをデタッチし、(さらに重要なことに)ブランチから移動して)ブランチを削除することで問題を回避しました)。この回避策は、Gitリポジトリにローカルの変更が変更されていない限り、完全に安全です。
git submodule init
もう1つの小さな問題は、Mercurialによって作成されたGitスーパーリポジトリでGitサブモジュールコマンドを発行する前に、Gitにサブモジュールについて通知するために実行する必要があることです(サブモジュールは適切な場所に複製されましたが、Mercurialによって確立されたためです。にそれらのエントリはありません.git/config
。
同様に、GitベースのMercurialサブリポジトリ内からGitによって管理されるコンテンツへの変更をオーサリングする場合は、Mercurialでコミットする前に、常にGitサブモジュールを追加し、コミットし、Gitサブリポジトリからプッシュするように注意する必要があります。 「スーパープロジェクト」。そうしないと、Mercurialがgitsuperとgitsubの1つの組み合わせを使用し、gitsuper自体が別のバージョンのgitsubを参照するという状況に陥る可能性があります。つまり、Gitのサブモジュールコードをバイパスするため(GitサブモジュールをMercurialサブリポジトリとして管理することにより)、GitのサブモジュールのビューをMercurialのビューと同期させるように注意する必要があります。