在多項目協作、企業級工程管理或開源社區維護中,經常面臨需要同時管理數十甚至上百個 Git 倉庫的場景:
多倉庫需要統一
pull
拉取更新定期向多個項目批量
commit
和push
自動備份 Git 項目
批量拉取私有倉庫并管理密鑰
為解決這類高頻、重復、機械性工作,我們可以使用 Python 編寫一個Git 自動化助手工具,實現:
批量 clone 多個遠程 Git 倉庫
批量執行 pull / commit / push
支持設置統一 commit message
支持命令行控制與配置文件管理
支持日志輸出與失敗重試
一、項目功能概覽
功能模塊 | 說明 |
---|---|
倉庫配置 | 支持 YAML / JSON 配置倉庫 URL 和路徑 |
clone 批處理 | 支持跳過已存在目錄,自動 clone 多倉庫 |
pull / commit / push 批量執行 | 一鍵同步所有項目代碼 |
commit message 統一 | 設定統一 commit 信息 |
支持 SSH 密鑰 | 自動化處理私有倉庫訪問 |
日志記錄 | 每次操作都記錄詳細日志,便于追蹤 |
二、技術棧與依賴
技術 / 庫 | 用途 |
---|---|
GitPython | Git 操作封裝庫,簡化命令行交互 |
PyYAML | 配置文件解析 |
os / subprocess | 補充執行 git 命令(部分特殊情況) |
logging | 日志記錄 |
argparse | 命令行參數解析 |
安裝依賴
bash
復制編輯
pip install GitPython PyYAML
三、項目結構設計
bash
復制編輯
git_helper/ ├── main.py # 啟動入口 ├── core/ │ ├── manager.py # 批量管理核心邏輯 │ ├── config.py # 倉庫配置解析 │ └── logger.py # 日志模塊 ├── repos.yaml # 倉庫配置清單 └── logs/ └── run.log # 自動記錄操作日志
四、倉庫配置文件 repos.yaml
使用 YAML 格式管理多倉庫:
yaml
復制編輯
repos: - name: ProjectA url: git@github.com:yourorg/project-a.git path: ./workspace/project-a - name: ProjectB url: https://github.com/yourorg/project-b.git path: ./workspace/project-b
五、配置解析 core/config.py
python
復制編輯
import yaml def load_repos(config_file="repos.yaml"): with open(config_file, "r", encoding="utf-8") as f: data = yaml.safe_load(f) return data["repos"]
六、Git 操作核心模塊 core/manager.py
python
復制編輯
from git import Repo, GitCommandError import os import logging class GitManager: def __init__(self, repos): self.repos = repos def clone_all(self): for repo in self.repos: path = repo["path"] if os.path.exists(path): logging.info(f"[跳過] {repo['name']} 已存在目錄") continue try: Repo.clone_from(repo["url"], path) logging.info(f"[clone成功] {repo['name']}") except GitCommandError as e: logging.error(f"[clone失敗] {repo['name']}: {e}") def pull_all(self): for repo in self.repos: try: r = Repo(repo["path"]) o = r.remotes.origin o.pull() logging.info(f"[pull成功] {repo['name']}") except Exception as e: logging.error(f"[pull失敗] {repo['name']}: {e}") def commit_all(self, message): for repo in self.repos: try: r = Repo(repo["path"]) r.git.add(all=True) if r.is_dirty(): r.index.commit(message) logging.info(f"[commit成功] {repo['name']}") else: logging.info(f"[無修改] {repo['name']}") except Exception as e: logging.error(f"[commit失敗] {repo['name']}: {e}") def push_all(self): for repo in self.repos: try: r = Repo(repo["path"]) r.remotes.origin.push() logging.info(f"[push成功] {repo['name']}") except Exception as e: logging.error(f"[push失敗] {repo['name']}: {e}")
七、日志模塊 core/logger.py
python
復制編輯
import logging import os def setup_logger(): os.makedirs("logs", exist_ok=True) logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("logs/run.log", encoding="utf-8"), logging.StreamHandler() ] )
八、命令行入口 main.py
python
復制編輯
import argparse from core.config import load_repos from core.manager import GitManager from core.logger import setup_logger def main(): setup_logger() parser = argparse.ArgumentParser(description="Git 自動化助手") parser.add_argument("--clone", action="store_true", help="批量 clone 所有倉庫") parser.add_argument("--pull", action="store_true", help="批量 pull 所有倉庫") parser.add_argument("--commit", help="批量 commit 所有倉庫,需指定 commit 信息") parser.add_argument("--push", action="store_true", help="批量 push 所有倉庫") args = parser.parse_args() repos = load_repos() manager = GitManager(repos) if args.clone: manager.clone_all() if args.pull: manager.pull_all() if args.commit: manager.commit_all(args.commit) if args.push: manager.push_all() if __name__ == "__main__": main()