年末年始、あなたのホームディレクトリは大丈夫ですか?未コミットのコード、マージ済みなのに残っている放置ブランチ、1年以上触っていないプロジェクト…。新年を迎える前に、開発環境をクリーンな状態にリセットしましょう。
前編では、1年間の開発活動を統計で振り返り、Gitリポジトリの大掃除を行います。新しいRust製OSSツールと実用的なスクリプトで、効率的に整理していきましょう。
なぜ年末に大掃除が必要なのか
エンジニアの開発環境は、日々の作業で確実に「散らかって」いきます:
- 未コミットの変更: 「後でコミットしよう」と思ったまま放置
- 未プッシュのコミット: ローカルに溜まったまま年を越すリスク
- 放置ブランチ: マージ済み・削除済みなのにローカルに残存
- 古いプロジェクト: 1年以上触っていないディレクトリが容量を圧迫
年末は、これらを一掃する絶好のタイミングです。
📊 1年間の振り返り統計
まずは、自分が今年どんなコードを書いてきたのか、統計で振り返ってみましょう。
onefetch: リポジトリの美しいサマリー表示
onefetch
は、Rust製のコマンドラインツールで、Gitリポジトリの統計情報をneofetch
風に美しく表示します。言語分布、コミット数、作成日、LOC(コード行数)などが一目でわかります。
インストール
1
2
3
4
5
| # macOS
brew install onefetch
# [Cargo](https://doc.rust-lang.org/cargo/)経由(Rust環境がある場合)
cargo install onefetch
|
基本的な使い方
1
2
3
4
5
6
| # カレントディレクトリのリポジトリ情報を表示
cd ~/work/my-project
onefetch
# ASCII artなしでコンパクトに表示
onefetch --no-art
|
実践例:全リポジトリのサマリーを一括表示
1
2
3
4
5
6
7
8
| # ホームディレクトリ配下の全Gitリポジトリを巡回
find ~/work -name ".git" -type d 2>/dev/null | while read gitdir; do
repo=$(dirname "$gitdir")
cd "$repo"
echo ""
echo "=== $(basename $(pwd)) ==="
onefetch --no-art --no-color-palette
done
|
このスクリプトで、全プロジェクトの統計を一覧できます。「あ、このプロジェクト今年1回しかコミットしてない」といった気づきが得られるでしょう。
シェル履歴の分析:よく使うコマンドTOP20
普段どんなコマンドを使っているか、確認してみましょう。
1
2
| # Bash/Zshの履歴からよく使うコマンドTOP20を抽出
history | awk '{print $2}' | sort | uniq -c | sort -rn | head -20
|
実行結果の例:
1523 git
842 cd
654 ls
421 docker
298 vim
...
統計の読み方アドバイス
統計データは、ただ眺めるだけでは意味がありません。以下の観点で解釈してみましょう:
コミット数の多寡
- コミット数が多い ≠ 生産性が高い
- 細かいコミットを心がけている可能性
- リファクタリング作業が多かった可能性
- 逆に、コミット数が少なくても大きな機能を実装している場合もある
よく触るファイル
- 最も編集したファイル → あなたの専門領域
- 長期間触っていないファイル → アーカイブ候補、または技術的負債の可能性
よく使うコマンド
gitが圧倒的に多い → バージョン管理を重視しているdockerの頻度が高い → コンテナ環境での開発が中心npm installやpip installが多い → 依存関係の管理に時間を取られている可能性

GitHub統計の振り返り
ローカルリポジトリだけでなく、GitHubでの活動も振り返りましょう。GitHub CLI
を使えば、コマンドラインから簡単に統計を取得できます。
GitHub CLIのインストール
1
2
3
4
5
6
7
8
| # macOS
brew install gh
# Ubuntu/Debian
sudo apt install gh
# 認証
gh auth login
|
年間コントリビューション数の確認
1
2
3
4
5
6
7
8
9
10
11
| # 自分のプロフィールを表示
gh api users/$(gh api user -q .login) | jq '{
public_repos: .public_repos,
public_gists: .public_gists,
followers: .followers,
following: .following
}'
# 今年作成したリポジトリ一覧
gh repo list --limit 100 --json name,createdAt,pushedAt \
| jq '[.[] | select(.createdAt | startswith("2025"))]'
|
よく触るリポジトリTOP10
1
2
3
4
| # 自分がコミットしたリポジトリを最終更新日順に表示
gh repo list --limit 100 --json name,pushedAt,isPrivate \
| jq -r '.[] | "\(.pushedAt)\t\(.name)\t(private: \(.isPrivate))"' \
| sort -r | head -10
|
Issue/PRの対応状況
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 自分が作成したIssueの統計
gh issue list --author @me --state all --limit 1000 --json state \
| jq '[group_by(.state)[] | {state: .[0].state, count: length}]'
# 自分が作成したPRの統計
gh pr list --author @me --state all --limit 1000 --json state \
| jq '[group_by(.state)[] | {state: .[0].state, count: length}]'
# 未対応のIssue/PRを確認
echo "=== Open Issues ==="
gh issue list --author @me --state open
echo "=== Open PRs ==="
gh pr list --author @me --state open
|
Star/Forkが多いリポジトリ
1
2
3
4
5
| # 自分のリポジトリをStar数順に表示
gh repo list --limit 100 --json name,stargazerCount,forkCount \
| jq -r 'sort_by(.stargazerCount) | reverse | .[]
| "\(.stargazerCount) ⭐ \(.forkCount) 🍴 \(.name)"' \
| head -10
|
読み方のポイント:
- 最終更新が3ヶ月以上前のリポジトリ → アーカイブまたは削除を検討
- Starが0のリポジトリ → プライベートに変更、または整理対象
- 未対応のIssue/PR → 年末に一気に対応またはクローズ

GitHub Actionsの棚卸し
GitHub Actionsのワークフローも、定期的に見直しが必要です。使われていないワークフローや失敗し続けているジョブを整理しましょう。
全リポジトリのワークフロー実行状況を確認
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #!/bin/bash
# check-github-actions.sh
# 目的: 全リポジトリのGitHub Actions実行状況を確認
echo "🔍 GitHub Actions の実行状況をチェック中..."
echo ""
gh repo list --limit 100 --json name | jq -r '.[].name' | while read repo; do
echo "=== $repo ==="
# 最近のワークフロー実行を取得
gh run list --repo $(gh api user -q .login)/$repo --limit 10 --json status,conclusion,name,createdAt 2>/dev/null | \
jq -r '.[] | "\(.createdAt) | \(.name) | \(.status) | \(.conclusion // "running")"' 2>/dev/null
echo ""
done
|
失敗し続けているワークフローの発見
1
2
3
4
5
| # 特定リポジトリの失敗したワークフローを確認
gh run list --repo owner/repo --status failure --limit 20
# 失敗したワークフローの詳細を確認
gh run view <RUN_ID> --log-failed
|
対処方法:
- 使っていないワークフロー →
.github/workflows/ から削除 - 失敗し続けているジョブ → 原因を修正するか、無効化する
- 古いActionバージョン → 最新版にアップデート(例:
actions/checkout@v2 → @v4)
不要なワークフローの削除
1
2
3
4
5
6
7
8
9
| # .github/workflows/ 内のファイル一覧
find .github/workflows/ -name "*.yml" -o -name "*.yaml"
# 最終更新日を確認
ls -la .github/workflows/
# 不要なワークフローを削除
git rm .github/workflows/old-workflow.yml
git commit -m "chore: remove unused GitHub Actions workflow"
|
GitHub Issueの大掃除
長期間放置されたIssueは、プロジェクトの見通しを悪くします。年末に一気に整理しましょう。
古いIssueの一覧表示
1
2
3
4
5
6
| # 1年以上更新されていないIssueを表示
gh issue list --repo owner/repo --state open --limit 100 --json number,title,updatedAt \
| jq '.[] | select(.updatedAt < "2024-01-01") | {number, title, updatedAt}'
# 特定のラベルがついたIssueを表示
gh issue list --label "bug" --state open
|
古いIssueを一括クローズ
1
2
3
4
5
6
7
8
9
10
11
12
13
| #!/bin/bash
# close-stale-issues.sh
# 目的: 1年以上更新されていないIssueを一括クローズ
REPO="owner/repo"
CUTOFF_DATE="2024-01-01"
gh issue list --repo $REPO --state open --limit 100 --json number,updatedAt \
| jq -r ".[] | select(.updatedAt < \"$CUTOFF_DATE\") | .number" \
| while read issue_num; do
echo "Closing issue #$issue_num..."
gh issue close $issue_num --repo $REPO --comment "このIssueは1年以上更新されていないため、年末の大掃除でクローズします。必要であれば再オープンしてください。"
done
|
ラベルの整理
1
2
3
4
5
6
7
8
9
10
11
12
13
| # ラベル一覧を表示
gh label list --repo owner/repo
# 使われていないラベルを確認
gh label list --repo owner/repo --json name | jq -r '.[].name' | while read label; do
count=$(gh issue list --repo owner/repo --label "$label" --state all --limit 1000 --json number | jq 'length')
if [ "$count" -eq 0 ]; then
echo "未使用: $label"
fi
done
# 不要なラベルを削除
gh label delete "old-label" --repo owner/repo --yes
|
チェックポイント:
🗂️ Gitリポジトリの棚卸し
統計で振り返ったら、次は実際にリポジトリをクリーンアップしていきましょう。
未コミット・未プッシュの発見スクリプト
年末年始で作業が中断されると、未コミットのコードや未プッシュのコミットを忘れてしまうリスクがあります。以下のスクリプトで一括チェックしましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| #!/bin/bash
# ~/bin/git-status-all.sh
# 目的: ホームディレクトリ配下の全Gitリポジトリで未コミット・未プッシュを検出
# 使い方: ./git-status-all.sh
echo "🔍 未コミット・未プッシュのチェックを開始..."
echo ""
find ~ -name ".git" -type d 2>/dev/null | while read gitdir; do
repo=$(dirname "$gitdir")
cd "$repo"
# 未コミットの変更があるか
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
echo "📝 未コミット: $repo"
git status --short
echo ""
fi
# 未プッシュのコミットがあるか
if [ -n "$(git log @{u}.. 2>/dev/null)" ]; then
unpushed_count=$(git log @{u}.. --oneline 2>/dev/null | wc -l | tr -d ' ')
echo "⬆️ 未プッシュ ($unpushed_count commits): $repo"
git log @{u}.. --oneline
echo ""
fi
done
echo "✅ チェック完了"
|
保存したら実行権限を付与:
1
2
| chmod +x ~/bin/git-status-all.sh
~/bin/git-status-all.sh
|
放置ブランチの一括削除
マージ済みのブランチや、リモートで削除されたブランチがローカルに残っていると、git branchの出力が煩雑になります。
手動で削除する場合
1
2
3
4
5
6
7
8
| # リモートで削除されたブランチの参照を削除
git fetch --prune
# マージ済みのローカルブランチを一覧表示
git branch --merged main
# マージ済みブランチを一括削除(main/master/developを除く)
git branch --merged main | grep -v "main\|master\|develop" | xargs git branch -d
|
Rust製ツールを使う場合
放置ブランチの削除を自動化するRust製ツールがいくつかあります:
1. git-clean-gone
1
2
3
4
5
| # インストール(Cargo経由)
cargo install git-clean-gone
# [gone]状態のブランチを削除
git clean-gone
|
2. git-clean (mcasper/git-clean)
1
2
3
4
5
| # インストール
cargo install git-clean
# インタラクティブに削除するブランチを選択
git-clean
|
これらのツールは、git branch -vvで[gone]と表示されるブランチ(リモートで削除済み)を自動検出して削除してくれます。
以前紹介したgit-absorb
も便利ですが、ブランチ整理には今回紹介したツールが専門的です。
git gc: ガベージコレクションでリポジトリを軽量化
ブランチを削除したり、git rebaseで履歴を書き換えたりしても、Gitの内部データベースには不要なオブジェクトが残っています。git gc
(garbage collection)を実行して、リポジトリを軽量化しましょう。
主な機能:
- 不要なオブジェクトの削除: 削除されたブランチやリセットされたコミットなど、どこからも参照されなくなったオブジェクトを削除
- オブジェクトの圧縮: 複数の小さなパックファイルを1つに統合し、デルタ圧縮でディスク使用量を削減
- 参照ログの整理: 古いreflogエントリを削除
- パフォーマンス向上: リポジトリのアクセス速度を改善
1
2
3
4
5
6
7
8
| # 基本的な実行
git gc
# より積極的な最適化(時間はかかるが効果大)
git gc --aggressive
# 古いオブジェクトも含めて即座にクリーンアップ
git gc --prune=now
|
いつ実行すべき?
通常、Gitはgit gc --autoを必要なタイミングで自動実行しますが、以下の場合は手動実行が効果的です:
- 上記のように大量のブランチを削除した後
git filter-branchやgit rebaseで履歴を書き換えた後- リポジトリの動作が遅くなったと感じたとき
.gitディレクトリのサイズが気になるとき
効果の確認:
1
2
3
4
5
| # 実行前後で.gitディレクトリのサイズを比較
du -sh .git
# より詳細な統計
git count-objects -vH
|
ブランチ整理をした後にgit gc --aggressiveを実行すると、参照されなくなったコミットオブジェクトが削除され、リポジトリサイズを大幅に削減できます。
放置リポジトリの発見
1年以上更新のないリポジトリは、アーカイブ候補かもしれません。以下のスクリプトで古いリポジトリを検出しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| #!/bin/bash
# 1年以上更新のないGitリポジトリを検出
# 使い方: ./find-stale-repos.sh
echo "🕰️ 1年以上更新のないリポジトリを検索中..."
echo ""
find ~/work -name ".git" -type d 2>/dev/null | while read gitdir; do
repo=$(dirname "$gitdir")
cd "$repo"
# 最新コミットの日付を取得
last_commit=$(git log -1 --format=%ci 2>/dev/null | cut -d" " -f1)
if [ -n "$last_commit" ]; then
# 日付の差分を計算(macOS/Linuxで動作)
if command -v date >/dev/null 2>&1; then
# macOSの場合
if date -j -f "%Y-%m-%d" "$last_commit" >/dev/null 2>&1; then
last_epoch=$(date -j -f "%Y-%m-%d" "$last_commit" +%s 2>/dev/null)
else
# Linuxの場合
last_epoch=$(date -d "$last_commit" +%s 2>/dev/null)
fi
current_epoch=$(date +%s)
days_ago=$(( (current_epoch - last_epoch) / 86400 ))
# 365日以上前の場合のみ表示
if [ "$days_ago" -gt 365 ]; then
size=$(du -sh "$repo" 2>/dev/null | cut -f1)
echo "📦 $days_ago 日前: $repo ($size)"
fi
fi
fi
done | sort -rn
echo ""
echo "✅ 検索完了"
|
検出されたリポジトリは、以下の選択肢を検討しましょう:
- アーカイブ:
tar czf archive.tar.gz old-project/ で圧縮 - 削除: 不要なら削除(GitHub
などにバックアップがあれば安心)
- 再開: 実は必要なプロジェクトだった場合は継続
Gitの履歴書き換えツールも活用
リポジトリの大掃除をより高度に行いたい場合は、Gitの黒歴史を隠蔽する:履歴書き換えツールまとめ
で紹介したツールも活用できます。
まとめ:前編のチェックリスト
以下の項目を実施して、Gitリポジトリをクリーンな状態にしましょう:
次回の後編では、ディスク容量の奪還(node_modules、Docker images)とバックアップ体制の見直しを行います。お楽しみに!
参考リンク