gitでは、ダースのライブラリのバージョニングを行う方法がすべて並行して動作しました


11

私たちはプロジェクトを行っていますが、プロジェクト間で多くのコードを再利用し、共通のコードを含むライブラリをたくさん持っています。新しいプロジェクトを実装するにつれて、一般的なコードを抽出してライブラリに追加する方法が増えています。ライブラリは互いに依存し、プロジェクトはライブラリに依存します。各プロジェクト、およびそのプロジェクトで使用されるすべてのライブラリは、参照しているすべてのライブラリの同じバージョンを使用する必要があります。ソフトウェアをリリースする場合、バグを修正する必要があり、長年、場合によっては数十年にわたって新しい機能を追加する必要があるかもしれません。約12のライブラリがあり、変更は多くの場合2つ以上にまたがり、複数のチームが複数のプロジェクトを並行して作業し、これらすべてのライブラリに同時に変更を加えます。

最近、gitに切り替えて、各ライブラリおよび各プロジェクトのリポジトリを設定しました。stashを共通のリポジトリとして使用し、機能ブランチで新しい作業を行い、プルリクエストを作成し、レビュー後にのみそれらをマージします。

プロジェクトで対処しなければならない問題の多くは、いくつかのライブラリとプロジェクト固有のコードを変更する必要があります。多くの場合、ライブラリインターフェイスの変更が含まれますが、その一部には互換性がありません。(これが怪しいと思うなら、私たちはハードウェアとインターフェイスし、特定のハードウェアを汎用インターフェイスの後ろに隠します。他のベンダーのハードウェアを統合するたびに、現在のインターフェイスが予期しなかったケースに遭遇するため、それらを改良する必要があります。)たとえば、プロジェクトを想像しP1たライブラリを使用してL1L2L3L1また、使用していますL2L3、とL2用途L3にも。依存関係グラフは次のようになります。

   <-------L1<--+
P1 <----+  ^    |
   <-+  |  |    |
     |  +--L2   |
     |     ^    |
     |     |    |
     +-----L3---+

ここで、このプロジェクトの機能に変更が必要でP1ありL3、のインターフェースを変更することを想像してくださいL3。これらのライブラリを参照するプロジェクトP2P3ミックスに追加します。それらをすべて新しいインターフェイスに切り替え、すべてのテストを実行し、新しいソフトウェアを展開する余裕はありません。それでは、代替手段は何ですか?

  1. 新しいインターフェースを実装する L3
  2. プルリクエストをL3してレビューを待ちます
  3. 変更をマージする
  4. の新しいリリースを作成する L3
  5. の新しいリリースをP1参照することで機能の作業を開始し、機能のブランチにL3機能を実装しますP1
  6. プルリクエストを行い、これをレビューして、マージします

(私はちょうど私がスイッチに忘れたことに気づいたL1L2新しいリリースに。そしてそれはと並行して行われる必要があるので、私も、どこでこれを固執するかわかりませんP1...)

これは、この機能を実装するための退屈でエラーが発生しやすい非常に長いプロセスであり、独立したレビューが必要であり(レビューがはるかに困難になります)、スケーリングがまったく行われず、私たちがビジネスを停止する可能性がありますプロセスが行き詰まってしまい、何もできなくなります。

しかし、あまり多くのオーバーヘッドなしで新しいプロジェクトに新しい機能を実装できるプロセスを作成するために、どのように分岐とタグ付けを使用するのでしょうか?


1
ツールを変更しても、実行中のプロセスにあまり影響しないはずです。では、gitに切り替える前にこの問題にどのように対処していましたか?
バートヴァンインゲン

あまりにも多くのライブラリが依存している場合、既存のメソッドを壊すことなく、単に新しいメソッドをインターフェイスに追加することは可能ですか?通常、これは最良のアイデアではありませんが、少なくとも新しい機能を実装するために「実行」できるようになり、余裕がある場合は古いメソッドを適切に非推奨にすることができます。または、これらのインターフェイスは、そのような「パラレルインターフェイス」が機能するにはステートフルすぎますか?
Ixrec

1
@Ixrec:「これはgitのやり方ではない」と言われました。誰もが個々のプロジェクトに個々のリポジトリを使用しているので、私たちもそれを行うことが決定されました。
sbi

2
頻繁に並行して変更する必要がある場合、それらは別個のプロジェクトではないと主張します。「プロジェクト」間の境界には、常に何らかの下位互換性が保証されている必要があります。
Ixrec

1
@Ixrec:より多くのハードウェアを統合することは、コードをより多くのプラットフォームに移植することに似ています。これを行うほど、別のハードウェア/プラットフォームのために変更する必要が少なくなります。したがって、長期的にはコードは安定します。ただし、現時点では、市場に十分に長く滞在できるプロセスを見つける必要があります。
sbi

回答:


5

ここで明らかなことを言うようなものですが、言及する価値があるかもしれません。

通常、gitリポジトリは独立している傾向があるため、lib / projectごとに調整されます。プロジェクトを更新しますが、残りは気にしません。それに依存する他のプロジェクトは、適切と思われる場合はいつでもライブラリを更新するだけです。

ただし、ケースは相関コンポーネントに大きく依存しているようであるため、通常は1つの機能がそれらの多くに影響します。そして、全体をバンドルとしてパッケージ化する必要があります。機能/変更/バグを実装するには、多くの異なるライブラリ/プロジェクトを一度に適合させる必要があることが多いため、すべてを同じリポジトリに配置するのが理にかなっています。

これには強力な利点/欠点があります。

利点:

  • 追跡可能性:ブランチには、この機能/バグに関連するすべてのプロジェクト/ライブラリで変更されたすべてが表示されます。
  • バンドル:タグを選択するだけで、すべてのソースを正しく取得できます。

欠点:

  • マージ:...単一のプロジェクトでは既に難しい場合があります。さまざまなチームが共有ブランチで作業しているため、影響に備えて準備を整えてください。
  • 危険な「おっと」要因:ある従業員が何らかの間違いをしてリポジトリを台無しにした場合、すべてのプロジェクトとチームに影響を与える可能性があります。

価格にメリットがあるかどうかを知るのはあなた次第です。

編集:

次のように機能します。

  • 機能Xを実装する必要があります
  • ブランチを作成 feature_x
  • 関係するすべての開発者はこのブランチで作業し、おそらくプロジェクト/ライブラリに関連する専用ディレクトリで作業します
  • 終わったら、レビュー、テスト、パッケージ化、何でも
  • バックマスターでそれをマージ...、これは以来、その間にタフな一部であってもよいfeature_yし、feature_zあまりにも追加されている可能性があります。「クロスチーム」マージになります。これが重大な欠点である理由です。

記録のためだけに:ほとんどの場合、これは悪い考えであり、マージの欠点は通常、依存関係管理/適切な機能の追跡を通じて得られるものよりも大きいため、慎重に行う必要があると思います。


おかげで、私たちは現在これを実際に見ています。これに照らして理解できないのは、gitで分岐する方法です。SVNでは、分岐とは(リポジトリ内の)サブツリーを別の場所(リポジトリ内)にコピーすることを意味します。これにより、リポジトリ内の任意のサブツリーのブランチを簡単に作成できるため、そこに多くのプロジェクトがある場合は、それぞれを個別にブランチできます。gitにはこのようなものがありますか、それとも常にレポ全体をブランチすることしかできませんか?
-sbi

@sbi:リポジトリ全体を分岐します。異なるブランチのサブツリーで作業することはできません。これは、あなたの場合のポイントを打ち負かすでしょう。Gitは何も「コピー」しません。作業中のブランチの変更を追跡するだけです。
-dagnelies

そのため、1つのライブラリの機能ブランチを作成する誰かが、マージまたはリベース時に他のすべてのライブラリもマージする必要があります。これは本当の欠点です。(ところで、SVNも遅延コピーのみを行います。)
sbi

@sbi:編集
-dagnelies

1
まあ、現在私たちのほとんどは快適ではありません。:-/さらに、開発者がgitに適合する方法(およびgitへの移行を推進した)であっても、開発プロセスをgitに適合させる方法がわかりません。はぁ。物事がよりスムーズになり始めるまで、数ヶ月の厳しい月になるでしょう。とにかくありがとう、あなたのものはこれまでのところ最も/唯一の有用な答えです。
sbi

4

探しているソリューションは、gitサブモジュールと連携した依存関係管理ツールです

次のようなツール:

  • メイヴン
  • 作曲

これらのツールを使用して、プロジェクトの依存関係を定義できます。

サブモジュールは、少なくともバージョン> 2.xx以上であるか、互換性のあるバージョン範囲= 2.2。*または特定のバージョン<2.2.3未満であることを示すことができます

パッケージの1つの新しいバージョンをリリースするたびに、バージョン番号でタグを付けることができ、その方法で特定のバージョンのコードを他のすべてのプロジェクトに取り込むことができます


しかし、依存関係の管理は私たちの問題ではなく、これは解決されています。現在、多くのライブラリで定期的に変更を行っており、安定したプロジェクトリリースを維持しながら、新しいバージョンを作成するオーバーヘッドを最小限に抑える必要があります。あなたの答えは、これに対する解決策を提供していないようです。
-sbi

@sbiこれは、新しいバージョンを作成し、安定したプロジェクトリリースを維持するオーバーヘッドを管理します。プロジェクトxはプロジェクトyバージョン2.1.1に依存するように指示できるため、プロジェクトxに影響しないプロジェクトyの新しいバージョンを作成できます。
パトリック

繰り返しますが、依存関係の宣言は問題ではありません。すでにこれを行うことができます。問題は、複数のプロジェクト/ライブラリにまたがる変更を効率的に管理する方法です。あなたの答えはこれを説明できません。
sbi

@sbi:あなたの問題は何ですか?変更を行い、バージョンを上げ、必要に応じて依存関係を更新し、出来上がり。最初の投稿で説明したのは、典型的なMaven&Coです。もの。各ディストリビューションは、明確に定義されたバージョン管理されたライブラリに基づいています。どうすればより明確になりますか?
-dagnelies

@arnaud:(現在かなり一般的な)変更が3つ以上のレイヤーにまたがるようなプロセスの所要時間は、私たちを殺すでしょう。私の質問はそれを説明していると思いました。
sbi

0

サブモジュール

1つのコメントで示唆されているように、サブモジュールgitにトライする必要があります。

project P1が3つのサブモジュールを参照する場合L1L2およびL3は、実際に3つのリポジトリすべてに特定のコミットへの参照を保存します。これらは、そのプロジェクトの各ライブラリの作業バージョンです。

したがって、複数のプロジェクトで複数のサブモジュールを使用できます。プロジェクトが新しいバージョンを使用している間にP1、ライブラリの古いバージョンを参照する場合があります。L1P2

新しいバージョンを配信するとどうなりますL3か?

  • 新しいインターフェースを実装する L3
  • コミット、テスト、プル要求の作成、レビュー、マージ、...(これを避けることはできません)
  • 確保L2作品でL3、コミット...
  • L1新しいL2で動作するようにします...
  • P1すべてのライブラリの新しいバージョンで動作することを確認します。
    • の内部P1のローカル作業コピーL1L2およびL3、興味のある変更を取得します。
    • 変更git add L1 L2 L3をコミットし、モジュールへの新しい参照をコミットします
    • プルリクエストP1、テスト、レビュー、プルリクエスト、マージ...

方法論

これは、この機能を実装するための退屈でエラーが発生しやすい非常に長いプロセスであり、独立したレビューが必要であり(レビューがはるかに困難になります)、スケーリングがまったく行われず、私たちがビジネスを停止する可能性がありますプロセスが行き詰まってしまい、何もできなくなります。

はい、変更するため、独立したレビューが必要です。

  • 図書館
  • それに依存するライブラリ
  • 複数のライブラリに依存するプロジェクト

あなたががらくたを出すので、あなたは廃業するでしょうか?(実際にはそうではないかもしれません)。はいの場合、テストを実行して変更を確認する必要があります。

適切なgitツール(偶数gitk)を使用すると、各プロジェクトが使用しているライブラリのバージョンを簡単に確認でき、ニーズに応じてそれらを個別に更新できます。サブモジュールは状況に最適であり、プロセスを遅くすることはありません。

このプロセスの一部を自動化する方法を見つけることができるかもしれませんが、上記の手順のほとんどは人間の脳を必要とします。時間を短縮する最も効果的な方法は、ライブラリとプロジェクトを簡単に進化させることです。コードベースが新しい要件を適切に処理できる場合、コードレビューはより簡単になり、時間はほとんどかかりません。

(編集) 関連するコードレビューをグループ化することも役立ちます。すべての変更をコミットし、それらの変更を使用するすべてのライブラリとプロジェクトにそれらの変更が伝達されるまで待ってから、プル要求をまとめます(またはそれらを処理する前に)。最終的には、依存関係チェーン全体についてより大きなレビューを行うことになります。たぶん、これは各ローカルの変更が小さい場合に時間を節約するのに役立ちます。


依存関係の問題を解決する方法を説明し(前に述べたように、これを整理しました)、私たちが抱えている問題を否定します。なぜあなたも気にしますか?(FWIW、発電所を駆動するソフトウェアを作成します。クリーンで安全な徹底的にレビューされたコードが主要な機能です。)
sbi

@sbi分岐とタグ付けの特別な場合でない場合、サブモジュールとは何ですか?あなたは考えて、彼らはまた、依存関係を追跡するためのサブモジュールは、依存関係の管理に関するものです。しかし、もし望むなら、サブモジュールをタグで作り直してください、私は気にしません。私はあなたの問題を理解していません:レビューされたコードが主要な機能である場合、あなたはレビューのためにいくらかの時間をかけなければなりません。動揺することはありません。制約を課して、できるだけ速く進みます。
コアダンプ

レビューは私たちにとって非常に重要です。これが、問題(およびそのレビュー)が複数のリポジトリの複数の変更のために複数のレビューに分割されることを懸念する理由の1つです。さらに、1つの問題で私たちを死に追いやることで動揺したくありません。コードの作成と確認に時間を費やすことです。サブモジュールについて:これまでのところ、私が聞いた唯一のことは「気にしないでください、これはgitの方法ではありません」です。まあ、私たちの要件は非常にユニークであると思われるので、おそらくこの決定を再検討する必要があります
...-sbi

0

だから私が理解しているのは、L3インターフェイスを変更したいが、L3インターフェイスに依存する他のP2とP3をすぐに変更したいP1の場合です。これは、下位互換性の典型的なケースです。この下位互換性の保持に関する素晴らしい記事があります

これを解決する方法はいくつかあります。

  • 古いインターフェイスを拡張できる新しいインターフェイスを毎回作成する必要があります。

または

  • しばらくして古いインターフェイスを廃止する場合は、いくつかのバージョンのインターフェイスを使用し、すべての依存プロジェクトが移動したら古いインターフェイスを削除します。

1
いいえ、後方互換性はリリースブランチを通じて保証されており、私たちの問題ではありません。問題は、現在急速に変化しているコードベースに座っていることです。これは、インターフェイスが頻繁に変更される段階にあるにもかかわらず、ライブラリに分割したいと思っています。SVNでそのような獣を管理する方法は知っていますが、管理でdrれずにgitでそれを行う方法はわかりません。
sbi

0

私があなたの問題を正しく理解している場合:

  • あなたは4つの相互関連モジュール、P1とL1からL3を持っています
  • 最終的にL1からL3に影響するP1に変更を加える必要があります
  • 4つすべてを一緒に変更する必要がある場合、プロセスの失敗としてカウントされます。
  • それらをすべて1つずつ変更する必要がある場合、プロセスの失敗としてカウントされます。
  • 変更を加える必要があるチャンクを事前に識別する必要がある場合、プロセスの失敗としてカウントされます。

目標は、P1とL1を一度に実行し、1か月後に別のL2とL3を実行できるようにすることです。

Javaの世界では、これは簡単であり、おそらくデフォルトの動作方法です。

  • 関連する分岐の使用なしですべてが1つのリポジトリに格納されます
  • モジュールは、すべて同じディレクトリツリーにあるという事実ではなく、バージョン番号に基づいてmavenによってコンパイル+リンクされます。

したがって、L3のローカルディスクに、ディスク上の他のディレクトリにあるP1のコピーに対してコンパイルした場合にコンパイルされないコードを保持できます。幸いなことにそうではありません。物語のコンパイル/リンクはソースコードではなくコンパイルされたjarファイルに対して行われるため、Javaはこれを簡単に行うことができます。

私は、C / C ++の世界でこの問題に対する既存の広く使用されている解決策を知らないので、言語を切り替えたいとは思わないでしょう。しかし、同等のことをするmakeファイルで何かを簡単にハッキングできます。

  • インストールされたライブラリ+埋め込みバージョン番号を持つ既知のディレクトリへのヘッダー
  • 適切なバージョン番号のディレクトリへのモジュールごとのコンパイラパスの変更

ほとんどのC開発者は、もしそうなら奇妙にあなたを見ますが、あなたはmavenC / C ++サポートを使用することさえできます...


「4つすべてを一緒に変更する必要がある場合、プロセスの失敗としてカウントされます」。実際にはそうではありません。実際、これはまさにSVNを使用して行ったことです。
sbi

その場合、すべてのプロジェクトをリポジトリに置くだけで問題はないと思います。
-soru

現在、ライブラリを2つのリポジトリのみに配置することを評価しています。それはまだ1つ以上ですが、「すべてのプロジェクトに1つ」よりはるかに少なく、ライブラリは2つのグループに非常にうまく分割できます。ご意見ありがとうございます!
sbi

PS:「言語を切り替えたいとは思わないでしょう。」これは埋め込みのものです。:)
sbi

-1

単純な解決策があります。リポジトリ全体でリリースブランチをカットし、すべての修正をアクティブに出荷されたすべてのリリースにマージします(gitでは簡単にクリアできるはずです)。

すべての選択肢は、時間の経過とともにプロジェクトの成長とともに恐ろしい混乱を生み出します。


詳しく説明してもらえますか?あなたが何を提案しているのか分かりません。
sbi

明確なケースでは、ブランチポイントをベースブランチおよびタイムスタンプとして定義します。次の階層があります。ベースブランチ->リリース開発ブランチ->プライベート開発ブランチ。すべての開発はプライベートブランチで行われ、その後、階層の下にマージされます。顧客リリースブランチは、リリース開発ブランチから切り離されています。私はgitにそれほど精通していませんが、無料のソース管理システムの中で明確なケースに最も近いようです。
zzz777

私の質問を注意深く読んで、リポジトリ間の変更の伝播に伴うオーバーヘッドに問題があることを示したはずです。これはあなたの答えとは何の関係もありません。
sbi

@sbiご質問を誤解して申し訳ありません。そして、遅かれ早かれ恐ろしい混乱に直面することを恐れています。
zzz777
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.