git_cleaner.py: Rekurzivně spustit git gc na všech vašich repozitářích
Tento skript, git_cleaner.py, je navržen pro rekurzivní prohledávání zadaného adresáře (nebo aktuálního adresáře ve výchozím nastavení) pro Git repozitáře a spuštění git gc na každém z nich. Zaznamenává velikost a počet souborů adresáře .git před a po spuštění git gc, což umožňuje vidět, kolik místa bylo uvolněno a kolik souborů bylo odstraněno. Skript také poskytuje konečné shrnutí všech zpracovaných repozitářů.
git_cleaner.py
#!/usr/bin/env python3
import os
import subprocess
import argparse
import sys
def get_dir_stats(path):
"""Vrací tuple (celková_velikost_bajty, celkový_počet_souborů)."""
total_size = 0
file_count = 0
for dirpath, _, filenames in os.walk(path):
for f in filenames:
fp = os.path.join(dirpath, f)
if not os.path.islink(fp):
total_size += os.path.getsize(fp)
file_count += 1
return total_size, file_count
def format_size(bytes_size):
"""Převede bajty na lidsky čitelný řetězec."""
for unit in ['B', 'KB', 'MB', 'GB']:
if abs(bytes_size) < 1024:
return f"{bytes_size:.2f} {unit}"
bytes_size /= 1024
return f"{bytes_size:.2f} TB"
def main():
parser = argparse.ArgumentParser(
description="Recursively run 'git gc', reporting space and files saved."
)
parser.add_argument(
"target_dir",
nargs="?",
default=".",
help="Directory to search (default: '.')"
)
args, unknown_args = parser.parse_known_args()
target_path = os.path.abspath(args.target_dir)
if not os.path.isdir(target_path):
print(f"Error: {target_path} is not a directory.")
sys.exit(1)
total_saved_bytes = 0
total_files_removed = 0
repos_processed = 0
print(f"--- Scanning: {target_path} ---")
for root, dirs, _ in os.walk(target_path):
if ".git" in dirs:
repos_processed += 1
git_dir = os.path.join(root, ".git")
# 1. Zaznamenat statistiky před
size_before, files_before = get_dir_stats(git_dir)
print(f"\n[{repos_processed}] Optimizing: {root}")
try:
# 2. Spustit git gc
# Poznámka: Používáme -C pro spuštění git v konkrétním adresáři
cmd = ["git", "-C", root, "gc"] + unknown_args
subprocess.run(cmd, check=True, capture_output=True)
# 3. Zaznamenat statistiky po
size_after, files_after = get_dir_stats(git_dir)
saved_size = size_before - size_after
removed_files = files_before - files_after
total_saved_bytes += max(0, saved_size)
total_files_removed += max(0, removed_files)
print(f" Files: {files_before} -> {files_after} ({removed_files} removed)")
print(f" Size: {format_size(size_before)} -> {format_size(size_after)} ({format_size(saved_size)} saved)")
except subprocess.CalledProcessError as e:
print(f" [!] Error: {e.stderr.decode().strip()}")
# Efektivita: neprocházet do .git složky, kterou jsme právě zpracovali
dirs.remove(".git")
# Konečná souhrnná tabulka
print("\n" + "="*45)
print(f"{'FINAL SUMMARY':^45}")
print("-" * 45)
print(f" Repositories Processed : {repos_processed}")
print(f" Total Space Reclaimed : {format_size(total_saved_bytes)}")
print(f" Total Files Removed : {total_files_removed}")
print("="*45)
if __name__ == "__main__":
main()Příklad výstupu
git_cleaner_output.txt
[...]
[433] Optimizing: /home/uli/dev/FlareDNS
Files: 73 -> 33 (40 removed)
Size: 70.14 KB -> 47.03 KB (23.10 KB saved)
=============================================
FINAL SUMMARY
---------------------------------------------
Repositories Processed : 433
Total Space Reclaimed : 238.14 MB
Total Files Removed : 21612
=============================================Pokud vám tento článek pomohl, zvažte, zda mi nekoupíte kávu nebo nepřispějete přes PayPal na podporu výzkumu a publikování nových článků na TechOverflow