Skip to content

Instantly share code, notes, and snippets.

@kartben
Created January 27, 2025 16:02
Show Gist options
  • Save kartben/a18380a4b807f411a0aac9c1ab3060e6 to your computer and use it in GitHub Desktop.
Save kartben/a18380a4b807f411a0aac9c1ab3060e6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import subprocess
import csv
from collections import defaultdict
from datetime import datetime
def get_contributor_commits():
try:
# Get all commits with commit date and author, sorted by oldest first
git_log = subprocess.check_output(
['git', 'log', '--format=%cI###%aN', '--reverse', '--use-mailmap', '--mailmap'],
universal_newlines=True
)
except subprocess.CalledProcessError:
print("Error: Failed to get git log. Are you in a git repository?")
return None
# Dictionary to store monthly stats and author counts
monthly_stats = defaultdict(lambda: defaultdict(int))
all_time_author_commits = defaultdict(int) # Track total commits per author
current_month = None
# Process each commit chronologically
for line in git_log.strip().split('\n'):
date_str, email = line.split('###')
date = datetime.fromisoformat(date_str)
month_key = f"{date.year}-{date.month:02d}"
# When we move to a new month, calculate stats for all authors
if month_key != current_month:
if current_month is not None:
# Calculate stats based on cumulative commits for all authors
monthly_stats[current_month] = defaultdict(int)
for author, commit_count in all_time_author_commits.items():
if commit_count == 1:
monthly_stats[current_month]['1'] += 1
elif 2 <= commit_count < 5:
monthly_stats[current_month]['2-5'] += 1
elif 5 <= commit_count < 20:
monthly_stats[current_month]['5+'] += 1
elif 20 <= commit_count < 100:
monthly_stats[current_month]['20+'] += 1
elif commit_count >= 100:
monthly_stats[current_month]['100+'] += 1
print(f"Completed month {current_month}: "
f"1 commit: {monthly_stats[current_month]['1']}, "
f"2-5 commits: {monthly_stats[current_month]['2-5']}, "
f"5+ commits: {monthly_stats[current_month]['5+']}, "
f"20+ commits: {monthly_stats[current_month]['20+']}, "
f"100+ commits: {monthly_stats[current_month]['100+']}")
current_month = month_key
# Simply update the author's total commit count
all_time_author_commits[email] += 1
# Calculate stats for the final month
if current_month:
monthly_stats[current_month] = defaultdict(int)
for author, commit_count in all_time_author_commits.items():
if commit_count == 1:
monthly_stats[current_month]['1'] += 1
elif 2 <= commit_count < 5:
monthly_stats[current_month]['2-5'] += 1
elif 5 <= commit_count < 20:
monthly_stats[current_month]['5+'] += 1
elif 20 <= commit_count < 100:
monthly_stats[current_month]['20+'] += 1
elif commit_count >= 100:
monthly_stats[current_month]['100+'] += 1
print(f"Completed month {current_month}: "
f"1 commit: {monthly_stats[current_month]['1']}, "
f"2-5 commits: {monthly_stats[current_month]['2-5']}, "
f"5+ commits: {monthly_stats[current_month]['5+']}, "
f"20+ commits: {monthly_stats[current_month]['20+']}, "
f"100+ commits: {monthly_stats[current_month]['100+']}")
return monthly_stats
def write_csv(stats):
# Sort months chronologically
months = sorted(stats.keys())
with open('contributor_stats.csv', 'w', newline='') as f:
writer = csv.writer(f)
# Write header
writer.writerow(['Month', '1 commit', '2-5 commits', '5+ commits', '20+ commits', '100+ commits'])
# Write data for each month
for month in months:
# Convert YYYY-MM to YYYY-MM-01 for Excel compatibility
year, month_num = month.split('-')
excel_date = f"{year}-{month_num}-01"
writer.writerow([
excel_date,
stats[month]['1'],
stats[month]['2-5'],
stats[month]['5+'],
stats[month]['20+'],
stats[month]['100+']
])
def main():
print("Analyzing git repository...")
stats = get_contributor_commits()
write_csv(stats)
print("Statistics have been written to contributor_stats.csv")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment