Опция трейлеров в git --pretty option
Я пытался извлечь сводку вкладов из журнала git, составить краткое изложение этого и создать на его основе excel / csv для представления отчетов.
Я действительно пробовал
git log --after="2020-12-10" --pretty=format:'"%h","%an","%ae","%aD","%s","(trailers:key="Reviewed By")"'
и CSV выглядит с пустым столбцом CSV в конце.
...
"7c87963cc","XYZ","[email protected]","Tue Dec 8 17:40:13 2020 +0000","[TTI] Add support for target hook in compiler.", ""
...
и git log
выглядит что-то вроде
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed By: Sushant
Differential Revision: https://codereviews.com/DD8822
Что мне не удалось, так это извлечь Differential Revision
строку с помощью (trailers:key="Reviewed By")
команды.
Я не мог найти много информации о том, как заставить это работать. Я проверил руководство по git и попробовал то, что он объясняет.
Что-то мне может не хватать в этой команде? Ожидаемый вывод должен содержать текст https://codereviews.com/DD8822
в последней позиции в приведенном выше выводе CVS.
Ответы
Я не уверен, но:
- ключи трейлера не могут иметь пробелов (поэтому
Reviewed By
->Reviewed-By
иDifferential Revision
->Differential-Revision
); - трейлеры не должны быть разделены новыми строками, а должны быть отделены от сообщения фиксации фиксации (поэтому
Reviewed By
из вашего вопроса не рассматривается как трейлер).
Я бы также не рекомендовал использовать CSV, но вместо этого использовал TSV: git output не знает синтаксиса CSV (экранирование точек с запятой и запятых), поэтому выходной документ может быть сгенерирован без возможности анализа.
Если ваши сообщения фиксации будут выглядеть так ( -
вместо пробелов, без разделителей новой строки):
commit 7c87963cc
Author: XYZ <[email protected]>
Date: Tue Dec 8 17:40:13 2020 +0000
[TTI] Add support for target hook in compiler.
This adds some code in the TabeleGen ...
This is my body of commit.
Reviewed-By: Sushant
Differential-Revision: https://codereviews.com/DD8822
Тогда вам подойдет следующая команда:
git log --pretty=format:'%h%x09%an%x09%ae%x09%aD%x09%s%x09%(trailers:key=Reviewed-By,separator=%x20,valueonly)%x09%(trailers:key=Differential-Revision,separator=%x20,valueonly)'
создание короткого идентификатора фиксации, имени автора, адреса электронной почты автора, даты, сообщения фиксации, трейлера Reviewed-By
и трейлера Differential-Revision
для вывода значений, разделенных табуляцией.
Если вы не можете изменить старые сообщения фиксации , потому что ваша история не является безопасной для этого (она опубликована, запряженных коллег, ваши инструменты связаны с опубликованным совершить хэш), то вы должны обработать git log
вывод с sed
, awk
, perl
, или любым другой инструмент преобразования текста для создания вашего отчета. Скажем, обработайте что-то вроде того, git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B'
где строки между ^B
(STX) и EOF должны быть как-то проанализированы (отфильтрованы для интересующих вас трейлеров), затем присоединены к их групповым строкам, начиная с ^B
, а затем заменены символы, чтобы заменить разделители полей и записей на \t
и нет характер соответственно.
Но опять же, если вы можете редактировать историю, исправляя трейлеры сообщений фиксации (не уверен, насколько это может повлиять), я бы порекомендовал вам сделать это, а затем отвергнуть идею дополнительных трейлеров обработки скриптов, которые не распознаются, git-interpret-trailers
и просто исправить зафиксировать сообщения.
Редактировать 1 (текстовые инструменты)
Если переписывание истории невозможно, то реализация некоторых сценариев может вам помочь. Я довольно слаб в написании мощных скриптов sed
/ awk
/ perl
, но позвольте мне попробовать.
git log --pretty=format:'%x02%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%n%B' \
| gawk -f trailers.awk \
| sed '$!N;s/\n/\x1F/' \
| sed 's/[\x02\x1E]//g' \
| sed 's/\x1F/\x09/g'
Как это работает:
git
генерирует журнал, состоящий из данных, разделенных стандартными кодами C0 C1, предполагая, что таких символов нет в ваших сообщениях фиксации (STX, RS и US - я действительно не знаю, хорошее ли это место для их использования, и если я их применяю семантически корректно);gawk
фильтрует вывод журнала, пытаясь проанализировать группы, запущенные STX, и извлечь трейлеры, генерируя «двухстрочный» вывод (каждая нечетная строка для обычных данных, каждая четная строка для значений трейлера, соединенных запятыми, даже для отсутствующих трейлеров);sed
объединяет нечетные и четные строки попарно (кредиты принадлежат Кароли Хорвату );sed
убирает STX и RS;sed
заменяет US на TAB.
Вот trailers.awk
(опять же, я не awk
парень и понятия не имею, насколько идиоматичен следующий сценарий, но, похоже, он работает):
#!/usr/bin/awk -f
BEGIN {
FIRST = 1
delete TRAILERS
}
function print_joined_array(array) {
if ( !length(array) ) {
return
}
for ( i in array ) {
if ( i > 0 ) {
printf(",")
}
printf("%s", array[i])
}
printf("\x1F")
}
function print_trailers() {
if ( FIRST ) {
FIRST = 0
return
}
print_joined_array(TRAILERS["Reviewed By"])
print_joined_array(TRAILERS["Differential Revision"])
print ""
}
/^\x02/ {
print_trailers()
print $0
delete TRAILERS
}
match($0, /^([-_ A-Za-z0-9]+):\s+(.*)\s*/, M) {
TRAILERS[M[1]][length(TRAILERS[M[1]])] = M[2]
}
END {
print_trailers()
}
Пару слов о том, как awk
работает скрипт:
- предполагается, что записи, не требующие обработки, начинаются с STX;
- он пытается найти
grep
каждую строку, отличную от STX, дляKey Name: Value
шаблона и сохраняет найденный результат во временный массивTRAILERS
(который фактически служит мульти-картой, какMap<String, List<String>>
в Java) для каждой записи; - каждая запись записывается как есть, но трейлеры записываются либо до обнаружения новой записи, либо при EOF.
Редактировать 2 (лучше awk
)
Что ж, я очень слаб в этом awk
, поэтому, как только я awk
узнал больше о внутренних переменных, я понял, что awk
скрипт можно полностью переопределить и создать готовый к использованию TSV-подобный вывод без какой-либо пост-обработки с помощью sed
или perl
. Итак, более короткая и улучшенная версия сценария:
#!/bin/bash
git log --pretty=format:'%x1E%h%x1F%an%x1F%ae%x1F%aD%x1F%s%x1F%B%x1E' \
| gawk -f trailers.awk
#!/usr/bin/awk -f
BEGIN {
RS = "\x1E"
FS = "\x1F"
OFS = "\x09"
}
function extract(array, trailer_key, __buffer) {
for ( i in array ) {
if ( index(array[i], trailer_key) > 0 ) {
if ( length(__buffer) > 0 ) {
__buffer = __buffer ","
}
__buffer = __buffer substr(array[i], length(trailer_key))
}
}
return __buffer
}
NF > 1 {
split($6, array, "\n")
print $1, $2, $3, $4, $5, extract(array, "Reviewed By: "), extract(array, "Differential Revision: ")
}
Намного более кратко, легче читать, понимать и поддерживать.