How to Run Git Commands from Python with subprocess

This helper runs `git status --short` and `git log --oneline` from Python, captures their output, and returns readable strings with error handling for non-repo directories.

Easy Python 3.9+ Aug 9, 2026 Git + Python 14 views 0 copies

Python code

36 lines
Python 3.9+
import subprocess


def git_status():
    """Return a short, human-readable git status."""
    try:
        output = subprocess.run(
            ["git", "status", "--short"],
            capture_output=True,
            text=True,
            check=True,
        ).stdout.strip()
        return output if output else "Working directory is clean."
    except subprocess.CalledProcessError:
        return "Error: not a git repository."


def git_log(limit=5):
    """Return the last `limit` commit messages."""
    try:
        output = subprocess.run(
            ["git", "log", "--oneline", f"-{limit}"],
            capture_output=True,
            text=True,
            check=True,
        ).stdout.strip()
        return output if output else "No commits yet."
    except subprocess.CalledProcessError:
        return "Error: not a git repository."


if __name__ == "__main__":
    print("=== Git Status ===")
    print(git_status())
    print("\n=== Recent Commits ===")
    print(git_log())

Output

stdout
=== Git Status ===
 M README.md
?? new_file.txt

=== Recent Commits ===
3f2e1a4 Add README
2b8c9d0 Fix typo
1a2b3c4 Initial commit

How it works

The subprocess.run function executes a command and captures its output when capture_output=True is set. Passing text=True makes the output a string instead of bytes, which is easier to handle. The check=True flag raises a CalledProcessError if the command exits with a non-zero status, allowing us to catch errors like running outside a git repository. The --short and --oneline flags produce concise, human-readable output, and stripping whitespace keeps the result clean. This pattern is safe for simple read-only Git commands and avoids shell injection by passing arguments as a list.

Common mistakes

  • Using `shell=True` with command strings instead of a list of arguments, which risks injection and quoting bugs.
  • Forgetting `text=True`, causing bytes output that needs manual decoding.
  • Not handling `CalledProcessError` when running commands outside a git repo.
  • Assuming `check=True` is optional; without it, failures go unnoticed.

Variations

  1. Use `git rev-parse --short HEAD` to get the current commit hash.
  2. Parse the output with `splitlines()` to get a list of status lines for programmatic use.

Real-world use cases

  • A CI script that checks for uncommitted changes before deploying.
  • A developer tool that shows repo status and recent commits without leaving the terminal.
  • An automation bot that gathers commit history for changelog generation.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Git + Python

Related tutorials and quizzes for this topic.