12

githubでフォークが行われるとどうなるのだろうと思っています。

たとえば、プロジェクトをフォークすると、そのすべてのコードのコピーが github サーバーに作成されますか?それとも単にリンクを作成するだけですか?

別の質問: git では、同じファイルを追加するとすべてのファイルがハッシュされるため、ハッシュが既にシステムに存在するため、ファイルの内容を再度保存する必要はありません。正しいですか?

githubってこんなもん?したがって、別のユーザーとまったく同じコードをアップロードした場合、github gits を実行すると、同じハッシュを持つため、基本的にそのファイルへのリンクが作成されますか、それともすべてのコンテンツを個別に保存しますか?

どんな啓発も素晴らしいでしょう、ありがとう!

4

3 に答える 3

6

github.comは git とまったく同じセマンティクスですが、Web ベースの GUI インターフェイスがラップされています。

ストレージ: 「Git はファイルの各リビジョンを一意の BLOB オブジェクトとして保存します」
したがって、各ファイルは一意に保存されますが、SHA-1 ハッシュを使用してファイル間の変更を判断します。

github に関して言えば、フォークは基本的にクローンです。これは、新しいフォークがサーバー上のストレージの新しい領域であり、その ORIGIN への参照があることを意味します。git は本質的にリモートを追跡できるため、2 つの間にリンクを設定することは決してありません。各フォークはアップストリームを認識しています。

「たまたま別のユーザーとまったく同じコードをアップロードした場合」と言うとき、「アップロード」という用語は「git」の意味で少しあいまいです。同じリポジトリで作業していて、git で同じファイルをコミットすることさえ許可されている場合、それは異なるものであり、そのリビジョンがチェックインされたことを意味します。しかし、別のレポのクローン/フォークで作業することを意味する場合、同じ状況になりますが、ファイルシステム上で他のレポへのリンクは作成されません。

github が内部システムの内部でどのような最適化を行っているかについて、詳しい知識があるとは言えません。ディスク容量を節約するために中間のカスタム操作を行っている可能性があります。しかし、実際には、期待される git セマンティクスの下で常に動作する必要があるため、彼らが行うことはすべて透過的であり、あまり重要ではありません。

github の開発者は、独自の git ワークフローを内部でどのように行っているかについてのブログ投稿を書きました。彼らがサービスの実際のワークフローをどのように管理するかについてのあなたの質問とは関係ありませんが、結論からのこの引用はかなり有益だと思います:

Git 自体を理解するのは非常に複雑です。Git で使用するワークフローを必要以上に複雑にすると、毎日の精神的な負担が増えるだけです。私は常に、チームで機能する最も単純なシステムを使用し、それが機能しなくなるまでそれを行い、絶対に必要な場合にのみ複雑さを追加することをお勧めします.

私がそれから学んだことは、彼らは git 自体がいかに複雑であるかを認識しているので、ほとんどの場合、git をラップしてサービスを提供するために可能な限り軽いタッチを取り、git がネイティブで最も得意とすることを実行させます。

于 2012-08-15T18:24:33.930 に答える
2

GitHub が正確にどのように行っているかはわかりませんが、可能な方法は次のとおりです。git がデータを保存する方法についてある程度の知識が必要です。

簡単に言うと、リポジトリはデータベースを共有objectsできますが、それぞれに独自の参照があります。
概念実証のためにローカルでシミュレートすることもできます。

ベアレポのディレクトリ (ベア.git/でない場合はサブディレクトリ) には、レポが機能するための最低限のものが 3 つあります。

  • objects/すべてのオブジェクト (コミット、ツリー、ブロブなど) を格納するサブディレクトリ。それらは、オブジェクトのハッシュと同じ名前のファイルとして個別に保存されるか、ファイルに保存され.packます。
  • 内容が参照するオブジェクトのハッシュであるrefs/ような単純なファイルを格納するサブディレクトリ。refs/heads/master
  • HEAD現在のコミットが何であるかを示すファイル。その値は、生のハッシュ (デタッチされたヘッドに対応する、つまり、名前付きブランチにいない) または実際のハッシュが見つかる ref へのテキスト リンク (たとえばref: refs/heads/master、ブランチにいることを意味しますmaster)のいずれかです。

誰かがオリジナルの (フォークではない) リポジトリorigを Github に作成したとします。
シミュレートするために、ローカルで行います

$ git init --bare github_orig

上記がGithubサーバーで発生すると想像します。これで、空の github リポジトリができました。次に、自分の PC から github リポジトリのクローンを作成するとします。

$ git clone github_orig local_orig

もちろん、実生活では代わりにgithub_origを使用しますhttps://github...。これで、github リポジトリのクローンが作成されましたlocal_orig

$ cd local_orig/
$ echo zzz > file
$ git add file
$ git commit -m initial
$ git push
$ cd ..

このdirgithub_origの後、プッシュされたコミット オブジェクト、1 つの blob オブジェクト、および 1 つのツリー オブジェクトが含まれます。ファイルにはコミット ハッシュが含まれます。objectfilerefs/heads/master

では、誰かがForkボタンを押したときに何が起こるかを想像してみましょう。git リポジトリを作成しますが、手動で行います。

$ mkdir github_fork
$ cd github_fork/
$ cp ../github_orig/HEAD .
$ cp -r ../github_orig/refs .
$ ln -s ../github_orig/objects
$ cd ..

andをコピー していますが、 のシンボリック リンクを作成していることに注意してください。ご覧のとおり、フォークの作成は非常に安価です。数十のブランチがある場合でも、それぞれは単純な 16 進数のハッシュ (40 バイト) を含むディレクトリ内の単なるファイルです。元のオブジェクト ディレクトリにリンクするだけなので、何もコピーしません。HEADrefsobjectsrefs/headsobjects

ここで、ユーザーがフォークを作成し、フォークされたリポジトリをローカルで複製することをシミュレートします。

$ git clone github_fork local_fork
$ cd local_fork
$ # ls
.git/  file

objectsクローン元のリポジトリには独自のリポジトリはありませんが、元のリポジトリのリポジトリにリンクされていますが、クローンが正常に作成されたことがわかります。
これで、forking ユーザーはブランチを作成し、コミットしてから、それらを にプッシュできますgithub_fork。オブジェクトは、 !objectsと同じディレクトリにプッシュされます。github_origただしrefs、 とHEADは変更され、 のものとは一致しなくなりgithub_origます。

つまり、同じフォーク ツリーに属するすべてのリポジトリは共通のオブジェクト プールを共有し、各リポジトリには独自の参照が含まれているということです。自分のフォークされたリポジトリにコミットをプッシュする人は誰でも、自分の参照を変更しますが、オブジェクトを共有プールに入れます。

もちろん、実際に使用できるようにするには、さらにいくつかのことに注意する必要があります。最も重要なことは、git ガベージ コレクターは、それが呼び出されるリポジトリがすべての参照を認識していない限り、呼び出されてはならないということです。そうしないと、その参照からは到達できないが、他のリポジトリの参照からは到達できる共有プール内のオブジェクトが破棄される可能性があります。

于 2014-10-24T14:32:40.370 に答える