Как мне определить и перечислить уникальные фрагменты в коммите git?

У меня есть коммит с большим количеством (сотнями) подобных блоков, и я хотел бы перечислить каждый уникальный блок в коммите, чтобы сравнить их.

Я написал следующий скрипт GNU awk, который записывает каждый кусок в уникальный файл (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]
  }
}

Затем я запускаю это с git show [commit-SHA] | awk -f my_script.awk, который создает и выводит список полученных файлов. Это работает для моих целей, но есть ли способ сделать это более эффективно, используя команды git.

пример

Предположим, что патч для коммита выглядит так (для ясности ниже приведена 1 строка контекста):

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

Я хочу быть в состоянии идентифицировать, что есть только 3 уникальных куска, и видеть, что они. А именно:

Уникальный кусок 1:

 context
+added line
 context

Уникальный кусок 2:

 context
+different added line
 context

Уникальный лом 3:

 context
+even more different added line
 context

1 ответ

Решение

Коммиты - это моментальные снимки, и поэтому они не имеют различий.

Различия, конечно же, имеют разный интерес. Так что, если у вас есть только один коммит, вы не можете сделать это вообще. Вам нужно два коммита. Вы тогда просто отличаете их и делаете то, что делаете.

Обратите внимание, что git show <commit-hash> действительно означает git diff <parent or parents of commit> <commit-hash>, Если указанный коммит является коммитом слияния, он создает комбинированный дифференциал, который, вероятно, бесполезен для ваших целей, так как комбинированный дифференциал намеренно полностью пропускает многие изменения. Возможно, вы захотите запустить явный diff только для первого родителя коммита (чтобы просмотреть только изменения, внесенные как часть слияния).

Есть некоторые части Git, которые внутренне делают что-то вроде того, что вы делаете, для git rerere а также git patch-id, Тем не менее, они не делают именно то, что вы делаете: для rerere они записывают только блоки различий, где произошел конфликт слияния, и сопоставляют эти блоки различий (сохраненные по идентификатору хэша и имени файла) с разрешениями, записанными позже. За patch-id они убирают номера строк и пробелы, но накапливают весь набор изменений из коммита в один большой кусок. Было бы хорошо, если бы у Git было немного слесарного дела, которое сделало git patch-id от части к фрагменту, независимо от вычисления общего идентификатора патча для фиксации, но это не так.

Другие вопросы по тегам