Как получить Git журнал с коротким статом в одной строке?
Следующие команды выводят следующие строки текста на консоли
git log --pretty=format:"%h;%ai;%s" --shortstat
ed6e0ab;2014-01-07 16:32:39 +0530;Foo
3 files changed, 14 insertions(+), 13 deletions(-)
cdfbb10;2014-01-07 14:59:48 +0530;Bar
1 file changed, 21 insertions(+)
5fde3e1;2014-01-06 17:26:40 +0530;Merge Baz
772b277;2014-01-06 17:09:42 +0530;Qux
7 files changed, 72 insertions(+), 7 deletions(-)
Я заинтересован в том, чтобы над форматом отображаться следующим образом
ed6e0ab;2014-01-07 16:32:39 +0530;Foo;3;14;13
cdfbb10;2014-01-07 14:59:48 +0530;Bar;1;21;0
5fde3e1;2014-01-06 17:26:40 +0530;Merge Baz;0;0;0
772b277;2014-01-06 17:09:42 +0530;Qux;7;72;7
Это будет потребляться в некотором отчете, который может анализировать значения, разделенные точкой с запятой.
Дело в тексте "\n 3 files changed, 14 insertions(+), 13 deletions(-)"
(новая строка включена) преобразуется в 3;14;13
(без новой строки)
Одним из возможных угловых случаев является текст типа "5fde3e1;2014-01-06 17:26:40 +0530;Merge Baz"
, который не имеет такой строки. В этом случае я хочу ;0;0;0
В целом цель состоит в том, чтобы анализировать статистику изменений файлов в течение определенного периода времени.
Я прочитал документацию журнала git, но не смог найти какой-либо формат, который поможет мне отобразить в этом формате. Лучшее, что я придумал, было упомянутой выше командой.
Таким образом, любая команда или оболочка script, которая может генерировать ожидаемый формат, будет очень полезной.
Спасибо!
Ответы
Ответ 1
К сожалению, этого достичь невозможно, используя только git log
. Нужно использовать другие скрипты, чтобы компенсировать то, о чем большинство людей не знает: некоторые коммиты не имеют статистики, даже если они не сливаются.
Я работаю над проектом, который преобразует git log
в JSON
, и для его выполнения мне нужно было сделать то, что вам нужно: получить каждую фиксацию со статистикой в одной строке. Проект называется Gitlogg, и вы можете настроить его на свои нужды: https://github.com/dreamyguy/gitlogg
Ниже приведена соответствующая часть Gitlogg, которая поможет вам приблизиться к тому, что вы хотите:
git log --all --no-merges --shortstat --reverse --pretty=format:'commits\tcommit_hash\t%H\tcommit_hash_abbreviated\t%h\ttree_hash\t%T\ttree_hash_abbreviated\t%t\tparent_hashes\t%P\tparent_hashes_abbreviated\t%p\tauthor_name\t%an\tauthor_name_mailmap\t%aN\tauthor_email\t%ae\tauthor_email_mailmap\t%aE\tauthor_date\t%ad\tauthor_date_RFC2822\t%aD\tauthor_date_relative\t%ar\tauthor_date_unix_timestamp\t%at\tauthor_date_iso_8601\t%ai\tauthor_date_iso_8601_strict\t%aI\tcommitter_name\t%cn\tcommitter_name_mailmap\t%cN\tcommitter_email\t%ce\tcommitter_email_mailmap\t%cE\tcommitter_date\t%cd\tcommitter_date_RFC2822\t%cD\tcommitter_date_relative\t%cr\tcommitter_date_unix_timestamp\t%ct\tcommitter_date_iso_8601\t%ci\tcommitter_date_iso_8601_strict\t%cI\tref_names\t%d\tref_names_no_wrapping\t%D\tencoding\t%e\tsubject\t%s\tsubject_sanitized\t%f\tcommit_notes\t%N\tstats\t' |
sed '/^[ \t]*$/d' | # remove all newlines/line-breaks, including those with empty spaces
tr '\n' 'ò' | # convert newlines/line-breaks to a character, so we can manipulate it without much trouble
tr '\r' 'ò' | # convert carriage returns to a character, so we can manipulate it without much trouble
sed 's/tòcommits/tòòcommits/g' | # because some commits have no stats, we have to create an extra line-break to make `paste -d ' ' - -` consistent
tr 'ò' '\n' | # bring back all line-breaks
sed '{
N
s/[)]\n\ncommits/)\
commits/g
}' | # some rogue mystical line-breaks need to go down to their knees and beg for mercy, which they're not getting
paste -d ' ' - - # collapse lines so that the `shortstat` is merged with the rest of the commit data, on a single line
Обратите внимание, что я использовал символ табуляции (\t
) для разделения полей, поскольку ;
мог использоваться в сообщении фиксации.
Еще одна важная часть этого script заключается в том, что каждая строка должна начинаться с уникальной строки (в этом случае она совершает). Это потому, что наш script должен знать, где начинается линия. На самом деле все, что приходит после команды git log
, должно компенсировать тот факт, что некоторые коммиты могут не иметь статистики.
Но мне кажется, что то, что вы хотите достичь, состоит в том, что он аккуратно выводится в формате, который вы можете надежно использовать. Gitlogg отлично подходит для этого! Некоторые из его функций:
- Разберите
git log
из нескольких репозиториев в один JSON
файл.
- Введено
repository
ключ/значение.
- Введены
files changed
, insertions
и deletions
ключи/значения.
- Введено
impact
ключ/значение, представляющее кумулятивные изменения для фиксации (insertions
- deletions
).
- Санизировать двойные кавычки
"
путем преобразования их в одинарные кавычки '
для всех значений, которые разрешают или создаются с помощью ввода пользователя, например subject
.
- Доступны все заполнители
pretty=format:
.
- Легко включать/исключать, какие ключи/значения будут анализироваться на
JSON
, комментируя/раскомментируя доступные.
- Легко читаемый код, который тщательно прокомментировал.
- Script обратная связь исполнения на консоли.
- Обработка ошибок (поскольку путь к репозиториям необходимо установить правильно).
Успех, JSON был разобран и сохранен.
Ошибка 001: путь к репозиториям не существует.
Ошибка 002: путь к репозиториям существует, но пуст.
Ответ 2
git log --oneline --pretty="@%h" --stat |grep -v \| | tr "\n" " " | tr "@" "\n"
Это будет выглядеть примерно так:
a596f1e 1 file changed, 6 insertions(+), 3 deletions(-)
4a9a4a1 1 file changed, 6 deletions(-)
b8325fd 1 file changed, 65 insertions(+), 4 deletions(-)
968ef81 1 file changed, 4 insertions(+), 5 deletions(-)
Ответ 3
git не поддерживает статистику с равным --format, что стыдно:(
но это легко для него, здесь мое быстрое и грязное решение должно быть вполне читаемым:
#!/bin/bash
format_log_entry ()
{
read commit
read date
read summary
local statnum=0
local add=0
local rem=0
while true; do
read statline
if [ -z "$statline" ]; then break; fi
((statnum += 1))
((add += $(echo $statline | cut -d' ' -f1)))
((rem += $(echo $statline | cut -d' ' -f2)))
done
if [ -n "$commit" ]; then
echo "$commit;$date;$summary;$statnum;$add;$rem"
else
exit 0
fi
}
while true; do
format_log_entry
done
Я уверен, что это может быть написано лучше, но эй - это быстро и грязно;)
использование:
$ git log --pretty=format:"%h%n%ai%n%s" --numstat | ./script
Обратите внимание: этот формат, который вы указали, не является пуленепробиваемым. Точка с запятой может отображаться в сводке фиксации, которая разбивает количество полей в такой строке - вы можете либо переместить сводку в конец строки, либо как-то избежать ее - как вы хотите это сделать?
Ответ 4
Это один подход с awk
.
awk 'BEGIN{FS="[,;]"; OFS=";"} /;/ {a=$0} /^ /{gsub(/[a-z(+-) ]/,"") gsub(",",";"); print a,$0}'
Для данного ввода возвращается:
ed6e0ab;2014-01-07 16:32:39 +0530;Foo;3;14;13
cdfbb10;2014-01-07 14:59:48 +0530;Bar;1;21
772b277;2014-01-06 17:09:42 +0530;Qux;7;72;7
По-прежнему не работает для строк типа 5fde3e1;2014-01-06 17:26:40 +0530;Merge Baz
, у которых нет 3 files changed, 14 insertions(+), 13 deletions(-)
после него.
Ответ 5
Я помещаю что-то вроде этого в свой ~/.bashrc
:
function git-lgs() {
git --no-pager log --numstat --format=%ai "$1" | sed ':a;N;$!ba;s/\n\n/\t/g' | sed 's/\(\t[0-9]*\t*[0-9]*\).*/\1/'
}
Где аргумент git-lgs
- это имя файла, для которого вы хотите отобразить журнал.
Ответ 6
Следуйте за @user2461539, чтобы проанализировать его в столбцах. Работает с более сложными коллегами, такими как "Тема". Взломайте, чтобы выбрать свои собственные подходящие разделители. В настоящее время необходимо вырезать строку темы, поскольку она будет обрезать другие столбцы при переполнении.
#!/bin/bash
# assumes "_Z_Z_Z_" and "_Y_Y_" "_X_X_" as unused characters
# Truncate subject line sanitized (%f) or not (%s) to 79 %<(79,trunc)%f
echo commit,author_name,time_sec,subject,files_changed,lines_inserted,lines_deleted>../tensorflow_log.csv;
git log --oneline --pretty="_Z_Z_Z_%h_Y_Y_\"%an\"_Y_Y_%at_Y_Y_\"%<(79,trunc)%f\"_Y_Y__X_X_" --stat \
| grep -v \| \
| sed -E 's/@//g' \
| sed -E 's/_Z_Z_Z_/@/g' \
| tr "\n" " " \
| tr "@" "\n" |sed -E 's/,//g' \
| sed -E 's/_Y_Y_/, /g' \
| sed -E 's/(changed [0-9].*\+\))/,\1,/' \
| sed -E 's/(changed [0-9]* deleti.*-\)) /,,\1/' \
| sed -E 's/insertion.*\+\)//g' \
| sed -E 's/deletion.*\-\)//g' \
| sed -E 's/,changed/,/' \
| sed -E 's/files? ,/,/g' \
| sed -E 's/_X_X_ $/,,/g' \
| sed -E 's/_X_X_//g'>>../tensorflow_log.csv
Ответ 7
объединяя все ответы выше, вот мои 2 цента на случай, если кто-то ищет:
echo "commit id,author,date,comment,changed files,lines added,lines deleted" > res.csv
git log --since='last year' --date=local --all --pretty="%x40%h%x2C%an%x2C%ad%x2C%x22%s%x22%x2C" --shortstat | tr "\n" " " | tr "@" "\n" >> res.csv
sed -i 's/ files changed//g' res.csv
sed -i 's/ file changed//g' res.csv
sed -i 's/ insertions(+)//g' res.csv
sed -i 's/ insertion(+)//g' res.csv
sed -i 's/ deletions(-)//g' res.csv
sed -i 's/ deletion(-)//g' res.csv
и либо сохраните его в файле git-logs-into-csv.sh
либо просто скопируйте/вставьте в консоль.
Я думаю, что это относительно понятно, но на всякий случай:
-
--all
берет логи со всех веток -
--since
ограничивает количество --since
на которые мы хотим посмотреть -
--shortstat
- чтобы понять, что было сделано в --shortstat