この記事は「ウィルゲート Advent Calendar 2024」の 17 日目の記事です! adventar.org
こんにちは!!ウィルゲートプロダクト事業部 開発グループのことみん(@kotomin_m)です!!
このブログでは、複数リポジトリで特定の誰かがコミットしたコード行数を数える方法を簡単に紹介していきます!
端折っている部分も少々ありますが、コピペで実行できるシェルも載せているので、1年のふりかえりにぜひお試しください!
- やり方の説明
- ステップ1:GitHubに登録しているリポジトリ一覧をAPIで取得
- ステップ2:取得したリポジトリ一覧を整形
- ステップ3:全リポジトリをgit clone
- ステップ4:git log でコミットログを集計してCSV出力
- ステップ5:CSVファイルをGoogle スプレッドシートで集計
- おわりに
やり方の説明
今回は以下の5ステップで、GitHubのorganizationsにある全てのリポジトリでコミットしたコード行数を数えるようにしました!
- GitHubに登録しているリポジトリ一覧をAPIで取得
- 取得したリポジトリ一覧を整形
- 全リポジトリをgit clone
- git log でコミットログを集計してCSV出力
- CSVファイルをGoogle スプレッドシートで集計
今回はパワーで集計したのでちょっと無理矢理感もありますね。たぶん、もっとスマートな方法もあると思います。
コミットした期間で絞り込んだり、特定のリポジトリだけを集計するなどアレンジは可能なので、自分の用途に合わせてお使いください!
ステップ1:GitHubに登録しているリポジトリ一覧をAPIで取得
GitHubのAPIを使って全てのリポジトリ情報を取得します。 organizationsに含まれるリポジトリ数が多く、手動でgit cloneするリポジトリを指定するのは大変だったのでAPIで取得しました。
GitHub Personal Access Token を取得し、以下のシェルを実行します。
1_fetch_org_repos.sh
#!/bin/bash -eu # 必要な変数を設定 # あなたの GitHub Personal Access Token TOKEN="トークンを入力" # 対象のorganizations名 ORG_NAME="organizations-name" # 出力ファイル名 OUTPUT_FILE="1_repos.json" # GitHub API を使ってリポジトリ一覧を取得 curl -H "Authorization: token $TOKEN" \ "https://api.github.com/orgs/$ORG_NAME/repos?per_page=100" > "$OUTPUT_FILE" echo "リポジトリ一覧を $OUTPUT_FILE に保存しました。"
1_repos.json
ファイルにリポジトリ情報が出力されます。
[ { "id": 123456789, "node_id": "ABCDEFGH", "name": "repository-name", "full_name": "organizations-name/repository-name", (省略) }, ]
ステップ2:取得したリポジトリ一覧を整形
ステップ1で取得したリポジトリ情報から、full_name
のみを取得してテキストファイルに書き出します。
2_get_repos_full_name.sh
#!/bin/bash -eu # 必要な変数を設定 # 1で取得したJSONファイル名 INPUT_FILE="1_repos.json" # リポジトリ名を保存するファイル名 OUTPUT_FILE="2_repos_full_name.txt" # JSONファイルからリポジトリ名を抽出して保存 jq -r '.[].full_name' "$INPUT_FILE" > "$OUTPUT_FILE" echo "リポジトリ一覧を $OUTPUT_FILE に保存しました。"
2_repos_full_name.txt
に全てのリポジトリ名が出力されます。
organizations-name/repository-name organizations-name/repository-name-2 organizations-name/repository-name-3
ステップ3:全リポジトリをgit clone
ステップ2で取得したテキストファイルを使って、全てのリポジトリをgit cloneします。ファイルを編集することで、集計対象のリポジトリをフィルターすることも出来ます。
今回は特定のリポジトリに絞ってデバッグしながら実行したかったのでステップ2,3が存在していますが、一度テキストファイルに書き出す作業をしなくてもgit clone出来そうですね。
3_clone_repos.sh
#!/bin/bash -eu # 必要な変数を設定 # 2で取得したリポジトリ一覧ファイル名 REPOS_LIST="2_repos_full_name.txt" # クローン先ディレクトリ CLONE_DIR="repos" # リポジトリ一覧ファイルの確認 if [[ ! -f "$REPOS_LIST" ]]; then echo "リポジトリ一覧ファイルが見つかりません: $REPOS_LIST" exit 1 fi # クローン先ディレクトリの作成 mkdir -p "$CLONE_DIR" # リポジトリ一覧を1行ずつ処理 while read -r REPO_FULL_NAME; do # 空行をスキップ if [[ -z "$REPO_FULL_NAME" ]]; then continue fi # ローカルのディレクトリ名 REPO_DIR="$CLONE_DIR/$(basename "$REPO_FULL_NAME")" # ディレクトリが存在する場合はスキップ if [[ -d "$REPO_DIR" ]]; then echo "$REPO_FULL_NAME は既に存在します。" continue fi # リポジトリをクローン git clone "git@github.com:$REPO_FULL_NAME.git" "$REPO_DIR" done < "$REPOS_LIST" echo "すべてのリポジトリをクローンしました。"
repos/
ディレクトリ配下に、全てのリポジトリがクローンされます。
ステップ4:git log でコミットログを集計してCSV出力
git clone
したリポジトリに対して、git log
とawk
コマンドでコミット行数を集計し、CSVファイルを出力します。
ここで集計期間も指定するので、過去1年分だけ集計するなどカスタマイズすることも出来ます。
4_git_log_commit_count.sh
#!/bin/bash -eu # 必要な変数を設定 # コミットログを取得したい人のメールアドレス EMAIL="email@example.com" # クローン先ディレクトリ CLONE_DIR="repos" # 実行結果を保存するファイル名 RESULT_FILE="$EMAIL.csv" # コミットログの取得期間 SINCE_DATE="2010-01-01" UNTIL_DATE="2024-12-31" # 初期化:結果ファイルを空にする > "$RESULT_FILE" # クローン先ディレクトリを確認 if [[ ! -d "$CLONE_DIR" ]]; then echo "ディレクトリが見つかりません: $CLONE_DIR" exit 1 fi # 各リポジトリを処理 for REPO_PATH in "$CLONE_DIR"/*; do if [[ ! -d "$REPO_PATH/.git" ]]; then echo "$REPO_PATH はリポジトリディレクトリではありません。" continue fi REPO_NAME=$(basename "$REPO_PATH") # リポジトリのディレクトリに移動 cd "$REPO_PATH" || continue # git log コマンドでコミットログを取得し、awk で集計 LOG_SUMMARY=$(git log --numstat --pretty="%H" --author="$EMAIL" --since="$SINCE_DATE" --until="$UNTIL_DATE" --no-merges | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d, %d, %d\n", plus+minus, plus, minus)}') # ログのサマリーを表示 echo "$REPO_NAME, $LOG_SUMMARY" # 元のディレクトリに戻る cd - > /dev/null || exit # 結果をファイルに追記 echo "$EMAIL, $REPO_NAME, $LOG_SUMMARY" >> $RESULT_FILE done echo "結果を $RESULT_FILE に保存しました。"
email@example.com.csv
に、リポジトリごとの変更行数が保存されます。
メールアドレス, リポジトリ名, 変更総数, 追加行数, 削除行数 email@example.com, repository-name, 1000, 500, 500 email@example.com, repository-name-2, 2000, 1000, 1000 email@example.com, repository-name-3, 3000, 2000, 1000
ステップ5:CSVファイルをGoogle スプレッドシートで集計
email@example.com.csv
をGoogle スプレッドシートで開いて手動で集計します。
こういうときにスプシは便利ですね〜。変更行数が多いリポジトリ順とかも簡単に見れますね。
おわりに
変更行数を出すと「自分ってこんなにコード書いたんだな〜😆」ってなれますね!
他にも、「あの先輩どんだけコード書いてきたんだろう?対決だ!」なんてことも出来ます!💪(そして、「マジか〜全然勝てねえじゃん😇」なんてこともあります。)
使い方は無限大、ぜひやってみてください!!
「ウィルゲート Advent Calendar 2024(https://adventar.org/calendars/10272)」、翌日は中尾さんによる「 【フロントエンド改修事例】既存プロダクトのReactにCompound Components Petternを導入しました【コンポーネント設計】 」です。乞うご期待!