Как получить 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 был разобран и сохранен. Успех, JSON был разобран и сохранен.

Ошибка 001 Ошибка 001: путь к репозиториям не существует.

Ошибка 002 Ошибка 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