Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Github_repo_auditor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Git Repo Auditor

A Python script to **analyze and report the status** of all Git repositories within a given directory.

## 🔍 What It Does

This script recursively scans a directory for Git repositories and reports:

- **Uncommitted Changes**: Repos with local changes not yet staged or committed.
- **Ahead of Remote**: Repos that have local commits not yet pushed.
- **Behind Remote**: Repos that are missing commits from the remote.
- **Inactive Repos**: Repos with no commits in the last **30 days**.

## Features

- Scans nested folders for `.git` directories.
- Uses `git status` and `git log` to assess health and activity.
- Helps developers **organize, clean, and maintain** their local projects.
- No dependencies except Python 3 and Git.

## Usage

```bash
python3 git_repo_auditor.py /path/to/your/projects
```

## Screenshots

![Git Repo Status](git_repo_auditor.png)


Binary file added Github_repo_auditor/git_repo_auditor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions Github_repo_auditor/github_repo_auditor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python3

import os
import subprocess
from pathlib import Path
from datetime import datetime, timedelta

def is_git_repo(path):
return (path / '.git').exists()

def run_git_command(repo_path, args):
try:
result = subprocess.run(
['git'] + args,
cwd=repo_path,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
return result.stdout.strip()
except Exception as e:
return ""

def check_repo_status(repo_path):
status = {
'path': str(repo_path),
'uncommitted_changes': False,
'ahead': False,
'behind': False,
'inactive': False,
'last_commit': None,
}

# Uncommitted changes
changes = run_git_command(repo_path, ['status', '--porcelain'])
if changes:
status['uncommitted_changes'] = True

# Ahead/Behind
run_git_command(repo_path, ['remote', 'update']) # Update remote tracking
branch_info = run_git_command(repo_path, ['status', '-sb'])
if 'ahead' in branch_info:
status['ahead'] = True
if 'behind' in branch_info:
status['behind'] = True

# Last commit date
last_commit_date = run_git_command(repo_path, ['log', '-1', '--format=%ci'])
if last_commit_date:
commit_time = datetime.strptime(last_commit_date, '%Y-%m-%d %H:%M:%S %z')
status['last_commit'] = commit_time
if datetime.now(commit_time.tzinfo) - commit_time > timedelta(days=30):
status['inactive'] = True

return status

def scan_repos(base_dir):
base = Path(base_dir).expanduser()
for root, dirs, files in os.walk(base):
root_path = Path(root)
if is_git_repo(root_path):
yield check_repo_status(root_path)
dirs[:] = [] # Do not recurse into nested repos

def print_report(repos):
for repo in repos:
path = repo['path']
if repo['uncommitted_changes']:
print(f"[!] Uncommitted changes: {path}")
if repo['ahead']:
print(f"[↑] Ahead of origin/main: {path}")
if repo['behind']:
print(f"[↓] Behind origin/main: {path}")
if repo['inactive']:
last = repo['last_commit'].strftime('%Y-%m-%d')
print(f"[-] Inactive >30 days: {path} (Last: {last})")

if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print("Usage: python git-repo-cleaner.py <base_directory>")
sys.exit(1)

base_dir = sys.argv[1]
print(f"📁 Scanning Git repos in: {base_dir}\n")
results = list(scan_repos(base_dir))
print_report(results)
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ So far, the following projects have been integrated to this repo:
|[Zip password cracker](zip_password_cracker)|[umar abdullahi](https://github.com/umarbrowser)|
|[Task Scheduler](Task-Scheduler)|[heysagnik](https://github.com/heysagnik)|
|[PDF Password Decypter](PDF_Password_Decrypter)|[parthasdey2304](https://github.com/parthasdey2304)|
|[Github repo auditor](Github_repo_auditor)|[av4nth1ka](https://github.com/av4nth1ka)|

## How to use:
- Clone/Download the directory and navigate to each folder. Or...
Expand Down