¿Qué compromiso tiene este blob?

Resuelto readonly asked hace 16 años • 8 respuestas

Dado el hash de un blob, ¿hay alguna manera de obtener una lista de confirmaciones que tienen este blob en su árbol?

readonly avatar Oct 22 '08 05:10 readonly
Aceptado

Los dos scripts siguientes toman el SHA1 del blob como primer argumento y, después, opcionalmente, cualquier argumento que git logse entienda. Por ejemplo, --allbuscar en todas las ramas en lugar de solo en la actual, o -gbuscar 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 );
}
Aristotle Pagaltzis avatar Oct 21 '2008 23:10 Aristotle Pagaltzis

Para los humanos, el comando más útil es probablemente

git log --raw --all --find-object=<blob hash>

Esto muestra, en todas --alllas 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 --rawopción le dice a git que incluya los hashes del blob antes y después en sus líneas de salida.

andrewdotn avatar Mar 16 '2021 19:03 andrewdotn

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 %"
aragaer avatar Sep 16 '2015 14:09 aragaer

Además de git describelo que mencioné en mi respuesta anterior , git logahora git difftambié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-describeel trabajo también con blobs, de modo que git 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 la diffmaquinaria 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 Makefilecontenido enviado 2.0apareció en v1.9.2-471-g47fbfded53y en v2.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.

VonC avatar Feb 02 '2018 20:02 VonC