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.

3voto

pdp Punkte 3734

Ich konnte die beliebteste Antwort nicht verwenden, weil die --batch-check Befehlszeilenwechsel zu Git 1.8.3 (den ich verwenden muss) akzeptiert keine Argumente. Die folgenden Schritte wurden auf CentOS 6.5 mit Bash 4.1.2 ausprobiert

Wichtige Konzepte

In Git wird der Begriff Klecks impliziert den Inhalt einer Datei. Beachten Sie, dass eine Übertragung den Inhalt einer Datei oder eines Pfadnamens ändern kann. So kann dieselbe Datei je nach Commit auf einen anderen Blob verweisen. Eine bestimmte Datei kann in einem Commit die größte in der Verzeichnishierarchie sein, in einem anderen aber nicht. Die Frage nach großen Commits anstelle von großen Dateien rückt daher die Dinge in die richtige Perspektive.

Für die Ungeduldigen

Der Befehl zum Drucken der Liste der Blobs in absteigender Reihenfolge der Größe lautet:

git cat-file --batch-check < <(git rev-list --all --objects  | \
awk '{print $1}')  | grep blob  | sort -n -r -k 3

Beispielhafte Ausgabe:

3a51a45e12d4aedcad53d3a0d4cf42079c62958e blob 305971200
7c357f2c2a7b33f939f9b7125b155adbd7890be2 blob 289163620

Um solche Blobs zu entfernen, verwenden Sie die BFG Repo-Reiniger wie in anderen Antworten erwähnt. Gegeben eine Datei blobs.txt die z. B. nur die Hashes der Blobs enthält:

3a51a45e12d4aedcad53d3a0d4cf42079c62958e
7c357f2c2a7b33f939f9b7125b155adbd7890be2

Machen:

java -jar bfg.jar -bi blobs.txt <repo_dir>

Die Frage bezieht sich auf das Auffinden der Commits, was mehr Arbeit bedeutet als das Auffinden von Blobs. Um das zu wissen, lesen Sie bitte weiter.

Weitere Arbeiten

Bei einem Commit-Hash ist ein Befehl, der Hashes aller mit ihm verbundenen Objekte, einschließlich Blobs, ausgibt:

git ls-tree -r --full-tree <commit_hash>

Wenn wir also solche Ausgaben für alle Commits im Repo zur Verfügung haben, dann sind bei einem Blob-Hash die Commits, die mit einer der Ausgaben übereinstimmen, der Bunch. Diese Idee ist in dem folgenden Skript kodiert:

#!/bin/bash
DB_DIR='trees-db'

find_commit() {
    cd ${DB_DIR}
    for f in *; do
        if grep -q $1 ${f}; then
            echo ${f}
        fi
    done
    cd - > /dev/null
}

create_db() {
    local tfile='/tmp/commits.txt'
    mkdir -p ${DB_DIR} && cd ${DB_DIR}
    git rev-list --all > ${tfile}

    while read commit_hash; do
        if [[ ! -e ${commit_hash} ]]; then
            git ls-tree -r --full-tree ${commit_hash} > ${commit_hash}
        fi
    done < ${tfile}
    cd - > /dev/null
    rm -f ${tfile}
}

create_db

while read id; do
    find_commit ${id};
done

Wenn der Inhalt in einer Datei mit dem Namen find-commits.sh dann wird ein typischer Aufruf wie folgt aussehen:

cat blobs.txt | find-commits.sh

Wie bereits zuvor, wird die Datei blobs.txt listet Blob-Hashes auf, einen pro Zeile. Die create_db() speichert einen Zwischenspeicher für alle Commit-Listen in einem Unterverzeichnis des aktuellen Verzeichnisses.

Einige Statistiken aus meinen Experimenten auf einem System mit zwei Intel(R) Xeon(R) CPU E5-2620 2.00GHz Prozessoren, die vom Betriebssystem als 24 virtuelle Kerne dargestellt werden:

  • Gesamtzahl der Übertragungen im Repo = fast 11.000
  • Geschwindigkeit der Dateierstellung = 126 Dateien/s. Das Skript erstellt eine einzige Datei pro Übertragung. Dies geschieht nur, wenn der Cache zum ersten Mal erstellt wird.
  • Aufwand für die Cache-Erstellung = 87 s.
  • Durchschnittliche Suchgeschwindigkeit = 522 Übertragungen/s. Die Cache-Optimierung führte zu einer Reduzierung der Laufzeit um 80 %.

Beachten Sie, dass das Skript einen einzigen Thread hat. Daher wird immer nur ein Kern verwendet.

2voto

Windel Punkte 439

Verwenden Sie die --analyze Eigenschaft von git-filter-repo wie diese:

$ cd my-repo-folder
$ git-filter-repo --analyze
$ less .git/filter-repo/analysis/path-all-sizes.txt

0voto

vhs Punkte 7667

Wie kann ich die großen Dateien in der Git-Historie aufspüren?

Beginnen Sie mit der Analyse, Validierung und Auswahl der Grundursache. Verwenden Sie git-repo-analysis zu helfen.

Vielleicht finden Sie auch einen Nutzen in der ausführliche Berichte erzeugt durch BFG Repo-Reiniger die durch Klonen auf ein Digital Ocean-Droplet mit einem Netzwerkdurchsatz von 10MiB/s sehr schnell ausgeführt werden kann.

0voto

IanNorton Punkte 6850

Ich bin aus dem gleichen Grund darüber gestolpert wie alle anderen auch. Aber die zitierten Skripte haben bei mir nicht ganz funktioniert. Ich habe ein Skript erstellt, das eher eine Mischung aus den anderen ist, die ich gesehen habe, und es ist jetzt hier zu finden. https://gitlab.com/inorton/git-size-calc

-1voto

Mila Nautikus Punkte 1439

Um ein Gefühl für die "Diff-Größe" der letzten Übertragungen in der Git-Historie zu bekommen

git log --stat

Dies zeigt die Größe des Unterschieds in Zeilen an: hinzugefügte Zeilen, entfernte Zeilen

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