Gitリポジトリ内の単一または複数のプロジェクトを選択しますか?


223

gitほとんどのプロジェクトをモジュール化した環境では、リポジトリごとに1つのプロジェクト、またはリポジトリ設計の問題ごとに複数のプロジェクトに直面しています。モジュール化されたプロジェクトを考えてみましょう。

myProject/
   +-- gui
   +-- core
   +-- api
   +-- implA
   +-- implB

現在、リポジトリごとに1つのプロジェクトがあります。それは自由を与えます

  • release 個々のコンポーネント
  • tag 個々のコンポーネント

しかしbranch、多くの場合、分岐にapiはの同等の分岐が必要coreであり、おそらく他のコンポーネントも必要であるため、コンポーネントにとっても面倒です。

releaseコンポーネントを個別にしたい場合でも、リポジトリ設計ごとに複数のプロジェクトを利用することで、同様の柔軟性を得ることができます

どのような経験があり、これらの問題にどのように/なぜ対処しましたか?


1
私は今、非常によく似た問題を抱えています。プロジェクトの異なるバージョンをリリースする必要があるので、それらは異なるリポジトリにある必要があります。しかし、これは管理するのは悪夢です。サブディレクトリだけを分岐する方法があれば素晴らしいでしょう。
アンドリューTフィンネル

1
各モジュールには、個別のバージョン番号が必要です。そして、使用しますgit-describe
linquize



Bit(bitsrc.io)とLerna(github.com/lerna/lerna)が言及されていないことに驚いています!詳細についてはこちらをご覧ください:hackernoon.com/…–
ヨニ

回答:


199

にはone project per repository、上記で説明したように、3つの大きな欠点があります。これらが真に別個のプロジェクトである場合、これらはあまり真実ではありませんが、その音の変化から、しばしば別の変更が必要になり、これらの問題を本当に誇張する可能性があります。

  1. バグがいつ導入されたかを発見するのは困難です。git bisectリポジトリをサブリポジトリに分割すると、ツールの使用がさらに難しくなります。それはだ、可能なことがはるかに困難である、それは危機の時代におけるバグ狩りを意味し、同じように簡単ではありません。
  2. 機能の履歴全体を追跡するのははるかに困難です。ヒストリトラバースコマンドはgit log、破損したリポジトリ構造の場合ほど有意義にヒストリを出力しません。サブモジュールやサブツリー、または他のスクリプト可能なメソッドを使用していくつかの有用な出力を取得できますが、関心のあるすべてのコミットを入力tig --grep=<caseID>またはgit log --grep=<caseID>スキャンすることとは異なります。あなたの履歴は理解しにくくなり、本当に必要なときに履歴が有用でなくなります。
  3. 新しい開発者は、コーディングを開始する前に、バージョン管理の構造を学習するのにより多くの時間を費やします。新しいジョブはすべて、手順をピックアップする必要がありますが、プロジェクトリポジトリを破壊すると、コードのアーキテクチャに加えてVC構造もピックアップする必要があります。私の経験では、これは、単一のリポジトリを使用する従来の中央集中型のショップから来たgitを初めて使用する開発者にとって特に困難です。

結局、これは機会費用の計算です。ある元雇用主では、プライマリアプリケーションを35の異なるサブリポジトリに分割していました。その上で、複雑なスクリプトセットを使用して履歴を検索し、状態(本番と開発ブランチなど)がそれら全体で同じであることを確認し、それらを個別にまたはまとめてデプロイしました。

ただ多すぎた。少なくとも私たちには多すぎます。管理オーバーヘッドにより、機能が軽快になり、展開が非常に難しくなり、新しい開発者に教えるのに時間がかかりすぎ、最初にリポジトリを破壊した理由をほとんど思い出せませんでした。ある美しい春の日、私はEC2で午後10クラスターのコンピューティング時間を費やしました。数十回のgit filter-branch呼び出しでリポジトリを戻しました。振り返ることはありませんでした。


7
余談ですが、リポジトリマネージャーとしては、20時間ではラップトップができなかった2時間でできる時間を昼食よりも安く購入できるシステムで購入するよりも楽しいものはほとんどありません。時々私は本当にインターネットが大好きです。
クリストファー

2
これらの個々のプロジェクトを個別のリリースとしてどのようにリリースしますか?それとも、それをする必要はありませんか?それが私が抱えている問題です。あなたはプロジェクトAのV1を作成する必要がある、と場合とプロジェクトB.のV2
アンドリュー・T Finnell

5
レポジトリ

1
一般的な使用例でこれを自動化するスクリプトを作成しました:github.com/Oakleon/git-join-repos
chrishiestand

「VC構造」とは何ですか?
ロバートハーヴェイ

60

クリストファーは、リポジトリごとに1つのプロジェクトの欠点を列挙する非常に良い仕事をしました。複数リポジトリのアプローチを検討する理由のいくつかを説明したいと思います。私が働いてきた多くの環境では、複数リポジトリのアプローチが妥当な解決策でしたが、リポジトリの数とカットを行う場所の決定は必ずしも簡単なものではありませんでした。

私の現在の立場では、10年以上の歴史を持つ巨大な単一リポジトリCVSリポジトリをいくつかのgitリポジトリに移行しました。その最初の決定以来、リポジトリの数は(他のチームのアクションを通じて)成長し、最適以上のものがあると私は思うほどになりました。いくつかの新入社員はリポジトリをマージすることを提案しましたが、私はそれに反対しました。Waylandプロジェクトにも同様の経験があります。私が最近見た講演では、ある時点で、200を超えるgitリポジトリがあり、リードが謝罪しました。彼らのウェブサイトを見ると、今では彼らが5であることがわかります。リポジトリへの参加と分割は管理可能なタスクであり、(理由の範囲内で)実験することは問題ありません。

それでは、いつ複数のリポジトリが必要になるのでしょうか?

  1. 単一のリポジトリは大きすぎて効率的ではありません。
  2. リポジトリは疎結合または分離されています。
  3. 通常、開発者が必要とするのは、開発するリポジトリの1つまたは小さなサブセットのみです。
  4. 通常、リポジトリを個別に開発し、たまに同期するだけで済みます。
  5. あなたはより多くのモジュール性を奨励したいです。
  6. 異なるチームは異なるリポジトリで作業します。

ポイント2と3は、ポイント1が成立する場合にのみ重要です。リポジトリを分割することで、オフサイトの同僚が被る遅延を大幅に減らし、ディスク消費を減らし、ネットワークトラフィックを改善しました。

4と5はより微妙です。たとえば、クライアントとサーバーのリポジトリを分割すると、クライアントとサーバーのコード間の変更を調整するためのコストが高くなります。これは、2つの間の分離されたインターフェイスを促進するという点で、プラスになる可能性があります。

マルチリポジトリプロジェクトの欠点があっても、多くの立派な作業がそのように行われます-ウェイランドとブーストが思い浮かびます。ベストプラクティスに関するコンセンサスがまだ発展していないと思います。判断が必要です。複数のリポジトリ(git-subtree、git-submoduleなど)を操作するためのツールはまだ開発および実験中です。私のアドバイスは、実験して実用的であることです。


7
この回答は、「リポジトリの結合と分割は管理可能なタスクである」という主張をサポートするリファレンスがあるとさらに役立ちます。
ワイルドカード

3
複数のリポジトリは、共有コードの変更を難しくするため、モジュール性に対しても機能します。クロスレポの依存関係により、統合が困難になり、コードをより簡単に破損する可能性があります(これを確認するための優れたツールがある場合でも)。よりモジュール化。
カートJ.サンプソン

MicroServicesとDDDの設計に関するすべてがここにあります。共有コードを最小限に抑える必要があります。
アーウィン

49

GitHubを使用しているため、実際には1つのリポジトリに複数のプロジェクトがありますが、それらのプロジェクト/モジュールが適切にモジュール化されていること確認します(-apiおよび-core規約+ Maven +静的およびランタイムチェックを使用し、いつかOSGiにブートすることもあります) 。

それは何を節約しますか?さて、複数のプロジェクトで小さな何かを変更する場合、複数のプルリクエストを発行する必要はありません。課題とWikiは集中管理などされています。

各モジュール/プロジェクトを適切な独立したプロジェクトとして扱い、CIサーバーなどで個別にビルドおよび統合します。


1
とても興味深い。これはgithubの一般的なモデルだと思います。個々のコンポーネントのリリースに直面している場合submodules、リポジトリ全体をリリースまたはタグ付けするようなものを採用していますか?
ヨハンシェーベルグ

必要に応じてサブモジュールを作成しますが、今は親からバージョンダウンします。
マルタインVerburg

私の現在の雇用主では、同様の戦略を使用して、プロジェクト内の最新のコミットに関するメタデータを、アーティファクトのさまざまなマニフェストファイル(つまりの結果git log -1 -- <project_dir>)にパッケージ化します。本当に素晴らしいです。この答えは、より多くの賛成に値します。
クリストファー14

22

私にとって、1つまたは複数のリポジトリを使用する主な違いは、次の質問に対する回答です。

  • 同じチームによって開発された複数のパーツは、同じリリースサイクルで、同じ顧客ですか?次に、1つのリポジトリを分割する理由が少なくなります。
  • 複数の部分は互いに非常に依存していますか?そのため、モデル、コントローラー、UIを分割することは(それらが異なる部分であっても)相互依存性が高いため、あまり賢明ではありません。ただし、2つの部分の依存関係が小さく、数年ごとにしか変更されない安定したインターフェイスによって実装される場合、2つの部分を2つのリポジトリに分割するのが賢明です。

例として、Subversionリポジトリの「品質」をチェックする小さなアプリケーション(クライアントのみ)があります。コマンドラインから開始できるコア実装があり、Java 6で動作します。しかし、Java 8の一部としてJavaFXを使用するUIの実装を開始しました。そのため、2を分割し、 2番目のリポジトリ(2番目のビルドプロセス)、異なるスケジュール、...

私は上記の回答が好きです(投票しました)が、それらは完全な真実の話ではないと思います。そこで、リポジトリを分割するための引数も追加したかったのです。したがって、本当の答え(いつ分割するか)は中間のどこかにあるかもしれません...



0

あなたの例から、リポジトリは相互依存性の観点から設定する必要があります。MicroServicesおよびDomain Driven Designの設計に関するすべての理由がここに適用されます。場合によっては、コードの重複が許容される場合、インターフェイスを操作する場合、本当に必要な場合を除き互換性が損なわれないようにするなどです。

私の見解では、UIはバックエンドから独立している必要があります。したがって、UIプロジェクトリポジトリには通常、UIコードとクライアントコントローラーが含まれている必要があります。クライアントコントローラは、抽象的な方法でサービスコントローラに接続します。サービスとは別にバージョン管理されるサービスクライアント/ API抽象化を使用するため、クライアントを壊すことなくサービスを更新できます(複数の異なるクライアントが存在する可能性があります)。

したがって、サービス自体が独自のリポジトリである必要があります。私の見解では、サービスは、いくつかの単一の観点からのビジネスロジックの単なるラッパーです。そのため、通常、ビジネスロジックは、それをホストするサービステクノロジーから分離する必要があります。一方、リポジトリ実装は通常、ビジネスロジックに非常に密接に接続されているため、同じリポジトリに統合できます。ただし、走行距離は異なる場合があります。

もちろん、バックエンドと同じソースからすべてのUIをホストでき、バックエンドサービスが通常同じクライアントによってのみ使用される場合、テクノロジーまたは多くのスタックをサポートするという点でほとんど変更されそうにない単純なプロジェクトは、より多くの恩恵を受けることができます緊密に統合されたリポジトリ。

その場合、たぶん、1つのリポジトリに完全なカテゴリを配置するだけで十分であり、機能ドメインが独自のリポジトリで適切にスタンドアロンであることを確認することに集中できます。そうすれば、小さなリポジトリの利点を最大限に活用でき、それ以外のオーバーヘッドはほとんどありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.