0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

launchd + シェルスクリプトで「Day N 自動コミット」を作った — Macが勝手にgitログを育てる仕組み

0
Last updated at Posted at 2026-03-19

ある日、git log --oneline を叩いた。

Day 14: チーム定義(24ファイル)
Day 13: 自動化・ツール(34ファイル)
Day 12: コンテンツ・リサーチ(17ファイル)
Day 11: 戦略(12ファイル)

自分の歩みが全部、時系列で残っていた。Day 1 から今日まで、何をやったかが一目でわかる。「あれ、いつやったっけ」がない。日記をつけたことは一度もないのに、git が日記になっていた。

これは手動コミットではない。Mac が勝手にやっている。

なぜ「Day N」をコミットメッセージに入れたか

普通の自動コミットは日時がメッセージに入る。2026-03-19 auto backup みたいなやつ。悪くはない。でも読み返したとき、日付の羅列から「流れ」を感じるのは難しい。

「Day 1」「Day 14」と書いてあると、話が変わる。何日目に何をやったか。どこで加速したか。止まった日はあったか。ログ自体がプロジェクトの年表になる。

しかも計算は自動だ。基準日を一つ決めておけば、あとはスクリプトが date コマンドで勝手に算出する。

auto-backup.sh の中身

やっていることは 3 つ。差分検出、Day N 計算、カテゴリ自動判定。

#!/bin/bash
# プロジェクトの自動バックアップスクリプト
cd "/path/to/project" || exit 1

# 変更がなければ何もしない
if [ -z "$(git status --porcelain)" ]; then
  exit 0
fi

# 基準日からの経過日数を計算
FOUNDING_DATE="2026-03-06"
TODAY=$(date '+%Y-%m-%d')
if [[ "$(uname)" == "Darwin" ]]; then
  FOUNDING_SEC=$(date -j -f "%Y-%m-%d" "$FOUNDING_DATE" "+%s")
  TODAY_SEC=$(date -j -f "%Y-%m-%d" "$TODAY" "+%s")
else
  FOUNDING_SEC=$(date -d "$FOUNDING_DATE" "+%s")
  TODAY_SEC=$(date -d "$TODAY" "+%s")
fi
DAY_NUM=$(( (TODAY_SEC - FOUNDING_SEC) / 86400 + 1 ))

git add -A

# 変更ファイルのパスからカテゴリを自動判定
CHANGED=$(git diff --cached --name-only)
CATEGORIES=""
echo "$CHANGED" | grep -q "strategy"    && CATEGORIES="${CATEGORIES}戦略・"
echo "$CHANGED" | grep -q "automation"  && CATEGORIES="${CATEGORIES}自動化・"
echo "$CHANGED" | grep -q "creative"    && CATEGORIES="${CATEGORIES}クリエイティブ・"
echo "$CHANGED" | grep -q "research"    && CATEGORIES="${CATEGORIES}リサーチ・"
echo "$CHANGED" | grep -q "content"     && CATEGORIES="${CATEGORIES}コンテンツ・"
# フォルダ構成に合わせて追加する
CATEGORIES=$(echo "$CATEGORIES" | sed 's/・$//')
if [ -z "$CATEGORIES" ]; then CATEGORIES="更新"; fi

FILE_COUNT=$(echo "$CHANGED" | wc -l | tr -d ' ')
COMMIT_MSG="Day ${DAY_NUM}${TODAY}): ${CATEGORIES}${FILE_COUNT}ファイル)"

git commit -m "$COMMIT_MSG"
git push

ポイントを拾っていく

差分がなければ即終了。 git status --porcelain が空なら exit 0。空コミットは作らない。ログが汚れるだけだ。

macOS と Linux で date の書式が違う。 -j -f は macOS の BSD date。Linux の GNU date は -d を使う。ここをサボると CI で事故る。uname で分岐させておく。

Day N の計算は単純な引き算。 UNIX秒に変換して差分を取り、86400(1日の秒数)で割る。+1 しているのは「Day 0」ではなく「Day 1」から始めたいから。

カテゴリ自動判定は grep のパターンマッチ。 フォルダ名に特定の文字列が含まれていれば、対応するカテゴリを連結する。最後に末尾の区切り文字を sed で削る。どのフォルダにもマッチしなければ「更新」をデフォルトにする。

正直、カテゴリ判定は雑だ。複数フォルダにまたがる変更だと「戦略・自動化・リサーチ(42ファイル)」みたいな長いメッセージになる。でもそれはそれで「今日はいろいろやったな」とわかるので、問題にしていない。

launchd で定期実行する

Mac で定期実行するなら launchd 一択。cron は macOS で非推奨だし、スリープ復帰後の挙動が怪しい。launchd ならスリープ中にスケジュールを過ぎても、復帰時に実行してくれる。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.yourname.auto-backup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/path/to/auto-backup.sh</string>
    </array>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key><integer>12</integer>
            <key>Minute</key><integer>0</integer>
        </dict>
        <dict>
            <key>Hour</key><integer>23</integer>
            <key>Minute</key><integer>0</integer>
        </dict>
    </array>
    <key>StandardOutPath</key>
    <string>/tmp/auto-backup-stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/auto-backup-stderr.log</string>
</dict>
</plist>

12:00 と 23:00 の 1 日 2 回実行。昼に 1 回、寝る前に 1 回。登録は以下。

cp com.yourname.auto-backup.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.yourname.auto-backup.plist

StandardOutPathStandardErrorPath は必ず入れておく。launchd はデフォルトで stdout/stderr を捨てるので、トラブル時に何も手がかりがなくなる。/tmp/ に吐いておけば十分。

2 週間回した結果

14 日間で 30 回以上のコミットが自動で積まれた。ログの一部がこれ。

Day 14(2026-03-19): チーム定義(24ファイル)
Day 14(2026-03-19): Mailchimp開通(19ファイル)
Day 13(2026-03-18): 自動化・リサーチ(31ファイル)
Day 12(2026-03-17): 戦略・コンテンツ(18ファイル)
Day 11(2026-03-16): 戦略(12ファイル)

同じ Day に複数コミットがある日は「たくさん動いた日」。ファイル数が多い日は「大きな変更があった日」。逆に Day が飛んでいる日は何もしなかった日、ではなく変更がなかった日。空コミットを作らないから、ログに嘘がない。

「Day 12 に大きな設計変更をした」「Day 13 から自動化フェーズに入った」。こういう流れが、意識しなくても記録されている。手動で書いたら三日坊主で終わるタイプの記録が、勝手に溜まっていく。

注意点と Tips

git add -A のリスク。 全ファイルをステージングするので、.env やクレデンシャルが混入する危険がある。.gitignore を事前にしっかり書いておくこと。自動コミットだからこそ、gitignore が最後の砦になる。

push に失敗しても気づかない。 自動実行なので、ネットワーク障害や認証切れで push が失敗しても通知が来ない。stderr ログを定期的に確認するか、失敗時に通知を飛ばす仕組みを入れるといい。自分は stderr ログを別のスクリプトで監視している。

基準日は一度決めたら変えない。 途中で変えると Day N の連番が壊れる。プロジェクト開始日やチーム発足日など、意味のある日を最初に決めること。

cron ではなく launchd を使う理由。 macOS Ventura 以降、cron は非推奨。launchd はスリープ復帰後の遅延実行に対応している。ノート PC を閉じて翌朝開けたときに、昨晩のバックアップが走る。cron にはこの動きがない。

まとめ

シェルスクリプト 30 行と plist 1 枚。やっていることは地味だ。でも 2 週間後に git log を見たとき、「自分は毎日ちゃんと進んでいた」と数字で確認できる。

日記は続かない。でも git は勝手に書いてくれる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?