daisuzz.log

Gitで管理しているファイルの特定の期間の変更頻度をTSVで出力する

やりたいこと

  • ファイルの変更頻度を調べたい
  • 追加したファイルや削除したファイルは変更として扱いたくない
  • 過去の任意の期間を指定できるようにしたい
  • スプレッドシートにコピペしたいので、出力はTSV形式にしたい

方法

以下のワンライナーで出力することができる

git log --name-only --oneline --diff-filter=M --since='1 year ago' | grep -v ' ' | sort | uniq -c | sort -nr | head -n 20 | sed 's/^[ ]*//' | tr ' ' '\t'

基本的には、Gitで更新頻度の高いファイルを見つける方法 - アジャイルSEの憂鬱 を参考にさせてもらいながら、特定の期間を指定したり、追加や削除やリネームされたファイルは含まず変更されたファイルのみを出力できるようにしました。

GitHub - spring-projects/spring-framework: Spring Framework に対して実行した結果は以下。

$ git log --name-only --oneline --diff-filter=M --since='1 year ago' | grep -v ' ' | sort | uniq -c | sort -nr | head -n 20 | sed 's/^[ ]*//' | tr ' ' '\t'

79  build.gradle
16  src/docs/asciidoc/testing.adoc
12  spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java
12  spring-test/src/main/java/org/springframework/test/context/TestContextAnnotationUtils.java
11  src/docs/asciidoc/data-access.adoc
11  spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java
9   src/docs/asciidoc/web/webflux.adoc
9   gradle/docs.gradle
8   src/docs/asciidoc/web/webmvc.adoc
8   src/docs/asciidoc/web/webflux-webclient.adoc
8   spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java
8   spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java
8   ci/pipeline.yml
7   src/docs/asciidoc/languages/kotlin.adoc
7   spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
7   spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultWebClientTests.java
7   spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java
7   spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java
7   spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java
7   spring-test/src/main/java/org/springframework/test/context/NestedTestConfiguration.java

説明

  • git log --name-only --oneline --diff-filter=M --since='1 year ago'
    過去1年分のコミットログから、ファイルが変更されたコミットのハッシュとコミットメッセージと修正されたファイル名のみ抽出している。 --diff-filterは指定する文字によって出力するファイルの差分をフィルタリングできるオプションで、例えば、--diff-filter=Aを指定すれば、追加されたファイルのみを出力できるし、--diff-filter=Dを指定すれば削除されたファイルのみを出力できる。--diff-filter=ADのように複数指定することもできる。指定できる値の詳細は、Git - git-diff Documentation に書いてある。 また、期間の指定には--sinceを使っているが、--after--beforeなどで期間を指定することもできる。

  • grep -v ' '
    コミットのハッシュとコミットメッセージを除去して、修正されたファイル名のみ抽出

  • sort | uniq -c
    uniqでファイル名の重複を削除したいので、その前にsortで、修正されたファイル名をソートし、その後uniq -cでソートされたファイル名から重複を削除して、重複のカウントとファイル名を抽出

  • sort -nr
    文字列を数値として、降順にソートして出力

  • head -n 20
    先頭から20ファイルを抽出

  • sed 's/^[ ]*//' | tr ' ' '\t'
    先頭の空白文字を削除したり、TSV出力するため、文字列中の変更回数とファイル名の区切りを空白文字からタブ文字に変換

参考

Gitで更新頻度の高いファイルを見つける方法 - アジャイルSEの憂鬱

Git - Reference