¿Cómo puedo identificar y enumerar trozos únicos en un commit de git?

Tengo un compromiso con un gran número (cientos) de trozos similares, y me gustaría enumerar cada trozo único en la confirmación para compararlos.

Escribí el siguiente script de GNU awk, que escribe cada trozo en un file único ( hunk-[md5-of-hunk].txt ):

 BEGIN { hunk = "" buildhunk = 0 } function writeHunk() { if (length(hunk) > 0) { print hunk > "hunk.tmp" close("hunk.tmp") cmd = "cat hunk.tmp | md5" cmd | getline md5 close(cmd) if (!(md5 in hunkfiles)) { hunkfilename = "hunk-" md5 ".txt" print hunk > hunkfilename hunkfiles[md5] = hunkfilename } } } /^@@|^diff/ { writeHunk() hunk = "" buildhunk = ($1 == "@@") ? 1 : 0 } /^[ +-]/ { if (buildhunk) { hunk = hunk $0 "\n" } } END { writeHunk() system("rm hunk.tmp") for (md5 in hunkfiles) { print hunkfiles[md5] } } 

Luego corro esto con git show [commit-SHA] | awk -f my_script.awk git show [commit-SHA] | awk -f my_script.awk , que crea y enumera los files resultantes. Funciona para mis propósitos, pero ¿hay alguna manera de hacer esto de manera más eficiente usando los commands de plomería de git?

Ejemplo

Supongamos que el parche de confirmación se ve así (networkingucido a 1 línea de context a continuación por motivos de claridad):

 diff --git a/file1.txt b/file1.txt index a3fb2ed..4d6f587 100644 --- a/file1.txt +++ b/file1.txt @@ -3,2 +3,3 @@ context context +added line context @@ -7,2 +8,3 @@ context context +added line context @@ -11,2 +13,3 @@ context context +added line context @@ -15,2 +18,3 @@ context context +different added line context @@ -19,2 +23,3 @@ context context +different added line context @@ -23,2 +28,3 @@ context context +different added line context @@ -27,2 +33,3 @@ context context +even more different added line context @@ -31,2 +38,3 @@ context context +even more different added line context 

Quiero ser capaz de identificar que solo hay 3 types únicos y ver qué son. A saber:

Único trozo 1:

  context +added line context 

Único trozo 2:

  context +different added line context 

Trozo único 3:

  context +even more different added line context 

Los commits son snapshots , y como tales, no tienen diff hunks.

Diffs, por supuesto, tienen diff hunks. Entonces, si solo tienes una confirmación, no puedes hacer esto en absoluto. Necesitas dos commits. Entonces simplemente difúndelos y haz lo que estás haciendo.

Tenga en count que git show <commit-hash> realmente significa git diff <parent or parents of commit> <commit-hash> . Si la confirmación especificada es una confirmación de fusión, esto produce una diferencia combinada , que probablemente no sea útil para sus propósitos, ya que las diferencias combinadas omiten deliberadamente muchos cambios por completo. Es posible que desee ejecutar una diferencia explícita frente al primer padre del compromiso solamente (para ver solo los cambios introducidos como parte de la fusión).

Hay algunas partes de Git que hacen internamente algo como lo que estás haciendo, para git rerere y git patch-id . Sin embargo, no hacen exactamente lo que estás haciendo: por rerere , registran solo rerere diff donde hubo un conflicto de fusión, y hacen coincidir esos trozos de diferencias (guardados por ID de troceo y nombre de file) con las resoluciones registradas más tarde. Para patch-id , quitan los numbers de línea y el espacio en blanco, pero acumulan todo el set de cambios de un compromiso en una gran pieza. Sería bueno si Git tuviera un poco de plomería que hiciera git patch-id parte hunk por hunk, independientemente de calcular el ID del parche para la confirmación, pero no es así.