2012-12-05 30 views
6

ブランチごとにgitリポジトリの領域使用量をリストする方法があるかどうか知っていますか? (dfまたはduのように)ブランチあたりのGitディスク使用量

「ブランチのスペース使用量」とは、「リポジトリの他のブランチにまだ共有されていないコミットによって使用されるスペース」を意味します。

+3

ほとんどのファイルの内容が複数のブランチに存在するコミットされていないすべてのものを一掃しますと、他のクローン化されたディレクトリでこれを行うことを忘れないでください、それはあなたが意味のある何かを得ることができそうですしてください。 –

+0

私はあなたのコメントを本当に理解していない...私は私のgitの枝の各スペースがどれくらいのスペースを使用しているか私に示す何かをしたい... –

+1

あなたはgitブランチはスペースを取らない。つまり、ブランチの1つを削除すると、(圧縮を考慮しなくても)多くのコンテンツが削除されることはありません。リポジトリのサイズは、ブランチのサイズの合計と考えることはできません。 –

答えて

2

私はそれのためにしたRubyスクリプトがあります。私は私の2Moののgitリポジトリで、私は他の支店と共有されていないブロブの私に1Mo鋼を取った1本の役に立たない枝を得ただろうと見ることができた1つで

#!/usr/bin/env ruby -w 
require 'set' 

display_branches = ARGV 

packed_blobs = {} 

class PackedBlob 
    attr_accessor :sha, :type, :size, :packed_size, :offset, :depth, :base_sha, :is_shared, :branch 
    def initialize(sha, type, size, packed_size, offset, depth, base_sha) 
     @sha = sha 
     @type = type 
     @size = size 
     @packed_size = packed_size 
     @offset = offset 
     @depth = depth 
     @base_sha = base_sha 
     @is_shared = false 
     @branch = nil 
    end 
end 

class Branch 
    attr_accessor :name, :blobs, :non_shared_size, :non_shared_packed_size, :shared_size, :shared_packed_size, :non_shared_dependable_size, :non_shared_dependable_packed_size 
    def initialize(name) 
     @name = name 
     @blobs = Set.new 
     @non_shared_size = 0 
     @non_shared_packed_size = 0 
     @shared_size = 0 
     @shared_packed_size = 0 
     @non_shared_dependable_size = 0 
     @non_shared_dependable_packed_size = 0 
    end 
end 

dependable_blob_shas = Set.new 

# Collect every packed blobs information 
for pack_idx in Dir[".git/objects/pack/pack-*.idx"] 
    IO.popen("git verify-pack -v #{pack_idx}", 'r') do |pack_list| 
     pack_list.each_line do |pack_line| 
      pack_line.chomp! 
      if not pack_line.include? "delta" 
       sha, type, size, packed_size, offset, depth, base_sha = pack_line.split(/\s+/, 7) 
       size = size.to_i 
       packed_size = packed_size.to_i 
       packed_blobs[sha] = PackedBlob.new(sha, type, size, packed_size, offset, depth, base_sha) 
       dependable_blob_shas.add(base_sha) if base_sha != nil 
      else 
       break 
      end 
     end 
    end 
end 

branches = {} 

# Now check all blobs for every branches in order to determine whether it's shared between branches or not 
IO.popen("git branch --list", 'r') do |branch_list| 
    branch_list.each_line do |branch_line| 
     # For each branch 
     branch_name = branch_line[2..-1].chomp 
     branch = Branch.new(branch_name) 
     branches[branch_name] = branch 
     IO.popen("git rev-list #{branch_name}", 'r') do |rev_list| 
      rev_list.each_line do |commit| 
       # Look into each commit in order to collect all the blobs used 
       for object in `git ls-tree -zrl #{commit}`.split("\0") 
        bits, type, sha, size, path = object.split(/\s+/, 5) 
        if type == 'blob' 
         blob = packed_blobs[sha] 
         branch.blobs.add(blob) 
         if not blob.is_shared 
          if blob.branch != nil and blob.branch != branch 
           # this blob has been used in another branch, let's set it to "shared" 
           blob.is_shared = true 
           blob.branch = nil 
          else 
           blob.branch = branch 
          end 
         end 
        end 
       end 
      end 
     end 
    end 
end 

# Now iterate on each branch to compute the space usage for each 
branches.each_value do |branch| 
    branch.blobs.each do |blob| 
     if blob.is_shared 
      branch.shared_size += blob.size 
      branch.shared_packed_size += blob.packed_size 
     else 
      if dependable_blob_shas.include?(blob.sha) 
       branch.non_shared_dependable_size += blob.size 
       branch.non_shared_dependable_packed_size += blob.packed_size 
      else 
       branch.non_shared_size += blob.size 
       branch.non_shared_packed_size += blob.packed_size 
      end 
     end 
    end 
    # Now print it if wanted 
    if display_branches.empty? or display_branches.include?(branch.name) 
     puts "branch: %s" % branch.name 
     puts "\tnon shared:" 
     puts "\t\tpacked: %s" % branch.non_shared_packed_size 
     puts "\t\tnon packed: %s" % branch.non_shared_size 
     puts "\tnon shared but with dependencies on it:" 
     puts "\t\tpacked: %s" % branch.non_shared_dependable_packed_size 
     puts "\t\tnon packed: %s" % branch.non_shared_dependable_size 
     puts "\tshared:" 
     puts "\t\tpacked: %s" % branch.shared_packed_size 
     puts "\t\tnon packed: %s" % branch.shared_size, "" 
    end 
end 

+1

私はこのスクリプトを試して、次のエラーを受け取りました: 'serv01.ams38.siteground.eu [〜/ www/cledu(dev)] ruby​​ ../../diskspace.rb 。 ./../diskspace.rb:75:未定義メソッド 'is_shared 'for nil:NilClass(NoMethodError) –

+0

これは驚くべきことです、私が探していたものです! 'git-branch-space.rb:70:warning:割り当て済みだが未使用の可変ビット'、 'git-branch-space.rb:70:警告:割り当てられているが未使用の変数'git-branch-space.rb:70:警告:割り当てられていますが、未使用の変数パス' 出力を説明するもう少しの文書があれば素晴らしいでしょう。 – rjmunro

+0

@ChrisKepinskiスクリプトの前に 'git gc'を実行するとエラーが消えてしまいました。 – rjmunro

2

Gitは、ディスクスペースを使用して各コミットが(単純な意味で)コミットの有向非循環グラフを維持します。

すべてのブランチが最初のコミットから分岐しない限り、さまざまなブランチに共通のコミットが存在します。つまり、各ブランチはある程度のディスク容量を共有します。

これは、どのくらいの金額を共有するのか、他のどの支店と共有するのかによって資格を取得する必要があるため、ディスク使用量の「ブランチごとの」数字を提供することが難しくなります。

+0

実際には、このブランチだけでどれくらいのスペースが使われているのかを知りたいものがあります。* ...そのため、特定のブランチだけにあるコミットによって使用されるディスクスペースを合計します。各ブランチのためにそれを列挙します(それを小さくするために私のgit repoの正しい枝を切り取るのを助けるために) –

+0

それはもっと理にかなっていますが、 gitで使用されている圧縮方式のためです。大規模なブランチを淘汰しようとしている場合は、非共有コミットが多いものや、最後の共通コミットが大幅に異なる変更をコミットしたものを探す方が良いかもしれません。それでも、私はそれがかなり投機的だと言っています。 –

2

リポジトリのほとんどの領域は、ファイルを含むブロブによって取得されます。

しかし、ブロブが2つのブランチ(または同じ内容の2つのファイル)で共有されている場合、そのブロブは複製されません。リポジトリのサイズは、ブランチのサイズの合計と考えることはできません。ブランチが取るスペースという概念はありません。

そして、小さなファイルの変更でスペースを節約できる圧縮がたくさんあります。

通常、ブランチを切り捨てると、予測できない小さなスペースしか解放されません。

7

これには適切な回答がありません。特定のブランチにのみ含まれているコミットを見ると、ブロブのリスト(基本的にファイルバージョン)が得られます。これらのブロブが他のブランチのコミットの一部であるかどうかをチェックする必要があります。これを実行すると、ブランチの一部だけであるブロブのリストが作成されます。

これらのブロブのサイズを合計して結果を得ることができますが、これはおそらく非常に間違っています。 Gitはこれらのブロブを互いに圧縮します。したがって、ブロブの実際のサイズは、あなたのレポにある他のブロブに依存します。あなたは1000ブロブを削除することができます。各ブロブは10MB、ディスク空き容量は1KBです。

通常、大きなレポサイズは、レポの単一の大きなファイルによって引き起こされます(そうでない場合は、おそらく何か間違っています:)。それらを見つける方法に関する情報はここに見つけることができます:Find files in git repo over x megabytes, that don't exist in HEAD

+0

+1の有用なリンク –

0

私は今朝、同じ問題を抱えていたし、迅速なスクリプトを書いた:

for a in $(git branch -a | grep remotes | awk '{print $1}' | sed 's/remotes\/origin\///'); do echo -n ${a} -\ ; git clean -d -x -f > /dev/null 2>&1 ;git checkout ${a} > /dev/null 2>&1; du -hs -I .git .;done 

これは私たちがきれいにそれをチェックアウトを確認するために、その内容をリセットした後、すべてのリモートブランチをチェックアウトします。その後、.gitディレクトリのないサイズが表示されます。

これで、大きなファイルを含むブランチをプッシュした人を見つけることができました。

それは

関連する問題