2012-08-15 11 views
7

githubでフォークが実行されたときに何が起こるのか不思議です。Githubフォークの説明とファイルの格納方法

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

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

githubはこのようですか?だから、同じコードを別のユーザーと同じようにアップロードした場合、githubを使うと同じファイルへのリンクが作成されるだけです。同じハッシュを持つことになります。

いずれかの啓発は素晴らしいでしょう、ありがとう!

答えて

4

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

Storage:「Gitは格納一意Blobオブジェクトとしてファイルの各リビジョン」
だから各ファイルが一意に格納され、それはファイルへのファイルの変更を決定するために、SHA-1ハッシュを使用します。

githubに関しては、フォークは本質的にクローンです。つまり、新しいフォークは、サーバー上の新しいストレージ領域で、そのORIGINを参照します。 gitは本質的にリモコンを追跡できるので、決して2つの間のリンクを設定しません。各フォークは上流を知っています。

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

githubが内部システム上でどのような最適化を行っているかについての詳しい知識はありません。ディスクスペースを節約するために、おそらく中間のカスタム操作を行っている可能性があります。しかし、彼らがやろうとしていることは、あなたにとって透過的で、大したことではないでしょう。なぜなら、効果的なgitセマンティクスの下では常に効果的に動作するべきだからです。

デベロッパーのgithub wrote a blog postは、内部的に独自のgitワークフローを実行しています。それは彼らがサービスの実際のワークフローを管理する方法についてご質問とは関係ありませんが、私は結論から、この引用はかなり有益だと思う:

Gitリポジトリ自体が理解することはかなり複雑で、ワークフロー を作ります必要以上に複雑なものを使うのは、皆さんの日に精神的なオーバーヘッドを追加するだけです。私はいつも あなたのチームのために働く可能性のある最もシンプルなシステムを使用して を使用して、それがもはや機能しなくなるまで、そして複雑さを追加するまで、 が絶対必要です。

私はそれから離れて、どのように複雑なgitがそれ自身であるかを認識しているので、サービスを提供するためにそれらを包み込むことができる最も軽いタッチをとる可能性が最も高く、 。

+1

githubはフォークの作成中にハードリンクのような何らかの最適化を使用する可能性がありますが、すべての実用的な目的でgithubサーバー自体の単なるクローンです。 –

+0

@ NoufalIbrahim:はい。フォークがファイルのリビジョンを実際にコミットするまでディスクスペースを節約するために内部最適化を行うように努力することは間違いありません。しかし、それは実際にユーザーには透過的です。しかし、良い点。 – jdi

+0

@ NoufalIbrahim:私たちが知っているように、上流のレポが新しいコミットを受け取ったとき、フォークには何の影響も与えないので、それはもっと複雑だと思います。それらは個別に下流のフェッチを担当します。 – jdi

1

私はGitHubには、それを行う方法を正確に知っているが、ここで可能な方法ではありません。 gitがデータを格納する方法の知識が必要です。

簡単な答えは、repos can shareobjectsデータベースですが、それぞれには独自の参照があります。
概念実証のためにローカルでシミュレーションすることもできます。全店舗

  • objects/サブディレクトリ、:裸のレポのディレクトリで

    が動作するレポのために最低限の3つのものがある(または.git/サブディレクトリにそれは裸ではない場合)オブジェクト(コミット、ツリー、ブロブなど)。それらは、オブジェクトのハッシュと同じ名前を持つファイルとして、または.packファイルに個別に格納されます。 refs/heads/masterその内容のような、単純なファイルを格納する
  • refs/サブディレクトリには、それが参照するオブジェクトのハッシュです。
  • HEADファイル(現在のコミットは何ですか)。私たちはある意味します - その値は、生のハッシュ(私たちはどんな名前の枝に含まれていない、つまり切り離さヘッドに相当)または、例えばref: refs/heads/masterの実際のハッシュを見つけることができREF(へのテキストリンクのいずれかでありますブランチmaster

Githubで元の(フォークではない)レポorigを作成したとしましょう。
は、ローカル我々は上記のGitHubのサーバで起こることを想像

$ git init --bare github_orig 

を行い、シミュレートします。今は空のgithubリポジトリがあります。我々はhttps://github...を使用する実際の生活の中ではなく、github_origもちろん

$ git clone github_orig local_orig 

:その後、我々は我々自身のPCから、我々はgithubのレポのクローンを作成することを想像してみてください。今我々はlocal_origにgithubレポをクローンしました。このgithub_origobject dirの後

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

、オブジェクトをコミットfileし、一本の木のオブジェクトに対して1つのBLOBオブジェクトを、当社のプッシュが含まれます。 refs/heads/masterファイルにはコミットハッシュが含まれます。

は今、誰かがForkボタンを押したときの画像は何が起こっていることができましょう。我々HEADrefsをコピー

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

お知らせが、我々はobjectsためシンボリックリンクにします 私たちは手でGitのレポが、を作成します。我々が見ることができるようにフォークは非常に安いです。たとえ数十の分岐を持っていても、それぞれが単純な16進ハッシュ(40バイト)を含むrefs/headsディレクトリのファイルに過ぎません。 objectsの場合、元のオブジェクトディレクトリにのみリンクします。何もコピーしません!私たちはからクローンレポには独自のobjectsが、リンクを持っていませんが

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

我々は、我々がクローニングに成功していることがわかります。

は、今、私たちは、ユーザがクローンローカルフォークレポ、フォークを作ることをシミュレート元のレポのそれに。
分岐してコミットし、github_forkにプッシュすることができます。オブジェクトはobjectsディレクトリにプッシュされます。このディレクトリはgithub_origと同じです!しかしrefsHEADは変更され、github_origのものと一致しなくなります。

したがって、同じフォークツリーに属するすべてのreposは共通オブジェクトプールを共有し、各repoには独自の参照が含まれています。自分のフォークされたリポジトリにコミットする人は、自分の参照を変更しますが、オブジェクトを共有プールに入れます。それが中に呼び出されたレポがすべて参照の知識を持っていない限り、最も重要なのgitガベージコレクタは呼び出されない必要があります - - だけでなく、いくつかのより多くのものが世話をしなければならない、本当に使えるようにするもちろん

それは自分のものです。さもなければ、それは参照から到達可能ではないが他のreposの参照から到達可能な共有プール内のオブジェクトを破棄することができます。

0

https://enterprise.github.com/releases/2.2.0/notes GitHubのエンタープライズ(と私はGitHubのを想定)何とかディスクスペースの使用量を減らすためにフォーク間でオブジェクトを共有するによると:Gitリポジトリを共有することにより、ディスクの使用量を低減

このリリースでは、GitHubのエンタープライズリポジトリを保存する方法を変更し、 フォーク間のオブジェクトと は、リポジトリ・データを読み取るときにキャッシュのパフォーマンスを向上させます。

詳細については、https://githubengineering.com/counting-objectsをご覧ください。

関連する問題