Git Automation with GitPython
This guide demonstrates how to automate common Git operations (clone, add, commit, push, pull) using the GitPython library. This is useful for build scripts, automated backups, or managing multiple repositories programmatically.
Modules Used:
git(GitPython): To interact with Git repositories.- argparse: To handle command-line arguments.
Installation
You need to install GitPython. You also need git installed on your system and available in your PATH.
pip install GitPython
The Code
Save this as git_tool.py.
import git
from git import Repo
import argparse
import os
import sys
def clone_repo(url, destination):
if os.path.exists(destination):
print(f"Error: Destination '{destination}' already exists.")
return
try:
print(f"Cloning {url} to {destination}...")
Repo.clone_from(url, destination)
print("Clone successful.")
except Exception as e:
print(f"Clone failed: {e}")
def handle_repo(path, commit_msg=None, push=False, pull=False):
try:
repo = Repo(path)
if repo.bare:
print(f"Error: '{path}' is a bare repository.")
return
print(f"Repository: {path}")
print(f"Active Branch: {repo.active_branch}")
# 1. Pull
if pull:
print("Pulling changes from origin...")
origin = repo.remotes.origin
origin.pull()
print("Pull complete.")
# 2. Commit
if commit_msg:
# Check if there are changes (modified or untracked)
if repo.is_dirty(untracked_files=True):
print("Changes detected.")
# Stage all files (git add .)
print("Staging all files...")
repo.git.add(A=True)
# Commit
print(f"Committing: {commit_msg}")
repo.index.commit(commit_msg)
print("Commit successful.")
# 3. Push (only if committed)
if push:
print("Pushing to origin...")
origin = repo.remotes.origin
origin.push()
print("Push successful.")
else:
print("No changes to commit.")
elif push:
# Push without commit if requested
print("Pushing to origin...")
origin = repo.remotes.origin
origin.push()
print("Push successful.")
except git.exc.InvalidGitRepositoryError:
print(f"Error: '{path}' is not a valid Git repository.")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Git Automation Tool")
subparsers = parser.add_subparsers(dest="command", help="Command to run")
# Clone Command
clone_parser = subparsers.add_parser("clone", help="Clone a repository")
clone_parser.add_argument("url", help="Repository URL")
clone_parser.add_argument("dest", help="Destination folder")
# Sync Command (Commit/Push/Pull)
sync_parser = subparsers.add_parser("sync", help="Sync a repository (Commit, Push, Pull)")
sync_parser.add_argument("path", help="Path to local repository")
sync_parser.add_argument("-m", "--message", help="Commit message (required for commit)")
sync_parser.add_argument("--push", action="store_true", help="Push changes to remote")
sync_parser.add_argument("--pull", action="store_true", help="Pull changes from remote before committing")
args = parser.parse_args()
if args.command == "clone":
clone_repo(args.url, args.dest)
elif args.command == "sync":
handle_repo(args.path, args.message, args.push, args.pull)
else:
parser.print_help()
Usage
# Clone a repo
python git_tool.py clone https://github.com/gitpython-developers/GitPython.git ./my_repo
# Pull latest changes
python git_tool.py sync ./my_repo --pull
# Add all changes, commit, and push
python git_tool.py sync ./my_repo -m "Automated backup" --push