620 Stimmen

Wie findet/identifiziert man große Commits in der Git-History?

Ich habe ein 300 MB großes Git-Repo. Die Gesamtgröße meiner derzeit ausgecheckten Dateien beträgt 2 MB, und die Gesamtgröße des restlichen Git Repo beträgt 298 MB. Dies ist im Grunde eine reine Code-Repositorium, die nicht größer als ein paar MB sein sollte.

Ich vermute, dass jemand versehentlich einige große Dateien (Video, Bilder, etc.) übertragen und dann entfernt hat... aber nicht aus Git, so dass die Geschichte immer noch nutzlose große Dateien enthält. Wie kann ich die großen Dateien in der Git-Historie finden? Es gibt mehr als 400 Übertragungen, so dass es unpraktisch ist, eine nach der anderen zu suchen.

ANMERKUNG : meine Frage geht es nicht um wie man die Datei entfernt sondern wie man finden. es in erster Linie.

1361voto

raphinesse Punkte 16302

Ein rasend schneller Shell-Einzeiler

Dieses Shell-Skript zeigt alle Blob-Objekte im Repository an, sortiert vom kleinsten zum größten.

Für mein Beispiel-Repos lief es ungefähr so 100 Mal schneller als die anderen, die hier zu finden sind.
Auf meinem bewährten Athlon II X4-System bewältigt er die Linux-Kernel-Repository mit seinen 5,6 Millionen Objekten in etwas mehr als eine Minute .

Das Basisskript

git rev-list --objects --all |
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
  sed -n 's/^blob //p' |
  sort --numeric-sort --key=2 |
  cut -c 1-12,41- |
  $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest

Wenn Sie den obigen Code ausführen, erhalten Sie eine schöne menschenlesbare Ausgabe wie diese:

...
0d99bb931299  530KiB path/to/some-image.jpg
2ba44098e28f   12MiB path/to/hires-image.png
bd1741ddce0d   63MiB path/to/some-video-1080p.mp4

macOS-Benutzer : Seit numfmt unter macOS nicht verfügbar ist, können Sie entweder die letzte Zeile weglassen und mit rohen Bytegrößen arbeiten oder brew install coreutils .

Filtern

Zu erreichen weitere Filterung fügen Sie eine der folgenden Zeilen ein vor dem sort Zeile .

An Dateien ausschließen, die sich in HEAD fügen Sie die folgende Zeile ein:

grep -vF --file=<(git ls-tree -r HEAD | awk '{print $3}') |

An nur Dateien anzeigen, die eine bestimmte Größe überschreiten (z.B. 1MiB = 2 20 B) wird die folgende Zeile eingefügt

awk '$2 >= 2^20' |

Ausgabe für Computer

Um eine Ausgabe zu erzeugen, die besser für die Weiterverarbeitung geeignet von Computern, lassen Sie die letzten beiden Zeilen des Basisskripts weg. Sie übernehmen die gesamte Formatierung. Das Ergebnis sieht dann etwa so aus:

...
0d99bb93129939b72069df14af0d0dbda7eb6dba 542455 path/to/some-image.jpg
2ba44098e28f8f66bac5e21210c2774085d2319b 12446815 path/to/hires-image.png
bd1741ddce0d07b72ccf69ed281e09bf8a2d0b2f 65183843 path/to/some-video-1080p.mp4

Anhang

Entfernen von Dateien

Die eigentliche Entfernung der Datei finden Sie unter diese SO-Frage zum Thema .

Verstehen der Bedeutung der angezeigten Dateigröße

Dieses Skript zeigt die Größe jeder Datei im Arbeitsverzeichnis an. Wenn Sie sehen wollen, wie viel Platz eine Datei einnimmt, wenn sie nicht ausgecheckt ist, können Sie %(objectsize:disk) 代わりに %(objectsize) . Es ist jedoch zu beachten, dass auch diese Metrik ihre Tücken hat, wie im Abschnitt Dokumentation .

Anspruchsvollere Größenstatistiken

Manchmal reicht eine Liste großer Dateien einfach nicht aus, um herauszufinden, was das Problem ist. Verzeichnisse oder Verzweigungen, die eine große Anzahl kleiner Dateien enthalten, würden Sie zum Beispiel nicht entdecken.

Wenn das Skript hier also nicht ausreicht (und Sie eine aktuelle Version von git haben), sollten Sie sich git-filter-repo --analyze o git rev-list --disk-usage ( Beispiele ).

196voto

skolima Punkte 30692

Ich habe eine Ein-Zeilen-Lösung gefunden unter ETH Zürich Departement Physik wiki Seite (fast am Ende dieser Seite). Machen Sie einfach eine git gc um abgestandenen Müll zu entfernen, und dann

git rev-list --objects --all \
  | grep "$(git verify-pack -v .git/objects/pack/*.idx \
           | sort -k 3 -n \
           | tail -10 \
           | awk '{print$1}')"

zeigt Ihnen die 10 größten Dateien im Repository an.

Es gibt jetzt auch eine einfachere Lösung, GitExtensions verfügt jetzt über ein Plugin, das dies in der Benutzeroberfläche erledigt (und auch History-Rewrites behandelt).

GitExtensions 'Find large files' dialog

174voto

Mark Longair Punkte 412179

Ich habe dieses Skript in der Vergangenheit sehr nützlich gefunden, um große (und nicht offensichtliche) Objekte in einem Git-Repository zu finden:


#!/bin/bash
#set -x 

# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
# @author Antony Stubbs

# set the internal field separator to line break, so that we can iterate easily over the verify-pack output
IFS=$'\n';

# list all objects including their size, sort by size, take top 10
objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`

echo "All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file."

output="size,pack,SHA,location"
allObjects=`git rev-list --all --objects`
for y in $objects
do
    # extract the size in bytes
    size=$((`echo $y | cut -f 5 -d ' '`/1024))
    # extract the compressed size in bytes
    compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
    # extract the SHA
    sha=`echo $y | cut -f 1 -d ' '`
    # find the objects location in the repository tree
    other=`echo "${allObjects}" | grep $sha`
    #lineBreak=`echo -e "\n"`
    output="${output}\n${size},${compressedSize},${other}"
done

echo -e $output | column -t -s ', '

Dadurch erhalten Sie den Objektnamen (SHA1sum) des Blobs und können dann ein Skript wie dieses verwenden:

... um den Commit zu finden, der auf jeden dieser Blobs verweist.

38voto

friederbluemle Punkte 27915

Schritt 1 Schreibt alle SHA1s der Dateien in eine Textdatei:

git rev-list --objects --all | sort -k 2 > allfileshas.txt

Schritt 2 Sortieren Sie die Blobs vom größten zum kleinsten und schreiben Sie die Ergebnisse in eine Textdatei:

git gc && git verify-pack -v .git/objects/pack/pack-*.idx | egrep "^\w+ blob\W+[0-9]+ [0-9]+ [0-9]+$" | sort -k 3 -n -r > bigobjects.txt

Schritt 3a Kombinieren Sie beide Textdateien, um Informationen zu Dateiname/sha1/Größe zu erhalten:

for SHA in `cut -f 1 -d\  < bigobjects.txt`; do
echo $(grep $SHA bigobjects.txt) $(grep $SHA allfileshas.txt) | awk '{print $1,$3,$7}' >> bigtosmall.txt
done;

Schritt 3b Wenn Sie Dateinamen oder Pfadnamen haben, die Räume versuchen Sie diese Variante von Schritt 3a. Sie verwendet cut 代わりに awk um die gewünschten Spalten inkl. Leerzeichen von Spalte 7 bis zum Ende der Zeile zu erhalten:

for SHA in `cut -f 1 -d\  < bigobjects.txt`; do
echo $(grep $SHA bigobjects.txt) $(grep $SHA allfileshas.txt) | cut -d ' ' -f'1,3,7-' >> bigtosmall.txt
done;

Nun können Sie sich die Datei bigtosmall.txt ansehen, um zu entscheiden, welche Dateien Sie aus Ihrem Git-Verlauf entfernen möchten.

Schritt 4 Um die Entfernung durchzuführen (beachten Sie, dass dieser Teil langsam ist, da er jeden Commit in Ihrer Historie nach Daten über die identifizierte Datei durchsucht):

git filter-branch --tree-filter 'rm -f myLargeFile.log' HEAD

Quelle

Die Schritte 1-3a wurden kopiert von Auffinden und Löschen großer Dateien aus dem Git-Verlauf

EDITAR

Der Artikel wurde irgendwann in der zweiten Hälfte des Jahres 2017 gelöscht, aber eine archivierte Kopie davon kann weiterhin über die Wiederherstellungsmaschine .

16voto

Warren Seine Punkte 2083

Sie sollten Folgendes verwenden BFG Repo-Reiniger .

Auf der Website steht:

Das BFG ist eine einfachere und schnellere Alternative zu um schlechte Daten aus dem Verlauf Ihres Git-Repositorys zu bereinigen:

  • Entfernen verrückter großer Dateien
  • Entfernen von Passwörtern, Berechtigungsnachweisen und anderen privaten Daten

Das klassische Verfahren zur Verkleinerung eines Repositorys wäre:

git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --strip-biggest-blobs 500 some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X