2012-12-05 12 views
6

Czy wiesz, czy istnieje sposób na wyświetlenie wykorzystania przestrzeni w repozytorium git dla oddziału? (np. df lub du będzie)Wykorzystanie dysku Git w oddziale

Przez "wykorzystanie przestrzeni" dla oddziału rozumiem "przestrzeń wykorzystywaną przez zatwierdzenia, które nie są jeszcze udostępnione w innych gałęziach repozytorium".

+3

Większość zawartości pliku będzie obecny na więcej niż jeden oddział, więc jest mało prawdopodobne, można uzyskać coś pożytecznego. –

+0

Naprawdę nie rozumiem twojego komentarza ... Chcę czegoś, co wskazywałoby mi na to, ile przestrzeni używa każda gałąź mojego gita ... –

+1

Git gałęzie nie zajmują miejsca. Oznacza to, że jeśli usuniesz jedną z gałęzi, zazwyczaj nie usuniesz zbyt wielu treści (nawet bez uwzględnienia kompresji). A rozmiar repozytorium nie może być uważany za sumę wielkości gałęzi. –

Odpowiedz

2

Jak się wydaje, że nic takiego już nie istnieje, oto skrypt w języku Ruby, który zrobiłem w tym celu.

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

Z tą jedną udało mi się zobaczyć, że w moim repozytorium git 2Mo, ja mam jedną bezużyteczną gałąź która miała mi 1Mo BLOB nie jest dzielona z innymi oddziałami.

+1

Próbowałem tego skryptu i otrzymałem następujący komunikat o błędzie: 'serv01.ams38.siteground.eu [~/www/cledu (dev)] ruby ​​../../diskspace.rb . ./../diskspace.rb:75: undefined metoda 'is_shared 'for nil: NilClass (NoMethodError) –

+0

To jest niesamowite, właśnie tego szukałem! Dostaję z niego kilka ostrzeżeń: 'git-branch-space.rb: 70: ostrzeżenie: przypisana, ale nieużywana zmienna - bity', ' git-branch-space.rb: 70: ostrzeżenie: przypisana, ale nieużywana zmienna - size', 'git-branch-space.rb: 70: ostrzeżenie: przypisana, ale nieużywana zmienna - path' Byłoby wspaniale, gdyby było trochę więcej dokumentacji wyjaśniającej wynik. – rjmunro

+0

@ChrisKepinski Stwierdziłem, że błąd zniknął, jeśli uruchomiłem 'git gc' przed skryptem. – rjmunro

2

Git utrzymuje skierowany acykliczny wykres zatwierdzeń, z (w uproszczonym sensie) każdym zatwierdzeniem przy użyciu miejsca na dysku.

Jeśli wszystkie twoje gałęzie nie będą się różnić od pierwszego zatwierdzenia, wtedy będą wspólne, wspólne dla różnych gałęzi, co oznacza, że ​​każda gałąź "dzieli" pewną ilość miejsca na dysku.

Powoduje to, że trudno jest podać liczbę użycia dysku w oddziale, ponieważ musiałaby zostać zakwalifikowana, z jaką kwotą jest współużytkowana iz którymi innymi gałęziami jest ona udostępniana.

+0

Właściwie, chcę czegoś, co powie mi, ile przestrzeni jest zużywane * tylko przez tę gałąź * ... więc to zsumuje przestrzeń dyskową używaną przez zatwierdzenia, które są tylko w tej konkretnej gałęzi ... i które wyświetli listę dla każdego oddziału (aby pomóc mi odciąć właściwe gałęzie mojego repozytorium git, aby go zmniejszyć) –

+0

OK, to ma więcej sensu - ale nie wiem, czy to ułatwi wypracowanie , ze względu na schematy kompresji używane przez git. Jeśli chcesz odstrzelić zbyt duże gałęzie, lepiej byłoby znaleźć te, które mają wiele niepodzielonych zatwierdzeń i/lub te, które mają zobowiązania z istotnie rozbieżnymi zmianami do ostatniego wspólnego zatwierdzenia. Nawet wtedy, powiedziałbym, że to dość spekulatywne. –

2

Większość przestrzeni w twoim repozytorium pochodzi z obiektów typu blob zawierających pliki.

Ale gdy obiekt typu blob jest współdzielony przez dwie gałęzie (lub dwa pliki o tej samej zawartości), nie jest on duplikowany. Wielkość repozytorium nie może być uważana za sumę rozmiaru gałęzi. Nie ma takiej koncepcji jak przestrzeń zajmowana przez gałąź.

Istnieje również duża kompresja umożliwiająca oszczędność miejsca przy niewielkich modyfikacjach plików.

Zwykle odcięcie gałęzi uwolni tylko bardzo małą, nieprzewidywalną przestrzeń.

7

To nie daje prawidłowej odpowiedzi. Jeśli spojrzysz na zatwierdzenia zawarte tylko w konkretnej gałęzi, otrzymasz listę obiektów typu blob (zasadniczo wersje plików). Teraz musisz sprawdzić, czy te plamki są częścią któregokolwiek z zatwierdzeń w innych gałęziach. Po wykonaniu tej czynności pojawi się lista obiektów typu blob, które są tylko częścią Twojej gałęzi.

Teraz można podsumować rozmiar tych obiektów, aby uzyskać wynik - ale to prawdopodobnie byłoby bardzo złe. Git kompresuje te obiekty przeciwko sobie, więc rzeczywisty rozmiar obiektu typu blob zależy od tego, jakie inne obiekty znajdują się w repozytorium. Można usunąć 1000 bloków po 10 MB i tylko 1kb wolnego miejsca na dysku.

Zazwyczaj duży rozmiar repo jest spowodowany przez pojedyncze duże pliki w repozytorium (jeśli nie, prawdopodobnie robisz coś nie tak :). Informacje o tym, jak je znaleźć można znaleźć tutaj: Find files in git repo over x megabytes, that don't exist in HEAD

+0

+1 dla użytecznych linków –

0

miałem ten sam problem to rano i napisał krótki skrypt:

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 

Będzie kasa każdą zdalną gałąź po zresetowaniu ich zawartość, aby upewnić się, że to czysto kasy. Następnie wyświetli rozmiar bez katalogu .git.

Dzięki temu udało mi się znaleźć osobę, która pchnęła oddział z dużym plikiem.

Proszę pamiętać, aby zrobić to w innym sklonowanego katalogu jak będzie wymazać wszystko, co nie jest zaangażowana

Powiązane problemy