¿Qué compromiso tiene este blob?
Dado el hash de un blob, ¿hay alguna manera de obtener una lista de confirmaciones que tienen este blob en su árbol?
Los dos scripts siguientes toman el SHA1 del blob como primer argumento y, después, opcionalmente, cualquier argumento que git log
se entienda. Por ejemplo, --all
buscar en todas las ramas en lugar de solo en la actual, o -g
buscar en el reflog, o cualquier otra cosa que desee.
Aquí está como un script de shell: breve y sencillo, pero lento:
#!/bin/sh
obj_name="$1"
shift
git log "$@" --pretty=tformat:'%T %h %s' \
| while read tree commit subject ; do
if git ls-tree -r $tree | grep -q "$obj_name" ; then
echo $commit "$subject"
fi
done
Y una versión optimizada en Perl, todavía bastante corta pero mucho más rápida:
#!/usr/bin/perl
use 5.008;
use strict;
use Memoize;
my $obj_name;
sub check_tree {
my ( $tree ) = @_;
my @subtree;
{
open my $ls_tree, '-|', git => 'ls-tree' => $tree
or die "Couldn't open pipe to git-ls-tree: $!\n";
while ( <$ls_tree> ) {
/\A[0-7]{6} (\S+) (\S+)/
or die "unexpected git-ls-tree output";
return 1 if $2 eq $obj_name;
push @subtree, $2 if $1 eq 'tree';
}
}
check_tree( $_ ) && return 1 for @subtree;
return;
}
memoize 'check_tree';
die "usage: git-find-blob <blob> [<git-log arguments ...>]\n"
if not @ARGV;
my $obj_short = shift @ARGV;
$obj_name = do {
local $ENV{'OBJ_NAME'} = $obj_short;
`git rev-parse --verify \$OBJ_NAME`;
} or die "Couldn't parse $obj_short: $!\n";
chomp $obj_name;
open my $log, '-|', git => log => @ARGV, '--pretty=format:%T %h %s'
or die "Couldn't open pipe to git-log: $!\n";
while ( <$log> ) {
chomp;
my ( $tree, $commit, $subject ) = split " ", $_, 3;
print "$commit $subject\n" if check_tree( $tree );
}
Para los humanos, el comando más útil es probablemente
git log --raw --all --find-object=<blob hash>
Esto muestra, en todas --all
las ramas, cualquier confirmación que haya agregado o eliminado un archivo con ese hash, junto con la ruta.
$ git log --raw --all --find-object=b3bb59f06644
commit 8ef93124645f89c45c9ec3edd3b268b38154061a
⋮
diff: do not show submodule with untracked files as "-dirty"
⋮
:100644 100644 b3bb59f06644 8f6227c993a5 M submodule.c
commit 7091499bc0a9bccd81a1c864de7b5f87a366480e
⋮
Revert "submodules: fix of regression on fetching of non-init subsub-repo"
⋮
:100644 100644 eef5204e641e b3bb59f06644 M submodule.c
La --raw
opción le dice a git que incluya los hashes del blob antes y después en sus líneas de salida.
Desafortunadamente, los scripts eran un poco lentos para mí, así que tuve que optimizarlos un poco. Por suerte no sólo tenía el hash sino también la ruta de un archivo.
git log --all --pretty=format:%H -- <path> | xargs -I% sh -c "git ls-tree % -- <path> | grep -q <hash> && echo %"
Además de git describe
lo que mencioné en mi respuesta anterior , git log
ahora git diff
también se beneficia de la --find-object=<object-id>
opción " " para limitar los hallazgos a cambios que involucran el objeto nombrado.
Eso está en Git 2.16.x/2.17 (primer trimestre de 2018)
Consulte el compromiso 4d8c51a , el compromiso 5e50525 , el compromiso 15af58c , el compromiso cf63051 , el compromiso c1ddc46 , el compromiso 929ed70 (4 de enero de 2018) por Stefan Beller ( stefanbeller
) .
(Fusionado por Junio C Hamano -- gitster
-- en la confirmación c0d75f0 , 23 de enero de 2018)
diffcore
: agrega una opción de pico para encontrar una mancha específica
A veces, los usuarios reciben un hash de un objeto y quieren identificarlo más (por ejemplo: use el paquete de verificación para encontrar los blobs más grandes, pero ¿qué son? O esta pregunta de desbordamiento de pila "¿ Qué confirmación tiene este blob? ").
Uno podría verse tentado a ampliar
git-describe
el trabajo también con blobs, de modo quegit describe <blob-id>
se describa como '<commit-ish>:<path>
'.
Esto se implementó aquí ; Como se ve por la gran cantidad de respuestas (>110), resulta que es complicado hacerlo bien.
La parte difícil de acertar es elegir el 'compromiso' correcto, ya que podría ser el compromiso que (re)introdujo el blob o el blob que eliminó el blob; el blob podría existir en diferentes ramas.Junio insinuó un enfoque diferente para resolver este problema, que implementa este parche.
Enseñe a ladiff
maquinaria otra bandera para restringir la información a lo que se muestra.
Por ejemplo:$ ./git log --oneline --find-object=v2.0.0:Makefile b2feb64 Revert the whole "ask curl-config" topic for now 47fbfde i18n: only extract comments marked with "TRANSLATORS:"
observamos que el
Makefile
contenido enviado2.0
apareció env1.9.2-471-g47fbfded53
y env2.0.0-rc1-5-gb2feb6430b
.
La razón por la cual estas confirmaciones ocurren antes de la versión 2.0.0 son fusiones malvadas que no se encuentran usando este nuevo mecanismo.
Como se indica en los comentarios de marcono1234 , puedes combinar eso con la opción git log --all :
Esto puede resultar útil cuando no sabes qué rama contiene el objeto.