52

CoreABSuperという名前の 4 つのプロジェクトがあるとします。依存関係ツリーは次のようになります。

Super ---> Core
       |-> A -> Core
       |-> B -> Core

各プロジェクトをスタンドアロンにしたい、つまり、各プロジェクトを独自にチェックアウトしてコンパイルできるようにしたい (もちろん、それぞれの依存関係を含む)。

各プロジェクトをリポジトリにマッピングしてから、サブモジュールで依存関係を参照することを考えましたが、そのアプローチには次の問題があります。

  1. Superをすべての依存関係とともにチェックアウトすると、 Coreの 3 つのコピーが作成されます。
  2. サブモジュールは完全に独立しているため、これら 3 つのコピーのそれぞれがCoreの異なるリビジョンを指している可能性があり、混乱を招きます。

それで...何か足りないのですか?git サブモジュールを誤解したり、誤用したりしましたか? この問題に対する他の解決策はありますか (バイナリ依存関係に頼る以外に)?

4

6 に答える 6

18

Git サブモジュールでオーバーライドされた依存関係がないことを発見しました。

Super が Core に依存している場合、その Core の依存関係は、A と B が Core で持っている依存関係を「オーバーライド」する必要があります。

それをエミュレートする唯一の方法は、あなたが行った方法で Super プロジェクトを作成し、 A
B のサブモジュール Core を削除することです
(つまり、Super は A' と B' に依存するようになりました。 B' はコアのない B です)

于 2009-09-14T03:55:32.317 に答える
9

git リポジトリは、各リポジトリが特定の目的のためのスタンドアロン エンティティであるという点で、かなりアトミックである必要があります。プロジェクトAとBを組み合わせる以外のスーパープロジェクトの目的は何ですか?固有のもの (つまり、A、B、または Core のいずれにもないファイル) がない場合、それはかなり冗長です。

編集: git サブモジュールは、私が働いていたある場所で特に苦痛を伴うため、テキスト ファイルを介して依存リポジトリを追跡する独自の依存システムをセットアップしました。特定のコミットではなく、常にブランチの先頭を追跡するように設定しました。

次のように、すべてのプロジェクトを Super プロジェクトの一部であるかのようにセットアップできました。

Super
|-A
|-B
|-Core

プロジェクトは、相対パスを使用して相互に参照します../A/include.h。レポ A をチェックアウトしても機能しません。A だけで作業するには、別の「スーパー」レポを作成する必要があります。

AWorking
|-A
|-Core

編集git でのこの動作のもう 1 つの理由は、ルート リポジトリ ディレクトリの上 (つまり、.git フォルダーを含むフォルダーの上) にあるものを追跡できないことです。これは、スーパー プロジェクトとサブプロジェクトが必要な場合に必ず必要になります。同じリポジトリを参照してください。

于 2009-09-14T03:13:19.820 に答える
7

ここでの問題は、Git の設計と解決しようとしている問題との不一致だと思います。

Git はツリーを追跡するのに適しています。プロジェクト間の依存関係は、グラフを形成できます (おそらく形成します)。ツリーはグラフですが、グラフは必ずしもツリーではありません。問題はグラフを効果的に表現する方法であるため、ツリーはジョブに最適なツールではありません。

うまくいくかもしれないアプローチは次のとおりです。

git プロジェクトには .gitmodules ディレクトリがあり、コミットが依存する可能性のあるプロジェクト、それらが見つかる場所、プロジェクト内のどのパスに挿入されるかを示す「ヒント」が記録されます。( http://osdir.com/ml/git/2009-04/msg00746.html )

一連のプロジェクトからこの情報を読み取り、各プロジェクトの .gitmodules ファイルにあるヒントを、それらのプロジェクトが実際に配置されているファイルシステム上の場所にマップし、git が期待するパスからシンボリック リンクを追加するスクリプトを追加できます。サブモジュールをそれぞれのプロジェクトの実際のファイルシステムの場所にチェックアウトします。

このアプローチでは、シンボリック リンクを使用してツリー型から抜け出し、グラフを構築します。リンクを git リポジトリに直接記録すると、ローカル セットアップに固有の相対パスが個々のプロジェクトに記録され、プロジェクトが「完全に独立」することはありません。したがって、シンボリックリンクを動的に構築するスクリプト。

私は、このアプローチは望ましくない方法で git に干渉する可能性があると考えています。これは、あるものを見つけることが期待されるパスをたどり、代わりに別のものを配置したためです。おそらく、シンボリックリンクのパスを .gitignore することができます。しかし今、私たちはそれらのパスを 2 回書き留めており、DRY に違反しています。この時点で、サブモジュールを使用するふりをすることからもかなり離れています。各プロジェクトの別の場所に依存関係を記録し、git が期待するもののために .gitmodules ファイルを残すことができます。したがって、独自のファイル、たとえば .dependencies を作成し、各プロジェクトはその依存関係をそこに記述できます。私たちのスクリプトはそこを見て、シンボリックリンクを構築します。

うーん、独自の軽量パッケージ形式を備えたアドホック パッケージ管理システムについて説明したところかもしれません :)

megamic の提案は、私には git サブモジュールの良い使い方のように思えます。ここでは、グラフではなくセットを追跡することのみを扱っており、セットはツリーに簡単に収まります。1 レベルの深さのツリーは、基本的に親ノードと子ノードのセットです。

あなたが指摘したように、それはあなたの質問に記載されている問題を完全に解決するものではありません。私たちが関心を持っている可能性が高い「これはそれで動作する」という情報を 2 つの異なるタイプに分けることができます。 . 独自のビルド セットアップで使用される、「この一連のプロジェクト バージョンを使用してシステム全体を正常にテストしました」というステートメント

megamic の回答は解決されましたが (2)、(1) については、プロジェクトに依存関係を教えてもらいたいと考えています。次に、(1) からの情報を使用して、最終的に (2) として記録するバージョン セットを計算できます。これは、独自のツールを保証するのに十分複雑な問題であり、パッケージ管理システムに戻ります:)

私の知る限り、優れたパッケージ管理ツールのほとんどは、特定の言語またはオペレーティング システムのユーザー向けに作られています。Ruby の世界の「gem」パッケージについては Bundler を、Debian の世界の「.deb」パッケージについては apt を参照してください。

「ポリグロット」( http://blog.heroku.com/archives/2011/8/3/polyglot_platform/ ) プログラミング プロジェクトに適した、言語に依存せず、OS に依存しない優れたソリューションを誰かが知っている場合は、とても興味があります!それを質問として投稿する必要があります。

于 2011-08-08T03:45:25.533 に答える
2

次のように一貫性を管理できると思います:すべての「コア」ライブラリで同じ名前の「参照」ブランチまたは一連のタグを定義します(注:例には「コア」ライブラリが1つしかありません)。次に、サブプロジェクト (A、B、...) の開発者に、できるだけ早く「コア」の参照バージョンに定期的にアップグレードするように指示します。

ビルドを実行する前に、クリーンで再帰的な「スーパー」トップレベル チェックアウトで次の 3 つのコマンドを実行して、「コア」が A、B、C などで一貫して使用されていることを簡単に確認します。

# 1.  Switch to the reference version (= "Force" consistency where need be)
git submodule foreach --recursive 'git checkout [origin/]reference || true'

# 2a. Show which inconsistencies you just forced; terse output
git status -s; git submodule foreach --recursive git status -s 2>/dev/null

# 2b. Same but verbose output
git submodule; git submodule foreach --recursive git submodule

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive

上記の「簡潔な出力」コマンド 2a は、コアの「参照」バージョンを使用していないサブプロジェクトを強調表示します。

アプローチを簡単に拡張して、差分を表示したり、アップグレードを強制したり、その他の好きなことをしたりできます。

于 2012-02-09T11:43:12.780 に答える
2

ハードリンクを使用して共有サブモジュールをクローンに変換する小さなユーティリティ タスクが機能する場合があります。

ここで私の完全なソリューションを読むことができます: https://stackoverflow.com/a/10265084/84283

于 2012-04-22T04:03:25.867 に答える
0

依存関係ツリーをサブモジュールにマップしようとはしません-あなたがすでに発見した理由からです。

サブモジュールは、特定のブランチの特定のリビジョンを追跡するため、一貫した一連のモジュールのスナップショットを提供するのに役立ちます。

そのため、プロジェクトで異なるモジュールの特定のバージョンのセットを 1 つのユニットとして追跡する必要がある場合は、それらをサブモジュールとしてグループ化できます。次に、さまざまなバージョンのさまざまなモジュール セットにタグを付けて、プロジェクトの履歴を示すことができます。各タグは、ある時点で互換性があったモジュールのバージョンを示します。

 tags/
     release1/ 
           |-> A@1.0
           |-> B@1.1
           |-> C@1.2
     release2/
           |-> A@2.0
           |-> B@1.3
           |-> C@1.5

少なくとも私がそれらをどのように理解しているかは、Git に関するほとんどのことと同様に、おそらくそれ以上のものがあるでしょう。依存関係の管理に関して、私が言えることは別の方法を見つけることだけです。私が理解しているように、サブモジュールの有無にかかわらずGitが設計されたものではありません。

于 2009-09-14T03:15:54.370 に答える