web-dev-qa-db-ja.com

1行で短い統計情報を含む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_(改行なし)に変換されるということです。考えられるコーナーケースの1つは、_"5fde3e1;2014-01-06 17:26:40 +0530;Merge Baz"_のような行がないテキストです。その場合は_;0;0;0_が欲しい

全体的な目標は、一定期間のファイル変更統計を分析することです。 gitログのドキュメントを読みましたが、この形式でレンダリングするのに役立つ形式が見つかりませんでした。私が思いついた最高のものは、上記のコマンドでした。

したがって、期待される形式を生成できるコマンドまたはシェルスクリプトは非常に役立ちます。

ありがとう!

23
Ankush

残念ながら、これはgit logだけを使用して実現することは不可能です。ほとんどの人が気付いていないことを補うために他のスクリプトを使用する必要があります:一部のコミットには統計がありません、たとえそれらがマージされていなくても。

私はgit logJSONに変換するプロジェクトに取り組んでおり、それを実行するには、必要なことを実行する必要がありました。統計を使用して、各コミットを1行で取得します。プロジェクトは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が使用された可能性があるため、フィールドを区切るためにタブ文字(;)を使用したことに注意してください。

このスクリプトのもう1つの重要な部分は、各行が一意の文字列で始まる必要があることです(この場合はcommits)。これは、スクリプトが行の始まりを知る必要があるためです。実際、git logコマンドの後に来るものはすべて、一部のコミットに統計がない可能性があるという事実を補うためにあります。

しかし、達成したいことは、コミットをあなたの形式できちんと出力することだと私は思います。確実に消費することができます。 Gitloggはそれに最適です!その機能のいくつかは次のとおりです。

  • 複数のリポジトリのgit logを1つのJSONファイルに解析します。
  • 導入されたrepositoryキー/値。
  • 導入files changedinsertionsおよびdeletionsキー/値。
  • 導入されたimpactキー/値。これは、コミットの累積変更を表します(insertions --deletions)。
  • subjectのように、ユーザー入力を許可または作成するすべての値で、二重引用符"を一重引用符'に変換してサニタイズします。
  • ほぼすべてのpretty=format:プレースホルダーが利用可能です。
  • 使用可能なキー/値をコメントアウト/コメント解除することにより、どのキー/値がJSONに解析されるかを簡単に含める/除外します。
  • 徹底的にコメントされた読みやすいコード。
  • コンソールでのスクリプト実行フィードバック。
  • エラー処理(リポジトリへのパスを正しく設定する必要があるため)。

Success, the JSON was parsed and saved. 成功、JSONが解析されて保存されました。

Error 001 エラー001:リポジトリへのパスが存在しません。

Error 002 エラー002:リポジトリへのパスは存在しますが、空です。

7
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(-) 
5
user2461539

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
Patryk Obara

これは、awkを使用した1つのアプローチです。

_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(-)がない行ではまだ機能しません。

@ user2461539をフォローアップして、列に解析します。 「Subject」などのより複雑な列でも機能します。自分の適切な区切り文字を選択するためにハックしてください。現在、件名がオーバーフローすると他の列が切り捨てられるため、件名を削除する必要があります。

#!/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
1
ragulpr

上記のすべての答えを組み合わせると、誰かが探している場合に備えて、ここに私の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は私たちが見たいコミットの数を制限します
  • --shortstat-コミットで何が行われたかを把握する
0
avs099

私はこのようなものを私の~/.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の引数は、ログを表示するファイル名です。

0
Geremia