revertir - ¿Cómo encontrar/identificar archivos grandes/confirmados en el historial de Git?
regresar a un commit anterior git (10)
¿Cómo puedo rastrear los archivos grandes en el historial de git?
Comience por analizar, validar y seleccionar la causa raíz. Utilice git-repo-analysis
para ayudar.
También puede encontrar algo de valor en los informes detallados generados por BFG Repo-Cleaner , que pueden ejecutarse muy rápidamente mediante la clonación de una gota de Digital Ocean utilizando su rendimiento de red de 10MiB / s.
Tengo un git repo de 300 MB. Mis archivos retirados actualmente pesan 2 MB, y el repositorio de git pesa 298 MB. Básicamente, este es un repositorio de código que no debe pesar más de unos pocos MB.
Probablemente, alguien en algún momento cometió algunos archivos pesados por accidente (video, imágenes grandes, etc.), y luego los eliminó ... pero no de git, así que tenemos un historial con archivos grandes inútiles. ¿Cómo puedo rastrear los archivos grandes en el historial de git? Hay más de 400 confirmaciones, por lo que ir una por una requiere mucho tiempo.
NOTA : mi pregunta no es sobre cómo eliminar el archivo , sino sobre cómo encontrarlo en primer lugar.
🚀 Una cáscara increíblemente rápida de una sola línea 🚀
Este script de shell muestra todos los objetos de blob en el repositorio, ordenados de menor a mayor.
Para mi muestra de recompra, corrió unas 100 veces más rápido que los otros que se encuentran aquí.
En mi confiable sistema Athlon II X4, maneja el repositorio de Linux Kernel con sus 5.6 millones de objetos en poco más de un minuto .
El guión base
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
Cuando ejecute el código anterior, obtendrá una salida agradable y legible para el ser humano como esta:
...
0d99bb931299 530KiB path/to/some-image.jpg
2ba44098e28f 12MiB path/to/hires-image.png
bd1741ddce0d 63MiB path/to/some-video-1080p.mp4
Usuarios de macOS : dado que numfmt
no está disponible en macOS, puede omitir la última línea y tratar con tamaños de byte sin procesar o brew install coreutils
.
Filtración
Para lograr un mayor filtrado , inserte cualquiera de las siguientes líneas antes de la línea de sort
.
Para excluir los archivos que están presentes en HEAD
, inserte la siguiente línea:
| grep -vF --file=<(git ls-tree -r HEAD | awk ''{print $3}'') /
Para mostrar solo archivos que excedan el tamaño dado (por ejemplo, 1 MiB = 2 20 B), inserte la siguiente línea:
| awk ''$2 >= 2^20'' /
Salida para computadoras
Para generar una salida que sea más adecuada para el procesamiento posterior de las computadoras, omita las dos últimas líneas del script base. Ellos hacen todo el formato. Esto te dejará con algo como esto:
...
0d99bb93129939b72069df14af0d0dbda7eb6dba 542455 path/to/some-image.jpg
2ba44098e28f8f66bac5e21210c2774085d2319b 12446815 path/to/hires-image.png
bd1741ddce0d07b72ccf69ed281e09bf8a2d0b2f 65183843 path/to/some-video-1080p.mp4
Eliminación de archivos
Para la eliminación del archivo real, consulte esta pregunta SO sobre el tema .
Debe utilizar BFG Repo-Cleaner .
Según el sitio web:
El BFG es una alternativa más simple y rápida a git-filter-branch para limpiar los datos erróneos de su historial de repositorio de Git:
- Eliminar archivos grandes locos
- Eliminar contraseñas, credenciales y otros datos privados
El procedimiento clásico para reducir el tamaño de un repositorio sería:
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
He encontrado este script muy útil en el pasado para encontrar objetos grandes (y no obvios) en un repositorio de git:
#!/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 spereator 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 '', ''
Eso le dará el nombre del objeto (SHA1sum) del blob, y luego puede usar un script como este:
- ¿Qué cometido tiene este blob?
... para encontrar el commit que apunta a cada una de esas manchas.
He encontrado una solución de una sola línea en la página wiki de ETH Zurich Department of Physics (cerca del final de esa página). Solo haz un git gc
para eliminar la chatarra obsoleta, y luego
git rev-list --objects --all /
| grep "$(git verify-pack -v .git/objects/pack/*.idx /
| sort -k 3 -n /
| tail -10 /
| awk ''{print$1}'')"
le dará los 10 archivos más grandes en el repositorio.
También hay una solución más floja ahora disponible, GitExtensions ahora tiene un complemento que hace esto en la interfaz de usuario (y también maneja las reescrituras del historial).
Me encontré con esto por la misma razón que cualquier otra persona. Pero los guiones citados no funcionaron para mí. Hice uno que es más un híbrido de los que he visto y ahora vive aquí: https://gitlab.com/inorton/git-size-calc
Prueba git ls-files | xargs du -hs --threshold=1M
git ls-files | xargs du -hs --threshold=1M
.
Usamos el siguiente comando en nuestro canal de CI, se detiene si encuentra algún archivo grande en el repositorio de git:
test $(git ls-files | xargs du -hs --threshold=1M 2>/dev/null | tee /dev/stderr | wc -l) -gt 0 && { echo; echo "Aborting due to big files in the git repository."; exit 1; } || true
Si está en Windows, aquí hay un script de PowerShell que imprimirá los 10 archivos más grandes en su repositorio:
$revision_objects = git rev-list --objects --all;
$files = $revision_objects.Split() | Where-Object {$_.Length -gt 0 -and $(Test-Path -Path $_ -PathType Leaf) };
$files | Get-Item -Force | select fullname, length | sort -Descending -Property Length | select -First 10
Si solo desea tener una lista de archivos grandes, me gustaría proporcionarle la siguiente línea ( fuente en renuo ):
join -o "1.1 1.2 2.3" <(git rev-list --objects --all | sort) <(git verify-pack -v objects/pack/*.idx | sort -k3 -n | tail -5 | sort) | sort -k3 -n
Cuya salida será:
commit file name size in bytes
72e1e6d20... db/players.sql 818314
ea20b964a... app/assets/images/background_final2.png 6739212
f8344b9b5... data_test/pg_xlog/000000010000000000000001 1625545
1ecc2395c... data_development/pg_xlog/000000010000000000000001 16777216
bc83d216d... app/assets/images/background_1forfinal.psd 95533848
La última entrada en la lista apunta al archivo más grande en tu historial de git.
Puedes usar esta salida para asegurarte de que no estás eliminando cosas con BFG hubieras necesitado en tu historial.
Paso 1 Escribe todos los archivos SHA1 en un archivo de texto:
git rev-list --objects --all | sort -k 2 > allfileshas.txt
Paso 2 Ordena los blobs de mayor a menor y escribe los resultados en un archivo de texto:
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
Paso 3a Combine ambos archivos de texto para obtener información sobre el nombre de archivo / sha1 / tamaño:
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;
Paso 3b Si tiene nombres de archivos o nombres de rutas que contienen espacios, pruebe esta variación del Paso 3a. Utiliza cut
lugar de awk
para obtener las columnas deseadas incl. espacios desde la columna 7 hasta el final de la línea:
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;
Ahora puedes mirar el archivo bigtosmall.txt para decidir qué archivos quieres eliminar de tu historial de Git.
Paso 4 Para realizar la eliminación (tenga en cuenta que esta parte es lenta ya que examinará cada confirmación en su historial para obtener datos sobre el archivo que identificó):
git filter-branch --tree-filter ''rm -f myLargeFile.log'' HEAD
Fuente
Los pasos 1-3a se copiaron desde Buscar y purgar archivos grandes del historial de Git
EDITAR
El artículo se eliminó en algún momento de la segunda mitad de 2017, pero aún se puede acceder a una copia archivada usando la Máquina Wayback .