Gitで「分岐は無料」とはどういう意味ですか?
他のバージョン管理システムと比較してGitが言及されているときはいつでもこれをよく耳にします。
私は他の人( [〜#〜] svn [〜#〜] など)に対処する機会(?)を持っていなかったので、他の人に「高価」に分岐する方法は?
「ブランチはgitでfreeである」という主張は、それ自体「フリー」ではないため、事実を単純化したものです。内面を見ると、より正確な主張は、分岐がredonkulously cheapであると言うことです。なぜなら、 ブランチは基本的にコミットへの参照です 。ここで「安上がり」とは、オーバーヘッドが少ないほど安いと定義します。
Gitのオーバーヘッドの種類を調べて、Gitがなぜ「安い」のかを詳しく見てみましょう。
Gitリポジトリ.git
は、ほとんどがgitが使用するメタデータを含むファイルを含むディレクトリで構成されています。あなたがgitでブランチを作成するときはいつでも、例えばgit branch {name_of_branch}
、いくつかのことが起こります:
.git/refs/heads/{name_of_branch}
.git/logs/refs/heads/{name_of_branch}
基本的にはこれで、いくつかのテキストファイルが作成されます。参照をテキストファイルとして開くと、内容はブランチが指しているコミットのid-shaになります。 ブランチは別の種類のオブジェクトであるため、コミットを行う必要がないことに注意してください。ブランチとコミットはどちらもgitの「一流の市民」であり、1つの方法はブランチとコミットの関係を構成ではなく集合体として考えることです。ブランチを削除しても、コミットは「ぶら下がり」のまま存在します。誤ってブランチを削除した場合は、常に git-lost-found
または git-fsck --lost-found
でコミットを見つけて、sha-idにブランチを作成してみてください。左にぶら下がっている(そしてgitがまだガベージコレクションを実行していない限り)。
では、gitはどのブランチに取り組んでいるのかをどのように追跡するのでしょうか?答えは.git/HEAD
ファイルです。master
ブランチを使用している場合、このファイルは次のようになります。
ref: refs/heads/master
ブランチを切り替えると、.git/HEAD
ファイルの参照が変更され、コミットで定義された内容でワークスペースの内容が変更されます。
InSubversion、ブランチはリポジトリ内の仮想ディレクトリ 。したがって、ブランチを作成する最も簡単な方法は、ワンライナーsvn copy {trunk-url} {branch-url} -m "Branched it!"
を使用してリモートでブランチすることです。 SVNが行うことは次のとおりです。
trunk
、ターゲットディレクトリに、ローカルでそのコピーを作成することは、ファイルがコピーされてシンボリックリンクされる線形時間操作であるため、サーバー上でリモートでこのアクションを実行する必要があります。これは非常に遅い操作ですが、サーバーで実行するのは一定時間の操作です。サーバーで分岐を実行する場合でも、gitが分岐しない場合にSubversionでcommitが必要になることに注意してください。これは重要な違いです。これは、SVNをGitよりもわずかに安くするオーバーヘッドの一種です。
SVNでブランチを切り替える 、つまりsvn switch
のコマンドは、実際にはsvn update
を偽装しています。仮想ディレクトリの概念のおかげで、コマンドはgitよりもsvnの方が少し柔軟です。ワークスペースのサブディレクトリは、別のリポジトリURLをミラーリングするように切り替えることができます。最も近いのは git-submodule
を使用することですが、これを使用すると、意味的に分岐とはかなり異なります。残念ながら、これはミラーリングしているリモートURLのすべてのワークスペースディレクトリをチェックする必要があるため、GitよりもSVNでの切り替えが少し遅くなる設計上の決定でもあります。私の経験では、GitはSVNよりもブランチを切り替える方が速いです。
SVNはファイルをコピーするため、SVNの分岐にはコストがかかり、常に公開する必要があります。 gitでは、上で説明したように、ブランチは「単なる参照」であり、ローカルリポジトリに保持して、自由に公開できます。しかし、私の経験では、SVNは、たとえば、 ClearCase。
SVNが分散化されていないのは残念なことです。複数のリポジトリを一部のソースリポジトリにミラーリングすることができますが、SVNにはコミットの一意の識別子がないため、異なる変更を複数のSVNリポジトリで同期することはできません(gitには、コミットの内容に基づくハッシュされた識別子があります)。私が個人的にSVN経由でgitを使い始めた理由は、 リポジトリの開始はgitで非常に簡単で安価です だからです。ソフトウェア構成管理の概念では、プロジェクト(クローン、フォーク、ワークスペースなど)の異なるコピーはそれぞれ「ブランチ」であり、この用語を考えると、SVNで新しいコピーを作成することはGitほど安価ではありません。 「組み込み」のブランチ。
別の例として、Mercurialでは、分岐はDVCSとは少し異なり、名前付き分岐の作成/破棄には個別のコミットが必要でした。 Mercurial開発者は開発の後半に実装 bookmarks gitの同じ分岐モデルを模倣していますが、heads
はtips
と呼ばれ、branches
は代わりにbookmarks
ですMercurial用語で。
ブランチの実際のコストはそれをマージすることです。 Gitは、これを他のソース管理システムよりも簡単にします。スタックオーバーフローの質問を参照してくださいSVNよりもGitでマージする方法および/または理由はなぜですか?。
Gitでは、ブランチはローカルリポジトリへのコミットへの参照にすぎません。作成は非常に安価で、ネットワークはまったくありません。かなり自由ではありませんが(コマンドを入力する必要があります)、近くにあります。
SVNでの分岐はそれほど高価ではありません。これは単なるコピーであり、非常に安価なコミットです。 SVNには中央リポジトリモデルがあるため、ネットワークアクセスですが、恐ろしいものではありません。
一方、由緒あるCVSでは、分岐は非常に高価です。基本的に、CVSブランチにはタグの追加が含まれますが、CVSでは、すべてのファイルに影響を与える必要があることを意味します。各ファイルは、新しいタグを含むように書き直されます。それは恐ろしく高価です。そして、もしあなたのリポジトリが大きければ、それはまた恐ろしく遅いです。実際、大規模なプロジェクトの場合、遅いので、可能であればブランチを作成しない人もいます。
SVNの分岐はGitと同じくらい自由です。ブランチがどこから始まるかを示すのは、ほんの少しのハウスキーピングデータであり、保存されているファイルはまったく変更されません。 SVNの「コピー」は、シンボリックリンクをUnixディレクトリに追加するようなものです。作業コピーの変更をコミットするまで、SVNブランチはネットワークトリップを必要としないことに注意してください(ただし、ある時点でローカル以外をコミットしないと、SCMを使用することはあまりありません)。
Gitブランチには、内部でタグを追加するなど、ハウスキーピングも含まれることに注意してください。コミットするときに、どこかに保存する必要があります。それはまったく大したことではありません、それがそれが「無料」と呼ばれる理由です。
some古いバージョン管理システムでは、ブランチはその時点でコードの完全なコピーだったため、これは「無料」です(このコンテキストでは「無料」は本当に迅速かつ簡単で、スペースを占有しないことを意味します)。そのため、ブランチは多くのスペースを占有し、ソフトウェアのさまざまな完全に完全なバージョンが多数存在することになり、管理が容易になりました。それ以外の場合は、コードの完全なコピーではありませんでしたが、すべてのファイルをタグ用に変更する必要があったため、時間がかかり、面倒でした(「コストがかかる」)。
「無料/安価/高額」のもう1つの側面は、分岐の下流への影響に対処するための開発者リソースの観点からのコストと関係しています。つまり、ブランチからの変更をマージするプロセス。
そして、ここでは、GitやMercurialなどのDVCSシステムでブランチをマージすることは、古いシステムよりも簡単です。DVCSシステムは、グラフ内のバージョンの履歴を追跡する作業がはるかに優れているためです。つまり、以前の分岐でマージが発生した場合。これにより、マージがより正確になり、不必要な競合が減少します。そして、関係する開発者にとって主観的にマージが「より簡単」または「あまり怖くない」になります。