web-dev-qa-db-ja.com

ネストされたサブモジュールと依存関係をGit

Core[〜#〜] a [〜#〜][〜#〜] b [〜#〜]という名前の4つのプロジェクトがあるとしましょうスーパー。依存関係ツリーは次のようになります。

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

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

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

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

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

46

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

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

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

14
VonC

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

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

すべてのプロジェクトを、次のようなスーパープロジェクトの一部であるかのように設定することができました。

Super
|-A
|-B
|-Core

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

AWorking
|-A
|-Core

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

7
Igor Zevaka

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

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

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

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

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

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

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

うーん、私はアドホックパッケージ管理システムを独自の軽量パッケージフォーマットで説明したかもしれないと思います:)

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

あなたが指摘したように、それはあなたの質問で述べられた問題を完全に解決するわけではありません。関心があると思われる「これはそれで機能する」情報の2つの異なるタイプを分類できます。1。「プロジェクトYのバージョンXが必要です」というプロジェクトのバージョン(おそらくプロジェクトの作成者による)からのステートメント2 。「このプロジェクトバージョンのセットを使用してシステム全体を正常にテストしました」という、独自のビルドセットアップで使用されるステートメント

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

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

'polyglot'( http://blog.heroku.com/archives/2011/8/3/polyglot_platform/ )プログラミングプロジェクト、私は非常に興味があります!それを質問として投稿する必要があります。

6
Charlie

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

あなたはここで私の完全な解決策を読むことができます: https://stackoverflow.com/a/10265084/8428

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

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

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

2
MarcH

すでに発見した理由から、依存関係ツリーをサブモジュールにマッピングしようとはしません。

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

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

 tags/
     release1/ 
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]
     release2/
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]

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

0
aaa90210