2012-12-05 80 views
6

您是否知道是否有辦法列出每個分支的git存儲庫的空間使用情況? (如dfdu會)每個分支的Git磁盤使用情況

分支的「空間使用情況」我的意思是「尚未與存儲庫其他分支共享的提交使用的空間」。

+3

大多數文件的內容將出現在不止一個分支的一切,所以這是不可能的,你可以得到一些有意義的事情。 –

+0

我真的不明白你的評論...我想要的東西,這將表明我的每個git分支正在使用多少空間... –

+1

你git分支不佔用空間。也就是說,如果你刪除了一個分支,你通常不會刪除很多內容(即使沒有考慮到壓縮)。並且存儲庫的大小不能被認爲是分支大小的總和。 –

回答

2

因爲似乎沒有像這樣已經存在,這裏是我爲此做的Ruby腳本。

#!/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 

有了一個我能看到,在我的2Mo的git倉庫,我得到了一個無用的分支,它把我1Mo鋼不與任何其他部門共享的斑點。

+1

我試過這個腳本,並得到以下錯誤: 'serv01.ams38.siteground.eu [〜/ www/cledu(dev)] ruby​​ ../../diskspace.rb 。 ./../diskspace.rb:75:未定義的方法'is_shared'爲nil:NilClass(NoMethodError) –

+0

這真是太神奇了,正是我期待的!但是我收到了一些警告:'git-branch-space.rb:70:warning:assigned但未使用的變量 - 位', 'git-branch-space.rb:70:warning:assigned但未使用的變量 - size', 'git-branch-space.rb:70:warning:分配但未使用的變量 - 路徑' 如果有更多文檔解釋輸出,那將會很棒。 – rjmunro

+0

@ChrisKepinski如果我在腳本之前運行'git gc',我發現錯誤消失了。 – rjmunro

2

GIT中保持提交的有向無環圖,它(在一個簡單的意義上)每次提交使用磁盤空間。

除非你所有的分支從通用於各個分支的第一個承諾,那麼就會有分歧的提交,這意味着每個分公司的「股份」的磁盤空間一定量。

這使得難以提供磁盤利用率的「每個分支」圖中,因爲這將需要與共享什麼量合格,並與其他分支它是共享的。

+0

其實,我想要的東西,會告訴我有多少空間*只有通過這個分支* ...所以這將總結提交使用的磁盤空間只是在該特定的分支...和哪些將列出每個分支(爲了幫助我切斷我的git repo的正確分支,使其更小) –

+0

好吧,這樣做更有意義 - 但我不知道這是否使得它更容易解決,這是由於git使用的壓縮方案。如果您希望挑選超大分支,那麼尋找那些具有大量非共享提交以及/或者對最後一次常見提交進行了大量不同更改的提交可能會更好。即使那樣,我會說這是非常投機的。 –

2

您的存儲庫的大部分空間都是由包含這些文件的Blob所佔用的。

但是,當一個斑點是由兩個分支(或兩個文件相同的內容)共享它不重複。存儲庫的大小不能被認爲是分支大小的總和。沒有分支機構所採用的空間這樣的概念。

而且有很多壓縮功能可以節省小文件修改的空間。

通常切斷分支只會釋放一個非常小的,不可預知的空間。

7

這沒有一個正確的答案。如果你看看只包含在特定分支中的提交,你會得到一個blob列表(基本上是文件版本)。現在您必須檢查這些blob是否是其他分支中的任何提交的一部分。這樣做後,你將有一個blob列表,只是你的分支的一部分。現在

你能總結一下這些斑點的大小,得到的結果 - 但是這很可能是非常錯誤的。 Git相互壓縮這些blob,所以blob的實際大小取決於您的repo中的其他blob。您可以刪除1000個Blob,每個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目錄的大小。

有了這個,我能夠找到推送一個包含大文件的分支的人。

請記住要做到這一點在其他克隆目錄中,將它消滅不承諾

相關問題