Siapapun yang pertama di pagi hari git status mengetik dan kemudian minum kopi akan menyukai pembantu kecil ini. Terutama ketika banyak proyek web sedang dikembangkan secara paralel, ada satu proyek yang layak dilakukan gambaran ringkas: Di mana pohon kerja bersih, di mana perubahan yang tidak digabungkan digantung, dan di mana tarikan/dorongan menunggu? Alat shell kecil akan berhasil - asalkan dapat menangani spasi/Unicode dengan kuat di jalur dan tidak tersedak pada remote yang digantung.
#!/usr/bin/env bash
set -Eeuo pipefail
export LC_ALL=C
# Check if a command exists (no output).
have() { command -v "$1" >/dev/null 2>&1; }
# Ensure we have a `sort` that supports -z (NUL-delimited) input.
SORT_BIN="sort"
if ! "$SORT_BIN" -z </dev/null 2>/dev/null; then
if have gsort && gsort -z </dev/null 2>/dev/null; then
SORT_BIN="gsort"
else
printf 'Error: This script requires "sort -z" (GNU coreutils). Install coreutils (gsort).\n' >&2
exit 1
fi
fi
# Use GNU `timeout` if available; otherwise try `gtimeout` (macOS); otherwise no timeout.
TIMEOUT_BIN="timeout"
if ! have "$TIMEOUT_BIN"; then
if have gtimeout; then
TIMEOUT_BIN="gtimeout"
else
TIMEOUT_BIN=""
fi
fi
# Require git.
if ! have git; then
printf 'Error: "git" not found.\n' >&2
exit 1
fi
# Remove a leading "./" from a path for cleaner output.
trim_dot_slash() {
case "$1" in
./*) printf '%s\n' "${1#./}" ;;
*) printf '%s\n' "$1" ;;
esac
}
# Legend + divider (as requested)
printf '\n🟢: clean\n🟡: behind/ahead\n🔴: modified\n\n----------------------------------\n\n'
# Find all .git directories, NUL-delimited; sort NUL-delimited; iterate safely.
find . -type d -name .git -print0 \
| "$SORT_BIN" -z \
| while IFS= read -r -d '' gitdir; do
repo="${gitdir%/.git}"
display_path="$(trim_dot_slash "$repo")"
# Skip anything that isn't a proper work tree (safety check).
if ! git -C "$repo" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
continue
fi
# Working tree status; include untracked files for a strict "red" signal.
status_out="$(git -C "$repo" status --porcelain=v1 || true)"
# Upstream divergence check (only if an upstream is configured).
ahead=0
behind=0
if git -C "$repo" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
# Refresh refs; protect with timeout so a hanging remote doesn't stall the loop.
if [ -n "$TIMEOUT_BIN" ]; then
"$TIMEOUT_BIN" 10s git -C "$repo" fetch --all --prune >/dev/null 2>&1 || true
else
git -C "$repo" fetch --all --prune >/dev/null 2>&1 || true
fi
# Count commits only on our side (ahead) and only on upstream's side (behind).
ahead="$(git -C "$repo" rev-list --count --left-only HEAD...@{u} 2>/dev/null || echo 0)"
behind="$(git -C "$repo" rev-list --count --right-only HEAD...@{u} 2>/dev/null || echo 0)"
fi
# Decide the signal:
# - RED if the working tree isn't clean
# - YELLOW if clean but ahead/behind of upstream
# - GREEN otherwise
if [ -n "$status_out" ]; then
printf '🔴 %s\n' "$display_path"
else
if [ "${ahead:-0}" -gt 0 ] || [ "${behind:-0}" -gt 0 ]; then
printf '🟡 %s\n' "$display_path"
else
printf '🟢 %s\n' "$display_path"
fi
fi
done
Naskahnya masih perlu... chmod +x ~/path/to/script.sh membuatnya dapat dieksekusi dan dapat mengatur alias untuk menyimpan pengetikan yang berharga: Di sini Anda menambahkan ke ~/.bashrc / ~/.zshrc / ~/.bash_profile pintu masuk alias gscan='bash /path/to/script.sh' Selain itu. Sejak saat itu, sebuah gscan di direktori root yang diinginkan.
Penjelasan mengapa proses kedua terasa lebih cepat: Selama proses pertama, sistem file masih harus memindai semuanya; setelah itu metadata dan banyak lagi .git-Struktur telah masuk ke dalam cache halaman sistem operasi. Referensi dan grafik commit juga telah dipersiapkan. Selanjutnya fetch Sekarang, sebagian besar hanya mengirimkan delta kecil. Tanpa dasbor, tanpa overhead – snapshot status cepat langsung di terminal.