Help us understand the problem. What is going on with this article?

Gitのログをワンライナーで整形する

More than 3 years have passed since last update.

Git Advent Calendar 2016の枠が空いていたのでおじゃまします。続編と合わせてよろしくお願いします。


はじめに

この記事はGitのログをPythonを使って集計し、品質管理・分析に役立てる方法を考察した記事の序章として、コマンドのみでワンライナーでログを集計できる手法をまとめたものです。まとめると記事が長くなったので分離しました。

git log コマンドはいつ誰が何をどのようにコミットしたかを知ることができる、バージョン管理に欠かせない便利なツールです。しかしこれを品質の管理・分析に活かそうとしたら少し工夫が必要です。そこでまず、コマンドを駆使してGitのログをワンライナーで整形する手法をまとめてみました。

コミットの多いファイルの特定(--name-only オプションの利用)

まずはじめに、たくさんコミットされているファイルを特定するコマンドについてまとめてみました。開発期間中にたくさんコミットされているファイルはそれだけバグが含まれている可能性も高くなるため、リスクベースでテスト計画をたてる時などにログを活用できます。

コミット数の多いファイルTop10

$ git log --name-only --pretty="format:" | grep -ve '^$' | sort | uniq -c | sort -r | head

コミットログからファイル名のリストを抽出した後、1回目の sort によってファイル名で並び替えし、 uniq で重複するファイルを集約してカウントし、2回目の sort でカウントが多い順に並び替えて head で上位10件を出力しています。

git log --name-only --pretty="format:" | grep -ve '^$' までがコミットログからファイル名を抜き出す手法で、知っておけば色々応用ができます。

変更された行数のカウント(--numstatオプションの利用)

ステップ数を品質や生産性の指標として使うのは古(いにしえ)より伝わる古典的手法ですが、目的は色々ありますが行数をカウントすることはいまだによくあるのではないでしょうか。

全追加・削除行数

$ git log --numstat --pretty="%H" | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%d\n", plus, minus)}'

git log --numstat --pretty="%H" を使うと以下のように追加行数、削除行数、ファイル名が出力されるためそれを awkで集計しています。

急にawkが出てきましたが、以下のように1行のログがスペースで区切られた3つの要素で出力されていて、1つ目と2つ目がファイルごとの追加行数、削除行数なので、それをawkでひたすら足し算していくだけです。

10       23       README.md

ファイル単位の追加行数、削除行数

次はファイル単位の追加行・削除行のTop10を出力する例です。

$ git log --numstat --pretty="%H" | awk 'NF==3 {add_sum[$3]+=$1; del_sum[$3]+=$2} END {for (key in add_sum) {printf("%d, %d, %s\n", add_sum[key],del_sum[key],key)}}' | sort -k1,1nr -k2,2nr -t,| head 

awkがもはや無理やり感いっぱいで1行にまとめられています。上記はコミット単位の集計なので同じファイルを何回もコミットした場合、別々に変更行が出力されます。これをさらにファイル単位にまとめて集計してみたいところですが、これ以上awkを駆使すると目的が変わってしまうので今回はここまでにしておきます。

ログの取得範囲を絞り込む

最後に視点を変えてログの対象となる範囲を指定する方法についてまとめます。コマンドを駆使するわけではなくgit logのオプションの紹介です。

Commit Limitingによる絞り込み

例えばプロジェクトの開発期間で絞りたい場合は--since --untilなどを使います。git logCommit Limiting の仕様を確認することで様々な絞込みができます。

例)6カ月内にコミットされた、コミット数の多いファイルTop10

$ git log --name-only --pretty="format:" --since="6 months ago" | grep -ve '^$' | sort | uniq -c | sort -r | head

ブランチの差異による絞り込み

ダブルドット構文 .. を使ってブランチ同士のログの差異を取得する方法もあります。revision range の仕様で確認できます。例えば experimentmaster にマージされる前の変更点を確認する場合は以下のようにします。

例)ブランチを切ってからコミット数の多いファイルTop10

$ git log --name-only --pretty="format:" master..experiment | grep -ve '^$' | sort | uniq -c | sort -r | head

なお、トリプルドット構文というのもあります。詳細はコミットの範囲指定の記事が参考になります。

おわりに

以上のようにワンライナーでもある程度のことができますが、品質管理というよりはコマンドで出来ることを基準に考えてしまいがちなので、次回はPythonを使ってGitのログを活用する発展的な手法を考えてみます。続きは ラクス Advent Calendar 2016へ投稿する予定です。

参考

git リポジトリからプロジェクトの概要をつかむ
gitでnumstatを利用して総追加行数、総削除行数を取得するワンライナー
branchを切った時点のコミットとbranchの最新コミットとのlogとdiffをみたい

radiocat
Web系技術とAndroidアプリ開発が中心。スクラムマスターもやってます。 よろしくお願いします。
http://radiocat.hatenablog.com/
rakus
「IT技術で中小企業を強くします!」というミッションを掲げ、中小企業の業務効率化に貢献する複数のクラウドサービスを提供しているIT企業です。「楽楽精算」「メールディーラー」など、国内トップシェアを誇る複数のサービスを開発し、累計導入社数は5万社を超えています。次の時代の"楽"を創るための、まだ見ぬサービスや機能を生み出す取り組みは、今日も続いています。
https://www.rakus.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away