指定フォルダ配下の Git ローカルリポジトリ全てに対して Commit 済かどうか、Push 済どうかを表示する

背景

複数の PC から GitHub を使っているので、Commit や Push のし忘れがあると萎える(例: 「あー外出先の MBA で書いた内容、Push されてないやん……」)。

これを防止するために、以下の運用を考えた。

  • 「Commit/Push の状況を一覧表示するバッチファイル」を作る ……★1
  • タスク管理ツールに「コミット状況確認バッチを叩け!」という定期タスクを追加する
  • この定期タスクを、PC を使い終える直前のタイミングで実行するよう配置する

私はタスク管理ツールに従って動いているので、こうすれば忘れることはない。

今回やりたいのは、この ★1 部分を実現するバッチファイルを作る、ということ。

前提

(1)Windows で msysgit を使っていること。

$ git --version
git version 1.8.5.2.msysgit.0

(2)以下のようなフォルダ構造で運用していること。

$ cd
D:\work\github\stakiran

$ dir /b
100q       ← git clone 100q で clone した
2to3       ← git clone 2to3 で clone した
batchat
bin
bodyclock
booklog
...        ★こんな感じで一フォルダ内にローカルリポジトリを集めている

バッチファイル中身

@echo off
setlocal
set TERM=msys
for /F "usebackq" %%i in (`dir %~dp0 /b /ad`) do (
    if exist %~dp0%%i\.git (
        pushd %~dp0%%i
        echo [%%i]
        git status --short
        git diff origin/master --name-status
        popd
    )
)
pause

使い方

  • 上記バッチファイルを適当な名前(例: status_all.bat)で保存
  • ローカルリポジトリが集まってるフォルダに上記バッチファイルを置く
  • バッチファイルを叩く
    • 必要ならランチャ等から素早く呼べるようにしておく

実行結果

[100q]
[2to3]
[batchat]
 M README.md            ← まだCommitしてない
M       README.md       ← まだPushしてない
[bin]
[bodyclock]
[booklog]
M       201710.md       ← まだPushしてない
M       index.md        ← まだPushしてない
...
続行するには何かキーを押してください . . .

実装のはなし

使った Git コマンド

  • git status --short

Commitしてないファイルは(まだバージョン管理されてないファイルも含めて)これでわかる。

  • git diff origin/master --name-status

これはリモート側とコミットが一致してない時に差分(のStatus)を表示するコマンド。このコマンドの結果が出た=Pushがまだだよ、を意味する。Commit したけど Push してない せいで萎えたことは一度や二度じゃないので、このコマンドは重要。

※ちなみに origin/master 固定なのはオレオレ運用。ぼっち GitHub だと master だけで十分なのです。

バッチファイル詳細

setlocal
set TERM=msys

これは msysgit で標準出力のワーニング(WARNING: terminal is not fully functional)が出るのを抑止するおまじない。

for /F "usebackq" %%i in (`dir %~dp0 /b /ad`) do (

これは dir ... の部分で列挙されたファイル名の一つ一つが %%i に渡りますよ、というおまじない。dir /b /ad は「ディレクトリだけ列挙してね」「余分な情報はいいからディレクトリ名だけ列挙してね」という指定。

 if exist %~dp0%%i\.git (
        pushd %~dp0%%i
        echo [%%i]
        git status --short
        git diff origin/master --name-status
        popd
    )

やってることは if exist で .git フォルダの存在を確認して、存在しているならローカルリポジトリとみなして、status と diff を確認する……という感じ。あと、カレントディレクトリを(ローカルリポジトリの中に)移さないと git コマンドが動かないので、pushd/popd で移っている。

おわりに

これで Commit と Push をし忘れることがなくなった。また一つストレスを減らせた。