組み込みデバイスやその他の奇妙な世界向けに開発する場合、ビルドプロセスに、それらの非常に特定のバージョンを使用して、複数の専用バイナリが含まれる可能性が非常に高くなります。だから問題は、それらはあなたのソース管理の一部ですか?私のオフィスでは、「ソース管理からのチェックアウトには、コードをコンパイルするために必要なすべてのものが含まれている」という規則に従っており、これがいくつかの重大な議論につながっています。
これに対して私が目にする主な議論は、ソース管理DBの肥大化、バイナリファイルの差分の欠如です( 件名に関する以前の質問を参照) 。これは、以前の開発者が意図した正確な環境があることを確認し、ビルドし、適切なファイル(特定のバージョン以上のもの)を探し出さずに確認する機能に反しています。
VERSION CONTROL(誤称:ソース管理)の考え方は、履歴をロールバックし、変更の影響を回復し、変更とその理由を確認することです。これはさまざまな要件であり、一部にはバイナリのものが必要であり、一部には必要ありません。
例:組み込みファームウェアの作業では、通常、完全なツールチェーンが必要になります。多額の費用がかかる専用コンパイラーか、gccのバージョンのいずれかです。出荷用の実行可能ファイルを取得するには、ソースだけでなくツールチェーンも必要です。
ツールチェーンをバージョン管理にチェックインするのは面倒です。diffユーティリティは恐ろしいですが(あるとしても)、代替手段はありません。 5年後にコードを調べて何が行われるかを理解するためにツールチェーンを維持したい場合は、選択肢がない:バージョン管理下のツールチェーンも必要です。
長年にわたって、これを行う最も簡単な方法は、インストールCDのZipまたはISOイメージを作成し、これをチェックインすることです。チェックインコメントは、ツールチェーンの特定のメーカーのバージョン番号である必要があります。 gccまたは同様の場合は、使用しているすべてのものを大きなZipにバンドルして、同じようにします。
私が行った最も極端なケースはWindows XP Embeddedで、「ツールチェーン」は実行中のWindows XP VMであり、SQL Serverと構成ファイルのスタックが含まれていました。何百ものパッチファイルと一緒に。全ロットをインストールして最新の状態にするのに、約2〜3日かかりました。後世のためにそれを維持することは、VM全体をバージョン管理にチェックインすることを意味しました。仮想ディスクが約6 x 2GBのイメージで構成されているのを見ると、実際にはかなりうまくいきました。上に聞こえますが、それは私の後に来て、それを使用しなければならなかった人にとって非常に簡単になりました-5年後。
概要:バージョン管理はツールです。それを効果的に使用し、言葉の意味などにこだわらないでください。それよりも「ソースコントロール」と呼ばないでください。
Neal Fordは The Productive Programmer で、ソース管理にバイナリを保持する必要があるべきだと主張しています。
なぜバイナリを保持するのですか?今日のプロジェクトは、一連の外部ツールとライブラリに依存しています。一般的なロギングフレームワーク(Log4JやLog4Netなど)の1つを使用しているとしましょう。 ビルドプロセスの一部としてそのロギングライブラリのバイナリをビルドしない場合は、バージョン管理で保持する必要があります。これにより、続行できます。問題のフレームワークまたはライブラリが消えた場合でも(または、新しいバージョンで重大な変更が発生した場合でも)ソフトウェアをビルドするため。 常にバージョン管理でソフトウェアを構築するために必要な全体を維持します(オペレーティングシステムを除いて、仮想化でも可能です。「仮想化の使用、この章の後半)。バイナリのバージョン管理と共有ネットワークドライブの両方を維持することで、バイナリの保持を最適化できます。そうすれば、1時間ごとに対処する必要はありませんが、1年後に何かを再構築する必要がある場合に備えて保存されます。何かを再構築する必要があるかどうかはわかりません。機能するまでビルドし、その後は忘れます。 2年前から何かを再構築する必要があり、すべてのパーツが揃っていないことに気づくのはパニックを引き起こします。
私はこれ以上同意できませんでした。これは間違いなく、VCSが設計されていないタスク(バイナリを維持する)のためにVCSを覆すことになりますが、利点は潜在的な欠点を上回ると思います。ただし、後で説明するように、バイナリをVCSに保持することは実際的な解決策ではない場合があるため、マップされたネットワークドライブに保持するなど、他のオプションを検討する必要があります。
バイナリが大きすぎない場合は、VCSで確実に保持します。バイナリはおそらく小さいので、これはあなたの場合にはさらに当てはまるようですおよび非常に特定のバージョンで作業します。また、さまざまな理由により、見つけにくい場合もあります(作成者がWebサイトをシャットダウンしたか、必要なバージョンがダウンロード用にリストされなくなった)。可能性は低いですが、数年後に何が起こるかは決してわかりません。
数年前、グラフィックライブラリ(dllファイル)を使用してゲームに取り組んでいたときに、この本を読んでほしいと思います。開発をしばらく中断しましたが、続行したいのですが、プロジェクトが停止したため、dllを再度見つけることができませんでした。
原則として、「ソース管理に組み込むために必要なすべてのものをチェックする」キャンプには感謝しますが、依存関係管理は、ここ数年でMaven、Ivy、NuGetなどのツールを使用してかなり進化しました。
また、実際には、バイナリをチェックインして、多くの不快な副作用を引き起こしています。たとえば、Git/Mercurialは実際には調整されていません。また、バイナリを含むブランチをマージする場合、SubversionとPerforceは問題を引き起こす可能性があります。
依存関係管理ソリューションでは、プロジェクトのソース管理ファイルで、プロジェクトが依存するパッケージ名とバージョンを指定します。ほとんどすべての依存関係管理ツールでは、何らかのバージョン管理と命名規則に従って、依存関係のプライベートリポジトリを作成できます。ビルドを実行すると、依存関係管理ツールは、承認されたソースのリストからすべてのオープンソースとプロプライエタリの依存関係を解決し、それらをローカルキャッシュに格納します。次に同じバージョンの依存関係を使用してビルドするときには、すべてがすでに存在しており、はるかに高速になります。
その後、プライベートリポジトリを従来のファイルシステムバックアップツールでバックアップできます。
これにより、ソースツリーから大量のバイナリがプルされているときに経験したような速度低下を回避し、リポジトリに多数のdiffが困難なファイルが含まれるのを防ぎます。名前とバージョン番号による特定の依存関係の場所は1つだけなので、対処するマージの競合は発生せず、ローカルファイルシステムのキャッシュにより、ローカルコピーが変更されたかどうかを評価するコストに対処する必要がありません。更新をプルします。
ソース管理はソース用です。ソースは、他のものから構築できないものです。ソースと見なされる一部のファイルは、バイナリです。
私のVCSには多数のバイナリがチェックインされていますが、それぞれが私が作成しておらず、メンテナンスもしていない製品からのリリースの単位です。これはGNU ccRTPのようなものかもしれません。これは圧縮されたtarballとしてリリースされます。そのtarballは私のソースであり、完成した製品(a MakefileとRPM仕様(私の場合)を1つの自動化されたステップで実行します。ccRTPの新しいバージョンがある場合、新しいtarballを変更されたソースとして扱います。チェックアウトされたコピーに入れられ、ビルドされ、テストされ、コミットされます。 VCS。ソースに同梱されていない市販の製品(コンパイラー、ライブラリーなど)でも同じことを行いましたが、同じように機能します。unpack-configure-compile-packageの代わりに、それは単にunpack-packageです。ナイトリービルドを実行するソフトウェアは、make
を実行して完成品を取得できる限り、何も知りません。
ほとんどのVCSには、人間が読める形式のソースを扱いやすく、保存を効率化する機能がありますが、バイナリに適していないというのは、バイナリが挿入された後に無邪気に戻ってきた場合、実際には当てはまりません。 VCSがバイナリを内部的に処理する方法は、作成者が差分のみを保存することは努力する価値があると考えたかどうかに完全に依存します。個人的には、ccRTPディストリビューションのフルコピーを600Kで保存することは、他のすべてのソースと一緒にそのバージョンにタグを付ける機能で補われる以上のものだと思います。
これは、先ほどの「リポジトリ内のjar」の問題を思い出しますJavaでした。人々はJavaアプリを使用して依存関係をプッシュするために使用されました(バイナリjarファイル)リポジトリに。「ワンクリック」ビルドシステムとディスクスペースが安くて、誰も気にしないので、誰もがこれに満足しました。その後、Mavenに来て、バイナリ残骸をすべて削除し、ローカルキャッシュのみでリポジトリはまだBullet-Proビルドを維持しています。「ワンクリック」ビルドシステムはまだありますが、ソース管理はそこで意味のないバイナリファイルをシャッフルする必要はありません。
つまり、ソースコントロールからバイナリファイルを取得できますが、ビルド時にそれらを取得するには、ビルドシステムを微調整する必要があります。 (Mavenのような)専用のソフトウェアがなければ、これは単にそれらを取得するための多大な労力になる可能性があります。
ソース管理はsourcesを保持します。特定のバイナリBLOBがソースから再構築できる場合、それはソースではないため、ソースコードリポジトリに配置しないでください。ソースコントロールでは、再作成不可能なblobのみを使用する必要があります。
あなたは通常anotherを持っています リポジトリ ソースの時間をかけて構築したバイナリblobのネットワークフォルダー。これらは顧客に展開するか、プロジェクトで使用できます(毎回すべてを最初から構築するのではなく)。
だから、それがソースであればそれを入れてください。そうでない場合はしないでください。
目標は、最新のコードを取得して、何もインストール/セットアップすることなくビルドできるようにすることです(つまり、「シングルクリック」ビルド)。
多くの場所で私は依存関係のバイナリをチェックインしました。その他の場合、これは、ビルドスクリプトが依存関係を自動的にダウンロードして取得することを意味します。
この件については、Derek Greerによる このブログ投稿 を参照してください。
2つの異なるビルド段階のプロジェクトで作業しています
「メインプログラムのビルド」では、数千のソースコードテキストファイルと比較して、ほんの少しのバイナリが必要なため、バイナリがリポジトリにチェックインされます。これは正常に動作します。
インストーラーのビルドには、多くのサードパーティコンポーネントが必要です(Adobe Readerなど、一部はインストールCDにコピーされるだけです)。それらをリポジトリに入れているわけではありません。代わりに、これらのコンポーネントはネットワークドライブ(古いバージョンでも)に常駐し、ビルドスクリプトはそれらを適切な場所にコピーします。もちろん、再現可能なビルドを作成するには、サードパーティのコンポーネントが保存されているフォルダを変更しないように注意する必要があります。
どちらの方法も適切に機能し、「ソース管理からのチェックアウトには、コードをコンパイルするために必要なすべてのものが含まれている」という要件を満たします。
特定のバージョンの製品を将来再構築するために必要なすべてのものを保持する必要があります。
ただし、すべてをソース管理に保持する必要はありません。
ある会社は凍結したサーバーラックを維持していました(OSはその特定のハードウェアでのみ実行され、ツールチェーンはそのOSでのみ実行され、ソースはそのツールチェーンに依存していたため)。これをソース管理にチェックインできません。
ビルドの要件を分割する必要がある場合、2つのバージョン管理システムの同期を保つという会計上の問題があります。例えばこのクローゼットのハードウェアボックス、またはVMまたはこの保存されたバックアップボリュームのバイナリ、このSVNソースコードのリビジョンなどを使用します。これは、単一のソース管理システムを使用するよりも面倒ですが、解決可能です。 。
バイナリをSCMにチェックインするのは非常に混乱しています。私は非常に複雑なプロジェクトを実行していました。これには、サードパートライブラリへの依存関係がたくさんあります。私たちが採用した原則:
これはかなりうまくいきます。ソースコードをコンパイルできる各外部ライブラリのバージョンに関する設定ファイルがあります。この構成ファイルはSCMにチェックインされるため、ソースコードが進化するにつれて進化します。このアプローチを適用することにより、外部ライブラリのバージョンをいじり回すことなく、ビルドを正確に再現できます。
個人的に、哲学的に、私はソースコントロールに、ファイルの内容ではなく、大きなバイナリファイル(小さなバイナリリソースは問題ありません)へのチェックインpointersをチェックさせる傾向があります。このポインタには、バイナリファイルの内容のハッシュが含まれます。
バイナリファイル自体はソース管理によって管理されません。それはある種のライブラリに格納され、ポインタ、または具体的にはハッシュを使用して取得できます。
Git LFSとgit annexはそれを行いますが、バイナリファイルもある程度管理しようとします。私は彼らにそうしたくないのです。私はGitにチェックサムのみを保存し、バイナリファイルが変更されたかどうかを通知したいのですが、それらを管理したり保存したりしたくありません。自分でやりたい。
Gitは中小規模のバイナリファイルを処理できると思いますが、それが大きなバイナリファイルを管理するための適切なツールかどうかはわかりません。