Dado el hash de un blob, ¿hay alguna manera de obtener una lista de confirmaciones que tengan este blob en su árbol?
git
version-control
Solo lectura
fuente
fuente
git hash-object
osha1("blob " + filesize + "\0" + data)
, y no simplemente la suma de los contenidos del blob.git log --follow filepath
(y usar esto para acelerar la solución de Aristóteles, si lo desea).~/.bin
y asígnele un nombregit-find-object
. Luego puedes usarlo congit find-object
.git describe <hash>
: Vea mi respuesta a continuación .Respuestas:
Los siguientes scripts toman el SHA1 del blob como primer argumento, y después, opcionalmente, cualquier argumento que
git log
comprenda. Por ejemplo,--all
para buscar en todas las ramas en lugar de solo la actual, o-g
para buscar en el registro, o cualquier otra cosa que desee.Aquí es como un script de shell: corto y dulce, pero lento:
Y una versión optimizada en Perl, todavía bastante corta pero mucho más rápida:
fuente
git rev-parse --verify $theprefix
my $blob_arg = shift; open my $rev_parse, '-|', git => 'rev-parse' => '--verify', $blob_arg or die "Couldn't open pipe to git-rev-parse: $!\n"; my $obj_name = <$rev_parse>; chomp $obj_name; close $rev_parse or die "Couldn't expand passed blob.\n"; $obj_name eq $blob_arg or print "(full blob is $obj_name)\n";
obj_name="$1" shift git log --all --pretty=format:'%T %h %s %n' -- "$@" | while read tree commit cdate subject ; do if [ -z $tree ] ; then continue fi if git ls-tree -r $tree | grep -q "$obj_name" ; then echo "$cdate $commit $@ $subject" fi done
--all
como argumento adicional. (Encontrar todas las confirmaciones en todo el repositorio es importante en casos como eliminar un archivo grande del historial del repositorio ).Lamentablemente, los guiones fueron un poco lentos para mí, así que tuve que optimizar un poco. Afortunadamente, no solo tenía el hash sino también la ruta de un archivo.
fuente
<hash>
en el dado<path>
, entonces eliminar el<path>
argumento de lagit log
voluntad funcionará. El primer resultado devuelto es el commit deseado.Con Git 2.16 (Q1 2018),
git describe
sería una buena solución, ya que se le enseñó a excavar árboles más profundamente para encontrar uno<commit-ish>:<path>
que se refiera a un objeto blob dado.Consulte commit 644eb60 , commit 4dbc59a , commit cdaed0c , commit c87b653 , commit ce5b6f9 (16 de noviembre de 2017) y commit 91904f5 , commit 2deda00 (02 de noviembre de 2017) por Stefan Beller (
stefanbeller
) .(Fusionada por Junio C Hamano -
gitster
- en commit 556de1a , 28 dic 2017)Eso significa que la
git describe
página del manual se suma a los propósitos de este comando:Pero:
fuente
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2 -r | head -n 20
, lo que te devuelve los 20 blobs más grandes. Luego puede pasar ID de blob de la salida anterior agit describe
. Funcionó como un encanto! ¡Gracias!Pensé que esto sería algo generalmente útil, así que escribí un pequeño script en perl para hacerlo:
Pondré esto en Github cuando llegue a casa esta noche.
Actualización: Parece que alguien ya hizo esto . Ese usa la misma idea general pero los detalles son diferentes y la implementación es mucho más corta. ¡No sé cuál sería más rápido, pero el rendimiento probablemente no sea una preocupación aquí!
Actualización 2: por lo que vale, mi implementación es mucho más rápida, especialmente para un gran repositorio. Eso
git ls-tree -r
realmente duele.Actualización 3: debo tener en cuenta que mis comentarios de rendimiento anteriores se aplican a la implementación que vinculé anteriormente en la primera actualización. La implementación de Aristóteles es comparable a la mía. Más detalles en los comentarios para aquellos que tienen curiosidad.
fuente
git rev-parse $commit^{}
Si bien la pregunta original no lo solicita, creo que es útil verificar también el área de preparación para ver si se hace referencia a un blob. Modifiqué el script bash original para hacer esto y encontré lo que hacía referencia a un blob corrupto en mi repositorio:
fuente
Entonces ... necesitaba encontrar todos los archivos por encima de un límite dado en un repositorio de más de 8GB de tamaño, con más de 108,000 revisiones. Adapté el guión perl de Aristóteles junto con un guión rubí que escribí para llegar a esta solución completa.
Primero,
git gc
haga esto para asegurarse de que todos los objetos estén en paquetes de archivos, no escaneamos objetos que no estén en archivos de paquetes.A continuación, ejecute este script para localizar todos los blobs en CUTOFF_SIZE bytes. Capture la salida a un archivo como "large-blobs.log"
A continuación, edite el archivo para eliminar cualquier blob que no espere y los bits INPUT_THREAD en la parte superior. una vez que tenga solo líneas para los sha1 que desea encontrar, ejecute el siguiente script de esta manera:
Donde el
git-find-blob
guión está abajo.La salida se verá así:
Y así. Se enumerará cada confirmación que contenga un archivo grande en su árbol. Si
grep
sale de las líneas que comienzan con una pestaña, yuniq
así, tendrá una lista de todas las rutas que puede filtrar-ramificar para eliminar, o puede hacer algo más complicado.Permítanme reiterar: este proceso se ejecutó con éxito, en un repositorio de 10GB con 108,000 confirmaciones. Tomó mucho más tiempo de lo que predije cuando se ejecutó en una gran cantidad de blobs, sin embargo, durante 10 horas, tendré que ver si el bit de memorización está funcionando ...
fuente
-- --all
. (Encontrar todas las confirmaciones en todo el repositorio es importante en casos como eliminar completamente un archivo grande del historial del repositorio ).Además de
git describe
eso, lo menciono en mi respuesta anterior ,git log
ygit diff
ahora también se beneficia de la--find-object=<object-id>
opción " " para limitar los hallazgos a los cambios que involucran el objeto nombrado.Eso está en Git 2.16.x / 2.17 (Q1 2018)
Ver commit 4d8c51a , commit 5e50525 , commit 15af58c , commit cf63051 , commit c1ddc46 , commit 929ed70 (04 de enero de 2018) por Stefan Beller (
stefanbeller
) .(Fusionada por Junio C Hamano -
gitster
- en commit c0d75f0 , 23 ene 2018)fuente