2012-07-23 30 views
6

Me gustaría obtener una receta para encontrar cambios duplicados. patch-id es probable que sea el mismo, pero los atributos de confirmación pueden no serlo.git encontrar commits duplicados (por id-parche)

Esto parece ser un uso previsto de patch-id:

git patch-id --help

OIA, puede utilizar esta cosa a buscar es probable duplicado compromete.

Imagino que encadenar "git log", "git patch-id" y uniq podría hacer el trabajo mal pero si alguien tiene un comando que hace bien el trabajo , se lo agradecería.

+0

Esta es una característica fascinante. Por curiosidad, ¿qué tan atrás en el pasado pretendes mirar? Pude ver algunos usos de integración creativa para esto (es decir, "mi colaborador no sabe cómo volver a establecer la base"), pero a lo largo de la historia sería menos eficaz ...? – Christopher

+0

El problema apareció en una historia de una rama de una semana, por lo que mi caso de uso fue bastante amable (git log -p fue suficiente). El comentario del id del parche me dio curiosidad, sin embargo ... Buscar toda la historia podría ser doloroso. – bsb

Respuesta

10

Debido a los cambios duplicados son probablemente no en la misma rama (excepto cuando hay revierte entre ellos), usted podría utilizar git cherry:

git cherry [-v] [<upstream> [<head> [<limit>]]] 

Dónde upstream sería la rama para comprobar si hay duplicados de cambios en head.

2

tengo un proyecto que funciona en un acuerdo de recompra juguete, pero ya que mantiene la patch-> cometer un mapa de memoria que podría haber problemas en grandes repositorios:

# print commit pairs with the same patch-id 
for c in $(git rev-list HEAD); do \ 
    git show $c | git patch-id; done \ 
| perl -anle '($p,$c)[email protected];print "$c $s{$p}" if $s{$p};$s{$p}=$c' 

La salida debe ser pares de confirmaciones con el mismo ID de parche (3 duplicados ABC salen como "AB" luego "BC").

cambiar el comando git rev-list para restringir las confirmaciones verificado:

git log --format=%H HEAD somefile 

Añadir "| xargs git show" para ver las confirmaciones en detalle, o "| xargs muestran git -s --oneline "para un resumen:

0569473 add 6-8 
5e56314 add 6-8 again 
bece3c3 comment 
e037ed6 add comment again 

resulta patch-id no funcionó en mi caso original como hubo cambios adicionales en que luego cometer. "git log -S" fue más útil.

+0

Si quiere ver solo las diferencias crudas entre una confirmación y su padre, podría hacer algo como 'git diff $ c ~ 1 $ c | git patch-id'. Va a portarse mal en los commit de fusión. Seguir a ambos padres fusionarse es un problema más complejo. – Christopher

+0

Parece que patch-id encuentra la misma diferencia? $ git diff CABEZA ~ 1 CABEZA | git patch-id 3318362fa07e580 .. 000000000000 .. $ git show HEAD | git patch-id 3318362fa07e580 .. c397c4cdc426 .. – bsb

+0

@bsb ¿Estás seguro de que querías escribir 'git show $ c | git patch-id'? 'git show' imprime metadatos, pero' git patch-id' necesita un parche como entrada ... –

7

Para buscar duplicados de una confirmación específica, esto puede funcionar para usted.

primer lugar, determinar el ID de parche del objetivo cometer:

$ THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF='7a3e67c' 
$ git show $THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF | git patch-id 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3 

La primera SHA es el parche-id.A continuación, una lista de los ID de parche para cada confirmación y filtrar cualquier ese partido:

$ for c in $(git rev-list --all); do git show $c | git patch-id; done | grep 'f6ea51cd6acd30cd627ce1a56e2733c1777d5b52' 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 5028e2b5500bd5f4637531e337e17b73f5d0c0b1 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3 
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 929c66b5783a0127a7689020d70d398f095b9e00 

Todos juntos, con algunas banderas adicionales, y en la forma de un utility script: Uso

test ! -z "$1" && TARGET_COMMIT_SHA="$1" || TARGET_COMMIT_SHA="HEAD" 

TARGET_COMMIT_PATCHID=$(
git show --patch-with-raw "$TARGET_COMMIT_SHA" | 
    git patch-id | 
    cut -d' ' -f1 
) 
MATCHING_COMMIT_SHAS=$(
for c in $(git rev-list --all); do 
    git show --patch-with-raw "$c" | 
     git patch-id 
done | 
    fgrep "$TARGET_COMMIT_PATCHID" | 
    cut -d' ' -f2 
) 

echo "$MATCHING_COMMIT_SHAS" 

:

$ git list-dupe-commits 7a3e67c 
5028e2b5500bd5f4637531e337e17b73f5d0c0b1 
7a3e67ce38dbef471889d9f706b9161da7dc5cf3 
929c66b5783a0127a7689020d70d398f095b9e00 

no es terriblemente rápido, pero para la mayoría de las cesiones temporales deben hacer el trabajo (solo mide 36 segundos para un acuerdo de recompra con 826 confirmaciones y un 158MB .git dir en un 2,4 GHz Core 2 Duo).

+0

Puede que yo sea el único confundido, pero por si acaso, "compromiso de destino" no es literal; reemplácelo con el SHA de la confirmación para la que desea obtener una ID de parche. – Jimothy

+1

@Jimothy Yep, o un nombre de rama o una etiqueta (cualquier referencia, supongo). Veré si puedo aclararlo un poco. –

2

El comando ingenioso sugerido por bsb requiere un par de pequeños retoques:

(1) En lugar de git show, que se extiende git diff-tree --cc, el comando debe utilizar

git diff-tree -p 

De lo contrario git patch-id genera hashes nula SHA1 espurias .

(2) Cuando se utiliza la tubería a xargs, xargs debe tener el argumento -L 1. De lo contrario, una confirmación por triplicado no se emparejará con una confirmación equivalente.

Aquí es un alias para ir en ~/.gitconfig:

dup = "!f() { for c in $(git rev-list HEAD); do git diff-tree -p $c | git patch-id; done | perl -anle '($p,$c)[email protected];print \"$c $s{$p}\" if $s{$p};$s{$p}=$c' | xargs -L 1 git show -s --oneline; }; f" # "git dup" lists duplicate commits 
0

Para buscar confirmaciones duplicadas de cometer $hash, con exclusión de combinación se compromete:

git rev-list --no-merges --all | xargs -r git show | git patch-id \ 
    | grep ^$(git show $hash|git patch-id|cut -c1-40) | cut -c42-80 \ 
    | xargs -r git show -s --oneline 

Para buscar el duplicado de una combinación de cometer $mergehash, reemplace $(git show $hash|git patch-id|cut -c1-40) anterior por uno de los dos ID de parche (1ª columna) dado por git diff-tree -m -p $mergehash | git patch-id. Corresponden a los diffs de la fusión se comprometen con cada uno de sus dos padres.

para encontrar duplicados de todas las confirmaciones, con exclusión de combinación se compromete:

git rev-list --no-merges --all | xargs -r git show | git patch-id \ 
    | sort | uniq -w40 -D | cut -c42-80 \ 
    | xargs -r git log --no-walk --pretty=format:"%h %ad %an (%cn) %s" --date-order --date=iso 

La búsqueda para las confirmaciones duplicadas puede ser extendido o limitado por el cambio de los argumentos a git rev-list, que acepta numerosas opciones. Por ejemplo, para limitar la búsqueda a una rama específica, especifique su nombre en lugar de la opción --all; o para buscar en los últimos 100 commits, pase los argumentos HEAD ^HEAD~100.

Tenga en cuenta que estos comandos son rápidos ya que no utilizan ningún bucle de shell y los procesos por lotes se comprometen.

Para incluir las asignaciones de fusión, elimine la opción --no-merges, y reemplace xargs -r git show por xargs -r -L1 git diff-tree -m -p. Esto es mucho más lento porque git diff-tree se ejecuta una vez por confirmación.

Explicación:

  • La primera línea genera un mapa de los ID de parche con los hashes cometer (datos 2-columna, de 40 caracteres cada uno).

  • La segunda línea solo mantiene hashes de confirmación (2da columna) correspondientes a los ID de parche duplicados (1ra columna).

  • La última línea imprime información personalizada sobre las confirmaciones duplicadas.

Cuestiones relacionadas