最近もっぱらGitを使用していますが、軽くて高機能ですし便利だと思います。でも今日はGitの話しません。

そんなGitのlogを見る際に、色々いじって手ワンライナーに便利そうなコマンドオプションを幾つか発見したので、鬼の首を取ったようにメモしときますね。

言っておきますが分かってる人には当然の内容ですよ。。


想定しているOSはLinux、GNU coreutilsとGNU grepです。他のOSに載っているやつで動くかは不明。

で。まずは単品の、

1
git log

これだとlessとかで見る事になります。それはそれでいいんですけど、

commit ac048f833ba3743a8d5ad313985f49571436ca57
Author: udzura <udzura@hoge.udzura.jp>
Date:   Thu Feb 4 15:05:13 2010 +0900

    バッチのtypo修正

commit ce9e4356c945f892b606b206534145845a9d6ce1
Author: udzura <udzura@hoge.udzura.jp>
Date:   Thu Feb 4 14:00:01 2010 +0900

    バッチ直した

commit 5197339ddbd701b1902c7d9b7ae9732c8b627750
Author: deadwinter <deadwinter@hoge.udzura.jp>
Date:   Tue Feb 2 13:37:56 2010 +0900

    app/models/hoge.rb typo直した

commit c10da34d0394415065efe4ee4d1e80eb3ae5bae7
Author: udzura <udzura@hoge.udzura.jp>
Date:   Mon Feb 1 12:28:56 2010 +0900
......

「ワンライナーで必要な情報だけシュバッ! と抜き出したい」、UN*Xユーザならみんなそう思うかと考えられますので。

行番号を付けたい

「シュバッ」と抜き出す前段階として、表示に行番号を付けましょう。 cat -n です。

1
git log | cat -n
     1  commit ac048f833ba3743a8d5ad313985f49571436ca57
     2  Author: udzura <udzura@hoge.udzura.jp>
     3  Date:   Thu Feb 4 15:05:13 2010 +0900
     4
     5      バッチのtypo修正
     6
     7  commit ce9e4356c945f892b606b206534145845a9d6ce1
     8  Author: udzura <udzura@hoge.udzura.jp>
     9  Date:   Thu Feb 4 14:00:01 2010 +0900
    10
    11      バッチ直した
    12
    13  commit 5197339ddbd701b1902c7d9b7ae9732c8b627750
    14  Author: deadwinter <deadwinter@hoge.udzura.jp>
    15  Date:   Tue Feb 2 13:37:56 2010 +0900
    16
    17      app/models/hoge.rb typo直した
    18
    19  commit c10da34d0394415065efe4ee4d1e80eb3ae5bae7
    20  Author: udzura <udzura@hoge.udzura.jp>
    21  Date:   Mon Feb 1 12:28:56 2010 +0900
......

でもコレで

1
git log | cat -n | grep udzura@hoge.udzura.jp
     2  Author: udzura <udzura@hoge.udzura.jp>
     8  Author: udzura <udzura@hoge.udzura.jp>
    20  Author: udzura <udzura@hoge.udzura.jp>
......

とか抜き出しても、日付すら分かりませんね。。

grepした行の回りも見たい

grepには -C オプションがあります。マッチした行の前後N行も一緒に表示してくれます。

git logとかはちょうど、ユーザ名の前後一行に必要な情報が入ってます。

1
git log | cat -n | grep -C1 udzura@hoge.udzura.jp
     1  commit ac048f833ba3743a8d5ad313985f49571436ca57
     2  Author: udzura <udzura@hoge.udzura.jp>
     3  Date:   Thu Feb 4 15:05:13 2010 +0900
--
     7  commit ce9e4356c945f892b606b206534145845a9d6ce1
     8  Author: udzura <udzura@hoge.udzura.jp>
     9  Date:   Thu Feb 4 14:00:01 2010 +0900
--
    19  commit c10da34d0394415065efe4ee4d1e80eb3ae5bae7
    20  Author: udzura <udzura@hoge.udzura.jp>
    21  Date:   Mon Feb 1 12:28:56 2010 +0900
......

ここからさらに、「2010年2月1日」のコミットを探したい時は、月日と年度が分かれてるせいで以下のようにしますね。grepコマンドでAND検索をする時はひたすらgrepをパイプで重ねるのが私のジャスティスです(OR検索したいアナタには、 -e オプションというものがあります)。

1
git log | cat -n | grep -C1 udzura@hoge.udzura.jp | grep "Thu Feb 4" | grep 2010
    21  Date:   Mon Feb 1 12:28:56 2010 +0900

今思ったんだけど曜日が入ってるんだから年度要らないかも。まあサンプルということで。

ともかく、見事、欲しい情報が「21行目あたりに入っているんだな」と判明しました。git logの仕様的には、きっと(21 – 2 = 19)~24行目の間に入っているのでしょう。

N行目からM行を見たい

こういう 21 – 2 行目から6行分を見たい、という際は、 headtail を組み合わせるのが便利です。便利なんですよ。ハイフン+数字で「頭から|ケツから N 行を表示」という便利オプションを使いましょう。また、算数が面倒くさい向きには、 $((計算式)) という記法があって、これはこの中身の計算を展開してくれます。

1
git log | cat -n | head -$((21 - 2 + 5)) | tail -6
    19  commit c10da34d0394415065efe4ee4d1e80eb3ae5bae7
    20  Author: udzura <udzura@hoge.udzura.jp>
    21  Date:   Mon Feb 1 12:28:56 2010 +0900
    22
    23      まあ適当に直した
    24

出来ましたね!

まとめ

以上をまとめ、バックスラッシュという便利記法を使用すると、以下のワンライナーになりますね。バックスラッシュ `コマンド` は中身のコマンドを先に実行し、結果の出力を文字にして、その外側のコマンドを実行します。

1
git log | cat -n | head -$((`git log | cat -n | grep -C1 udzura@hoge.udzura.jp | grep "Mon Feb 1" | grep 2010 | cut -f1` - 2 + 5)) | tail -6

すいません、まとめといいながらさらにどさくさにまぎれて cut -f なるコマンドを混入させています。これは、空白区切り(デフォルト;区切りは -d で指定)のテキストの、任意の列を切り出してくれます。

【改訂新版】 Linuxコマンド ポケットリファレンス (Pocket Reference)

著者/訳者:沓名 亮典 平山 智恵

出版社:技術評論社( 2009-04-08 )

単行本(ソフトカバー) ( 576 ページ )


総括

TortoiseGitって便利なんですね。

総括2

ワンライナーのコツは:

  • コマンド一回一回ごとの「標準出力」の状態を把握する
  • バックスラッシュ記法を活用
  • その他、「[条件] && ~」「&&」「;」や各種制御構造をフル活用

とかな気がする。でも多分、シェルスクリプト書いたほうがいいよ。