11

C# で .NET エンタープライズ ソフトウェアを開発します。バージョン管理システムの改善を検討しています。私は以前にマーキュリアルを使用したことがあり、当社でそれを使用して実験してきました。ただし、エンタープライズ製品を開発しているため、再利用可能なコンポーネントまたはモジュールに重点を置いています。コンポーネントと依存関係を管理するために Mercurial のサブリポジトリを使用しようとしていますが、いくつかの問題があります。ソース管理/依存関係管理の基本的な要件は次のとおりです。

  1. 再利用可能なコンポーネント
    1. ソースごとに共有 (デバッグ用)
    2. サードパーティのバイナリやその他の再利用可能なコンポーネントに依存している
    3. 消費する製品のコンテキストで開発し、ソース管理にコミットすることができます
  2. 依存関係
    1. 製品は、サードパーティのバイナリやその他の再利用可能なコンポーネントに依存しています
    2. 依存関係には独自の依存関係があります
    3. 開発者は、依存関係でのバージョンの競合を通知する必要があります

これが私が使用しているmercurialの構造です:

再利用可能なコンポーネント:

SHARED1_SLN-+-docs
            |
            +-libs----NLOG
            |
            +-misc----KEY
            |
            +-src-----SHARED1-+-proj1
            |                 +-proj2
            |
            +-tools---NANT

最初のものを消費する 2 番目の再利用可能なコンポーネント:

SHARED2_SLN-+-docs
            |
            +-libs--+-SHARED1-+-proj1
            |       |         +-proj2
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-src-----SHARED2-+-proj3
            |                 +-proj4
            |
            +-tools---NANT            

両方のコンポーネントを消費する製品:

PROD_SLN----+-docs
            |
            +-libs--+-SHARED1-+-proj1
            |       |         +-proj2
            |       |
            |       +-SHARED2-+-proj3
            |       |         +-proj4
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-src-----prod----+-proj5
            |                 +-proj6
            |
            +-tools---NANT

ノート

  1. レポはCAPSです
  2. すべての子リポジトリはサブリポジトリと見なされます
  3. サードパーティ (バイナリ) ライブラリと内部 (ソース) コンポーネントはすべて、libs フォルダーにあるサブリポジトリです。
  4. サードパーティのライブラリは個々の mercurial リポジトリに保持されるため、使用するプロジェクトはライブラリの特定のバージョンを参照できます (つまり、古いプロジェクトは NLog v1.0 を参照し、新しいプロジェクトは NLog v2.0 を参照する場合があります)。
  5. すべての Visual Studio .csproj ファイルは第 4 レベル (proj* フォルダー) にあり、依存関係への相対参照が可能です (つまり、NLog を参照するすべての Visual Studio プロジェクトの ../../../libs/NLog/NLog.dll)。
  6. すべての Visual Studio .sln ファイルは第 2 レベル (src フォルダー) にあるため、コンポーネントを消費コンポーネントまたは製品に「共有」するときに含まれません。
  7. 開発者は、ソースが使用する Visual Studio プロジェクトの proj* フォルダーの子である限り (つまり、さまざまなソース/リソースを含む proj* フォルダーに n 個の子を含めることができます)、適切と思われるソース ファイルを自由に編成できます。
  8. Bob が SHARED2 コンポーネントと PROD1 製品を開発している場合、PROD1_SLN リポジトリ内で SHARED2 ソース (proj3 に属するソースなど) を変更し、それらの変更をコミットすることは完全に合法です。消費プロジェクトのコンテキストで誰かがライブラリを開発しても、私たちは気にしません。
  9. 社内で開発されたコンポーネント (SHARED1 および SHARED2) は、通常、プロジェクトを使用するソースによって含まれます (Visual Studio では、dll 参照を参照するのではなく、プロジェクトへの参照を追加します)。これにより、強化されたデバッグ (ライブラリ コードへのステップ イン) が可能になり、Visual Studio がプロジェクトを再構築する必要があるとき (依存関係が変更されたとき) を管理できるようになり、必要に応じてライブラリを変更できるようになります (上記のメモで説明されているように)。

質問

  1. Bob が PROD1 で作業しており、Alice が SHARED1 で作業している場合、Alice が SHARED1 に変更をコミットしたとき、Bob はどのようにして知ることができますか。現在 Mercurial を使用しているため、Bob は各サブレポ内で手動でプルして更新する必要があります。彼が PROD_SLN リポジトリからサーバーにプッシュ/プルする場合、サブリポジトリの更新についてはまったく知りません。これはMercurial wikiで説明されています。ボブがサーバーから最新の PROD_SLN をプルしたときに、サブリポジトリの更新をボブに通知するにはどうすればよいですか? 理想的には、通知を受け取り (できればプル中に)、更新するサブリポジトリを手動で決定する必要があります。

  2. SHARED1 は NLog v1.0 (mercurial の commit/rev abc) を参照し、SHARED2 は Nlog v2.0 (mercurial の commit/rev xyz) を参照するとします。ボブが PROD1 でこれら 2 つのコンポーネントを吸収している場合、ボブはこの不一致に注意する必要があります。技術的には、Visual Studio/.NET では 2 つのアセンブリが異なるバージョンの依存関係を参照できますが、NLog に依存するすべての .NET プロジェクトで NLog へのパスが固定されているため、私の構造ではこれが許可されません。ボブは、2 つの依存関係にバージョンの競合があることをどのように知ることができますか?

  3. ボブが PROD1 のリポジトリ構造を設定していて、SHARED2 を含めたい場合、SHARED2 に必要な依存関係をどのように知ることができますか? 私の構造では、彼は SHARED2_SLN リポジトリを手動で複製 (またはサーバー上で参照) し、libs フォルダーを調べるか、.hgsub ファイルをピークして、含める必要がある依存関係を判断する必要があります。理想的には、これは自動化されます。製品に SHARED2 を含めると、SHARED1 と NLog も自動的に組み込まれ、他の依存関係とのバージョンの競合があるかどうかが通知されます (上記の質問 2 を参照)。

より大きな質問

  1. 水銀は正しい解決策ですか?

  2. より良い水銀構造はありますか?

  3. これはサブリポジトリの有効な使用法ですか (つまり、Mercurial 開発者はサブリポジトリを最後の手段としてマークしました)?

  4. 依存関係の管理に Mercurial を使用することは理にかなっていますか? 依存関係を管理するためのさらに別のツールを使用することもできます (おそらく、内部の NuGet フィードでしょうか?)。これはサードパーティの依存関係にはうまく機能しますが、内部で開発されたコンポーネントには本当に面倒です (つまり、それらが積極的に開発されている場合、開発者は常にフィードを更新する必要があり、内部でそれらを提供する必要があり、許可されません)。消費するプロジェクトによって変更されるコンポーネント (注 8 および質問 2)。

  5. エンタープライズ .NET ソフトウェア プロジェクト向けのより良いソリューションはありますか?

参考文献

私はいくつかのSOの質問を読み、これが役立つことがわかりましが、受け入れられた回答は、依存関係に専用のツールを使用することを提案しています. このようなツールの機能は気に入っていますが、使用中のプロジェクトから依存関係を変更してコミットすることはできません (より大きな質問 4 を参照)。

4

2 に答える 2

12

これはあなたが探していた答えではないかもしれませんが、私たちは最近、初心者の Mercurial ユーザーがサブリポジトリを使用した経験があり、私たちの経験を伝える機会を探していました...

要約すると、経験に基づく私のアドバイスは次のとおりです。代わりに、ディレクトリを並べてレイアウトし、それに対応するようにビルドを調整する方法を見つけてください。

サブレポのリビジョンを親レポのリビジョンと結びつけることは魅力的に思えますが、実際にはうまくいきません。

変換のすべての準備中に、複数の異なるソースから、サブリポジトリは壊れやすく、適切に実装されていないというアドバイスを受けましたが、リポジトリとサブリポジトリ間のアトミックコミットが必要だったので、とにかく先に進みました。アドバイス、またはそれに対する私の理解は、実際的な結果よりも原則について多くを語っていました。

Mercurial とサブレポを使ってライブに行ったのは一度だけで、そのアドバイスを本当によく理解できました。ここに (記憶から) 私たちが遭遇した種類の問題の例を示します。

  • ユーザーは更新とマージのプロセスに苦労することになります。
  • サブレポではなく、親レポを更新する人もいます
  • サブリポジトリからプッシュする人もいますが、ang .hgsubstate は更新されません。
  • 誰かがマージ後に .hgsubstate を誤った状態のままにしてしまうため、サブリポジトリで作成されたリビジョンを「失う」ことになります。
  • 一部のユーザーは、.hgsubstate が更新されているのにサブリポジトリが更新されていないという状況に陥り、非常に不可解なエラー メッセージが表示され、何が起こっているのかを理解するために何時間も費やすことになります。
  • また、リリースのタグ付けと分岐を行う場合、親リポジトリとサブリポジトリの両方でこれを正しく行う方法についての説明は、何十行にもなります。(そして、親切で飼いならされた Mercurial の専門家に指示を書くのを手伝ってもらいました!)

これらのことはすべて、熟練したユーザーにとっては非常に面倒なことですが、Mercurial を初心者ユーザーに展開する場合、それは本当の悪夢であり、多くの時間を浪費する原因となります。

そのため、サブレポでコンバージョンを得るために多くの時間を費やした後、数週間後にサブレポをレポに変換しました。.hgsubstate を介してサブレポを参照する変換には大量の履歴があったため、はるかに複雑な問題が残りました。

Mercurial のFeatures of Last Resortページなど、以前のすべてのアドバイスの実際的な結果を本当に理解していればよかったのにと思います。

しかし、私はサブプロジェクトを管理する必要があります!

繰り返しますが、確信はありません。多数の依存関係を持つ Mozilla のような重要なプロジェクトは、サブリポジトリを使用しなくても問題なく実行できます。ほとんどの小さなプロジェクトでは、サブリポジトリを使用しないほうがよいでしょう。


編集:シェルリポジトリに関する考え

免責事項により、私はそれらの経験がありません...

いいえ、多くはないと思います。まだサブリポジトリを使用しているため、同じユーザーの問題がすべて適用されます (もちろん、サブリポジトリを処理するための正しいオプションを人間が提供する必要をなくすために、すべてのステップにラッパー スクリプトを提供できる場合を除きます)。

また、引用したwikiページには、シェルリポジトリに関する特定の問題がいくつかリストされていることに注意してください。

  • project/ と somelib/ の間の関係の過度に厳密な追跡
  • プロジェクト/をチェックまたはプッシュすることは不可能です somelib/ソースリポジトリが
  • 再帰的な diff、log、および
  • 驚くべきコミットのステータス再帰的性質

編集 2 - すべてのユーザーを対象にトライアルを行う

問題があることに実際に気付き始めたのは、複数のユーザーがサブリポジトリへの変更を含め、コミット、プル、プッシュを開始したときでした。私たちにとって、これらの問題に対応するには遅すぎました。もっと早く彼らのことを知っていれば、もっと簡単に簡単に対応できたのに。

したがって、この時点で私が提供できる最善のアドバイスは、レイアウトが石に刻まれる前に、プロジェクトのレイアウトを試運転することをお勧めすることです。

変更を行うには手遅れになるまで本格的なトライアルを終了しましたが、それでも人々はサブリポジトリではなく親リポジトリのみを変更したため、手遅れになるまで全体像が見えませんでした。

つまり、どのようなレイアウトを検討するにしても、そのレイアウトでリポジトリ構造を作成し、多くの人に編集してもらいます。さまざまなリポジトリ/サブリポジトリに十分な実際のコードを配置して、スローウェイのものであっても人々が実際の編集を行えるようにしてください。

考えられる結果:

  • すべてが正常に機能することがわかる場合があります。その場合、確実性を得るためにある程度の時間を費やしたことになります。
  • 一方で、結果がどうなるかを考えようと時間を費やすよりも、はるかに迅速に問題を特定できる可能性があります。
  • また、ユーザーも多くのことを学びます。
于 2012-07-24T21:52:35.530 に答える
3

質問1:

このコマンドは、親の「シェル」レポで実行されると、すべてのサブレポをトラバースし、存在しないデフォルトのプル場所から変更セットを一覧表示します。

hg incoming --subrepos

「--subrepos」オプションがチェックされている場合 (同じペインで)、TortoiseHg の「同期」ペインの「受信」ボタンをクリックすることで、同じことができます。

Mercurial IRC チャンネルのユーザーがここで助けてくれてありがとう。

質問 2 & 3:

まず、hg wiki で推奨されているように、親リポジトリが本当に「シェル」リポジトリになるように、リポジトリ構造を変更する必要があります。私はこれを極端に取り上げて、シェルにはコンテンツを含めるべきではなく、子としてのサブリポジトリのみを含めるべきだと言います。要約すると、src の名前を main に変更し、ドキュメントを main の下のサブリポジトリに移動し、prod フォルダーをサブリポジトリに変更します。

SHARED1_SLN:

SHARED1_SLN-+-libs----NLOG
            |
            +-misc----KEY
            |
            +-main----SHARED1-+-docs
            |                 +-proj1
            |                 +-proj2
            |
            +-tools---NANT

SHARED2_SLN:

SHARED2_SLN-+-libs--+-SHARED1-+-docs
            |       |         +-proj1
            |       |         +-proj2
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-main----SHARED2-+-docs
            |                 +-proj3
            |                 +-proj4
            |
            +-tools---NANT            

PROD_SLN:

PROD_SLN----+-libs--+-SHARED1-+-docs
            |       |         +-proj2
            |       |         +-proj2
            |       |
            |       +-SHARED2-+-docs
            |       |         +-proj3
            |       |         +-proj4
            |       |
            |       +-NLOG
            |
            +-misc----KEY
            |
            +-main----PROD----+-docs
            |                 +-proj5
            |                 +-proj6
            |
            +-tools---NANT
  1. すべての共有ライブラリと製品には、独自のリポジトリ (SHARED1、SHARED2、および PROD) があります。
  2. 共有ライブラリまたは製品で個別に作業する必要がある場合は、hg を使用して依存関係のリビジョンを管理するシェル (_SLN で終わる私のリポジトリ) を利用できます。シェルにはコンテンツが含まれておらず、サブリポジトリのみが含まれているため、利便性のためだけです。
  3. 共有ライブラリまたは製品のリリースをローリングするとき、開発者は、リリースの作成に使用されたすべての依存関係とその hg リビジョン/変更セット (またはできれば人間に優しいタグ) をリストする必要があります。このリストは、シェルではなく、ライブラリまたは製品 (SHARED1、SHARED2、または PROD) のリポジトリ内のファイルに保存する必要があります。これにより質問 2 と 3 がどのように解決されるかについては、以下の注 A を参照してください。
  4. 共有ライブラリまたは製品のリリースをロールバックする場合、一致するタグをプロジェクトリポジトリに配置する必要があります。これは便宜上シェルですが、シェルが暴走した場合(@Clareの回答で実際の経験から表明された懸念) )、シェル自体はダムでコンテンツが含まれていないため、実際には問題になりません。
  5. Visual Studio の sln ファイルは、 shell ではなく、共有ライブラリまたは製品のリポジトリ (SHARED1、SHARED2、または PROD) のルートに入ります。その結果、PROD に SHARED1 を含めると、開かない追加のソリューションがいくつか発生する可能性がありますが、それは問題ではありません。さらに、本当に SHARED1 で作業し、(PROD_SLN シェルで作業しながら) 単体テストを実行したい場合は、非常に簡単です。前述のソリューションを開くだけです。

注 A:

上記のポイント 3 に関して、依存関係ファイルが .hgsub に似た形式を使用し、rev/changeset/tag が追加されている場合、依存関係の取得を自動化できます。たとえば、新製品に SHARED1 が必要です。SHARED1 を libs フォルダーに複製し、ヒントまたは最後のリリース ラベルに更新します。ここで、依存関係ファイルを確認し、a) 依存関係を正しい場所に複製し、b) 指定された rev/changeset/tag に更新する必要があります。これを自動化することは非常に実現可能です。さらに、rev/changeset/tag を追跡し、共有ライブラリ間に依存関係の競合があることを開発者に警告することもできます。

Bob が PROD を開発している間に Alice が積極的に SHARED1 を開発している場合、穴が残ります。Alice が NLog v3.0 を使用するように SHARED1_SLN を更新した場合、Bob はこれを知らない可能性があります。Alice が依存関係ファイルを更新して変更を反映した場合、Bob は情報を持っているので、Bob は変更を認識している必要があります。

より大きな質問 1 & 4:

これはソース管理の問題であり、依存関係管理ツールで解決できるものではないと思います。なぜなら、それらは一般にバイナリで動作し、依存関係のみを取得するためです (変更を依存関係に戻すことを許可しないでください)。私の依存関係の問題は、Mercurial に固有のものではありません。私の経験から、すべてのソース管理ツールには同じ問題があります。SVN での 1 つの解決策は、単に svn:externals (または svn コピー) を使用し、すべてのコンポーネントにその依存関係を再帰的に含めて、製品を構築するためのおそらく巨大なツリーを作成することです。ただし、Visual Studio では、共有プロジェクトのインスタンスを 1 つだけ含めて、どこでも参照したいので、これはうまくいきません。@Clare の回答、hg メールリストへの私のメールに対する Greg の回答が示唆するように、コンポーネントをできるだけ平らに保ちます。

より大きな質問 2 & 3:

上で説明したように、より良い構造があります。サブレポを使用する強力なユースケースがあると思いますが、実行可能な代替手段は見当たりません。@Clare の回答で述べたように、サブリポジトリなしで依存関係を管理できると考えるキャンプがあります。ただし、この声明を裏付ける証拠や実際の参照はまだ見ていません.

より大きな質問 5:

より良いアイデアはまだあります...

于 2012-07-25T09:01:55.090 に答える