2017-01-05 4 views
2

gitリポジトリに "大きな"(5メガバイト)テキストファイルがあります。 最後の行に文字を追加してgit addを実行すると、.gitフォルダのサイズが約1 mb(私の5 MBファイルの圧縮サイズと見なします)に増加します。Gitはdiffの代わりに全体のファイルを保存するように見えますが、どうしたら回避できますか?

編集して追加するたびに同じことが起こります。

私がgit add -p fileを実行すると、わずか数バイトの良い差分が得られます。しかし、とにかく大きなオブジェクトファイルは、私が完全に追加するときに格納されます。

git gc --prune=nowを実行すると、大きなオブジェクトファイルが削除されますが、動作が期待どおりに機能しているようです。

しかし、定期的にgit gcを実行するのは良いオプションではありません。私はSDカードで自動的にgitを使用しています。このカードは、カードを消耗してメガバイトを削除します。

だから、私の質問(複数可)

1)私は、これはgitのの振る舞いである右のことを私はありますか?または私は何かを誤解するか?

2)これを避けてdiffを保存するだけですか?

古い変更を復元するなどの柔軟性を失うことは問題ありません。分岐やstashing、またはgitのために人生を複雑にする可能性がある他のものは必要ありません。

編集 私の問題は、gitがファイル全体を一度保存​​するのではないことです。しかし、それは各編集のためにファイル全体を保存します。各文字編集の間に追加とコミットを含む10文字を追加すると、ファイル全体が(圧縮形式で)10回保存されます。

+0

マイト便利です:http://blog.deveo.com/storing-large-binary-files-in-git-repositories/ – Swift

+0

ありがとう、私はそのリンクをssen持っているが、それは非常に大きいファイルを処理するためのより多くのようですそれらのサイズは問題です。または、削除されたファイルがまだgit.indexでスペースを取ってしまうという問題。しかし、これらのことは私には受け入れられます。 –

答えて

3

Gitはすべてのファイルを「オブジェクト」として格納します(具体的には、のBLOBオブジェクトとして、BLOBはGitの4つのオブジェクトタイプの1つです)。しかし、これはすべての話ではありません。

各オブジェクトはその内容によって一意に識別されます。オブジェクトの内容は暗号化ハッシュになります(具体的には、生の内容の前にオブジェクト型(この場合はblob)が付加され、そのサイズがバイト単位で表され、1つのASCII NULバイトが付加されたSHA-その後に実際のオブジェクトバイトが続きます)。したがって、同じファイルを複数回追加すると、生の内容は変わらないので同じハッシュになりますが、1バイトでも変更すると、新しいオブジェクトと新しいハッシュが追加されます。

これはリポジトリが〜1 MB増加する理由です:あなたが推測したように、圧縮された5 MBオブジェクトのサイズは1 MBです。 1バイトが異なるので、新しいオブジェクトは新しいIDを持ち、新しい「緩い」オブジェクトとして格納されます。緩いオブジェクトは、圧縮されたオブジェクトとヘッダーで構成され、個別のファイルに保存されますが、すべてのオブジェクトが緩んでいるわけではありません。また、Gitはパックオブジェクトを提供しています。

パックされたオブジェクトはかなり複雑です。パックに格納されているオブジェクトは "deltified"です:GitのlibXdiffの特殊変形版で圧縮されています(Is the git binary diff algorithm (delta storage) standardized?も参照)。 Gitはベースオブジェクトと一連の派生オブジェクトを選択し、ベースに対して圧縮します。運があれば、ファイルは自分自身に対して圧縮されるので、一度パックされると、基本ファイル自体を除いて、比較的小さくなる。

通常、Gitはパックファイルをいつ作成するのかを選択します。通常のコードでは、ほとんどの通常のソースファイルをうまく処理します。非常に大きなテキストファイルは自動的にパッキングのアンバランスになりますので、より良い結果を得ることができるかどうかを確認するために、手作りパッキング(時折のgit repack -a -dを使用したり、ウィンドウパラメータを微調整)を試してみてください。ただし、ネットワーク接続経由​​でデルタを送信するために使用される「シンパック」を除き、パックファイルでは、すべてのデリゲートオブジェクトと同じパックにベースオブジェクトが存在する必要があります。大容量のファイルが頻繁に変更される場合は、多くの大型パックを取得するため、頻繁にパックするのは非生産的です(ただし、-a -dステップでは、「保存」ファイルを使用しない限りパックを統合する必要があります)。

(ファイルの作業ツリーのバージョンを変更し、git add結果と、それは新しいハッシュを取得した場合、Gitはすぐにかかわらず、既存のパックされたバージョンの、緩やかなオブジェクトとしてパッケージ化されます。)

+0

+1ありがとうございます!意味あり。たぶんgitは私が必要とするもののための正しいツールではありません。あなたの情報は、gitオブジェクトとパックされたオブジェクトを理解するのに大いに役立ちました。 –

+0

最近では、大規模な計画では5 MBが小さくても、そうでないかもしれません。それでも、Gitの外に大きなファイルを格納するための非常に多くの補助システム(Git-LFSとgit-annexに気付く2つの補助システム)があります。 – torek

+0

問題は合計です。多くのファイルが関係しており、新しい編集を頻繁に追加しています。私が物事を理解しているので、上の2つの質問に対する答えは1)はい、2)いいえgitはこのハッキリな環境で置き換えられます –

0

これは、すべてのソース管理システムでよく見られる問題です。彼らはであり、テキストとして解析できるコードを格納するためにはを意味します。テキストではないものは差別的に格納されません。認識できないファイルは単純にアップロードされます。私は仕事でいくつかのリポジトリを管理していたので、大きなファイルをアップロードしてリポジトリサイズをギガバイト単位で増やし、それを移動したり再アップロードしたりすることができたユーザーに対処しました。

+0

ありがとう、問題は、一度コードを格納するのではなく、テキストファイル全体が各編集に格納されるということです。 –

関連する問題