Как найти предыдущих авторов всех измененных строк в git?

Учитывая диапазон коммитов, скажем HEAD~1 а также HEAD (т.е. просто HEAD), Я хочу найти предыдущих авторов строк, которые были изменены в этом диапазоне, и сколько строк они изменили.

Точнее: для каждой строки, которая была изменена в диапазоне, я хочу получить предыдущего автора (используя git blame, например). Затем я хочу сгруппировать по этим авторам, суммируя измененные строки.

Например, рассмотрим файл X, который был изменен этими людьми ранее HEAD (Я отметил людей, которые изменили строки в начале строки, сравнимо с git blame выходной):

Adam: Lorem ipsum dolor 
Adam: sit amet, consectetur
Adam: adipiscing elit.
Bob:  Praesent efficitur urna
Bob:  ac volutpat lacinia.
Bob:  Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.

Теперь автор Carl изменяет файл следующим образом (обратите внимание, что это смесь псевдокодов git blame а также git diff):

Adam: Lorem ipsum dolor 
Adam: sit amet, consectetur
- Adam: adipiscing elit.
+ Carl: adipiscing elit I love cats.
- Bob:  Praesent efficitur urna
+ Carl: Praesent efficitur urna :D
- Bob:  ac volutpat lacinia.
+ Carl: ac volutpat lacinia YOLO.
+ Carl: Added extra line, lol!
- Bob:  Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.

Таким образом, Карл изменил 2 строки из Боба, удалил одну строку из Боба и изменил одну строку из Адама. Таким образом, вывод моего скрипта должен быть:

Боб: 3 Адам: 1

Мое общее решение будет:

  1. Найти измененные диапазоны строк
  2. Передайте эти диапазоны с -L параметр для git blame запросить предыдущего автора
  3. Сделайте окончательную группировку самостоятельно, анализируя git blame вывод и подведение итогов.

В настоящее время я борюсь с 1.: получить диапазон строк, которые были изменены diff (в данном случае один диапазон 3,6). Когда у меня есть эти диапазоны, я могу передать их git blame -L чтобы получить предыдущих авторов этих строк. Так как я могу сделать git diff или другой инструмент git возвращает диапазон строк как числовой start,end пары?

1 ответ

Решение

Я не знаю, как заставить Git сделать это, но я взломал решение, чтобы разобрать вывод git diff чтобы получить значения, которые вам нужны.

Если вы бежите git diff -U0В верхней части каждого чанка вы увидите что-то вроде этого:

@@ -5,2 +5,3 @@

это означает, что 2 строки были удалены, начиная со строки 5, и 3 были добавлены туда. (The -U0 параметр для git diff скрывает все строки контекста, так что печатаются только те строки, которые действительно изменились. Без этого параметра номера строк были бы неверными.) Существует три различных сценария, которые могут возникнуть для данного блока: строки были добавлены, строки были удалены или строки были изменены (удалены и добавлены). Предыдущий пример показывает, что заголовок будет отображать для измененных строк. Добавленные строки будут выглядеть так:

@@ -5,0 +6,2 @@

Для вашего случая использования мы можем игнорировать такие строки. Удаленные строки будут выглядеть так:

@@ -5,5 +4,0 @@

Обратите внимание, что второе число в каждой паре является смещением, показывающим, сколько строк было добавлено / удалено. К счастью, git blame также может принять смещение для <end> значение, поэтому мы можем втиснуть это в формат, который git blame могу принять.

Вот одна строчка bash, которая должна добиться цели:

git diff -U0 HEAD~1 -- $file | grep "^@@" | grep -Ev "@@ -[[:digit:]]+,0" | sed 's/^@@ //' | sed 's/ @@.*//' | cut -d' ' -f 1 | sed 's/[+-]//' | awk '{ if ($1 !~ /,/) { print $1",1" } else { print $1 } }' | sed 's/,/,+/'

Объяснение:

  • $file текущий файл, который вы обрабатываете.

  • Первый grep команда ограничивает вывод заголовками чанка, а вторая grep Команда удаляет фрагменты, представляющие добавленные строки.

  • Первые два sed Команды удаляют все, кроме номеров строк диапазона.

  • cut используется для получения первого значения диапазона, то есть линий, которые существовали в HEAD~1 которые не существуют в HEAD,

  • Следующий sed команда раздевает ведущий статус персонажа.

  • Если только одна строка добавлена ​​или удалена в данном чанке, git diff будет использовать, например, +2 как диапазон вместо +2,1, awk команда исправляет это.

  • Наконец, последний sed команда заменяет , с ,+ чтобы git blame знает, что второе значение является смещением вместо номера строки.

Вы можете использовать каждую строку вывода одной строки (сохраняются, например, в $row) следующее:

git blame -L$row HEAD~1 -- $file
Другие вопросы по тегам