Git: ¿Cómo puedo encontrar un commit que se acerque más a un directorio?


Alguien tomó una versión (desconocida para mí) de Moodle, aplicó muchos cambios dentro de un directorio, y la liberó (árbol aquí).

¿Cómo puedo determinar qué commit del proyecto original se editó más probablemente para formar este árbol?

Esto me permitiría formar una rama en el commit apropiado con este parche. Seguramente vino de cualquiera de los 1.8 o 1.9 ramas, probablemente de una etiqueta de lanzamiento, pero difiriendo entre confirmaciones particulares no me ayuda mucho.

Actualización Postmortem: la respuesta de knittl me ha acercado tanto como voy a acercarme. Primero agregué mi repositorio de parches como el remoto "extranjero" (no hay confirmaciones en común, eso está bien), luego hice diffs en bucles con un par de opciones de formato. El primero usó el formato --shortstat:

for REV in $(git rev-list v1.9.0^..v1.9.5); do 
    git diff --shortstat "$REV" f7f7ad53c8839b8ea4e7 -- mod/assignment >> ~/rdiffs.txt; 
    echo "$REV" >> ~/rdiffs.txt; 
done;

El segundo acaba de contar los cambios de línea en un diff unificado sin contexto:

for REV in $(git rev-list v1.9.0^..v1.9.5); do 
    git diff -U0 "$REV" f7f7ad53c8839b8ea4e7 -- mod/assignment | wc -l >> ~/rdiffs2.txt;
    echo "$REV" >> ~/rdiffs2.txt; 
done;

Había miles de confirmaciones que investigar, pero este parece ser el partido más cercano.

Author: Community, 2011-06-17

4 answers

Puede escribir un script, que difunde el árbol dado contra un rango de revisiones en su repositorio.

Supongamos que primero recuperamos el árbol cambiado (sin historial) en nuestro propio repositorio:

git remote add foreign git://…
git fetch foreign

Luego emitimos el diffstat (en forma corta) para cada revisión contra la que queremos coincidir:

for REV in $(git rev-list 1.8^..1.9); do
   git diff --shortstat foreign/master $REV;
done

Busca la confirmación con la menor cantidad de cambios (o usa algún mecanismo de clasificación)

 11
Author: knittl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 16:19:14

Esta fue mi solución:

#!/bin/sh

start_date="2012-03-01"
end_date="2012-06-01"
needle_ref="aaa"

echo "" > /tmp/script.out;
shas=$(git log --oneline --all --after="$start_date" --until="$end_date" | cut -d' ' -f 1)
for sha in $shas
do
    wc=$(git diff --name-only "$needle_ref" "$sha" | wc -l)
    wc=$(printf %04d $wc);
    echo "$wc $sha" >> /tmp/script.out
done
cat /tmp/script.out | grep -v ^$ | sort | head -5
 1
Author: mattalxndr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-13 05:01:03

Qué tal usar git para crear un parche a partir de todas las versiones de 1.8. y 1.9 a esta nueva versión. Entonces usted podría ver qué parche tiene más 'sentido'.

Por ejemplo, si el parche 'elimina' muchos métodos, entonces probablemente no es esta versión, sino una anterior. Si el parche tiene muchas secciones que no tienen sentido como una sola edición, entonces probablemente no sea esta versión tampoco.

Y así sucesivamente... En realidad, desafortunadamente, no existe un algoritmo para hacer esto perfectamente. Voy a tener para ser heurístico.

 0
Author: rafalotufo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 16:57:02

¿Qué tal usar 'git blame'? Le mostrará, para cada línea, quién lo cambió y en qué revisión.

 -2
Author: rafalotufo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 15:49:07