web-dev-qa-db-ja.com

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

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

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

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

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

しかし、branchコンポーネントの扱いも面倒です。頻繁に分岐するapiには、coreに同等のブランチが必要であり、おそらく他のコンポーネントも必要になるためです。

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

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

239
Johan Sjöberg

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

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

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

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

209
Christopher

Christopher リポジトリごとに1つのプロジェクトモデルの欠点を列挙するのに非常に優れた仕事をしました。マルチリポジトリアプローチを検討する理由のいくつかについて説明します。私が取り組んだ多くの環境では、マルチリポジトリのアプローチが妥当な解決策でしたが、リポジトリをいくつ持つべきか、どこでカットするのかを決めるのは必ずしも簡単なことではありませんでした。

私の現在の立場では、10年以上の歴史を持つ巨大な単一リポジトリCVSリポジトリをいくつかのgitリポジトリに移行しました。その最初の決定以来、リポジトリーの数は(他のチームのアクションによって)増加しており、最適なものよりも多くあると私が思うまでになりました。いくつかの新入社員はリポジトリのマージを提案しましたが、私はそれに反対しました。 Waylandプロジェクトにも同様の経験があります。最近私が見た講演では、ある時点で200を超えるgitリポジトリがありましたが、そのことについてリードは謝罪しました。彼らの website を見ると、彼らは5歳であることがわかります。リポジトリへの参加と分割は扱いやすいタスクであり、(妥当な範囲内で)実験しても問題ないことを確認することが重要です。

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

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

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

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

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

70
Spacemoose

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

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

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

51
Martijn Verburg

私にとって、1つ以上のリポジトリを使用する主な違いは、次の質問に対する答えです。

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

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

上記の回答は気に入っています(投票したものです)が、それは本当の話ではありません。そのため、リポジトリを分割するための引数も追加したいと思いました。したがって、実際の答え(いつ分割するか)は途中のどこかにあるかもしれません...

24
mliebelt

git-subtreeAtlassian blogmedium blog 、または kernel link を参照)は、あなたが持っているものにぴったりです。したがって、最上位のプロジェクトはそれぞれ、異なるバージョンのサブツリーのセットを使用します。

あなたの例から、リポジトリはそれらがどのように相互依存しているかという観点で設定されるべきです。 MicroServicesとドメインドリブンデザインの設計に関するすべての理由がここに当てはまります。場合によっては、重複したコードが許容され、インターフェースを操作し、本当に必要でない限り互換性を壊さないことなどです。

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

したがって、サービス自体は独自のリポジトリでなければなりません。私の考えでは、このサービスは、単一の通過点ビジネスロジックのラッパーにすぎません。そのため、ビジネスロジックは通常、それをホストするサービステクノロジーとは別にする必要があります。一方、リポジトリの実装は通常、ビジネスロジックに密接に接続されているため、同じリポジトリに統合できます。しかし、そこにあなたの走行距離は異なる場合があります。

もちろん、テクノロジーや複数のスタックのサポートの点で大幅に変更される可能性が低い単純なプロジェクトでは、すべてのUIをバックエンドと同じソースからホストでき、バックエンドサービスは通常、同じクライアントでのみ使用されます。緊密に統合されたリポジトリ。

その場合は、たぶん1つのリポジトリに完全なバーティカルを配置するだけで問題なく、機能ドメインが独自のリポジトリで適切にスタンドアロンであることを確認することに焦点を当てます。その場合でも、リポジトリが小さいというほとんどの利点があり、それ以外の場合はオーバーヘッドがほとんどありません。

1
Arwin