Created
June 17, 2025 17:20
-
-
Save antonlvovych/190ce978fbf95e4671c18e2205173d8d to your computer and use it in GitHub Desktop.
Git Insights Script - Enhanced version with auto-generated file exclusions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Git Insights Script - Enhanced version with auto-generated file exclusions | |
# Usage: sh git-insights.sh [start_date] [end_date] | |
# Example: sh git-insights.sh 2024-01-01 2024-12-31 | |
function days_between { | |
local start_timestamp="$1" | |
local end_timestamp="$2" | |
local seconds_diff=$((end_timestamp - start_timestamp)) | |
local days_diff=$((seconds_diff / 86400)) # 86400 seconds in a day | |
echo "$days_diff" | |
} | |
# Use git to filter files (respects .gitignore automatically) | |
# No manual exclude patterns needed - git ls-files only shows tracked files | |
# Get project date range | |
first_commit_hash=$(git rev-list --max-parents=0 HEAD) | |
last_commit_hash=$(git rev-parse HEAD) | |
start_timestamp=$(git log -n 1 --pretty=format:%ct "$first_commit_hash") | |
end_timestamp=$(git log -n 1 --pretty=format:%ct "$last_commit_hash") | |
days_diff=$(days_between "$start_timestamp" "$end_timestamp") | |
first_commit_date=$(git log -n 1 --pretty=format:%ci --date=format-local:"%Y-%m-%d" "$first_commit_hash") | |
last_commit_date=$(git log -n 1 --pretty=format:%ci --date=format-local:"%Y-%m-%d" "$last_commit_hash") | |
# Parse command line arguments | |
start_date="$1" | |
end_date="$2" | |
if [ -n "$start_date" ]; then | |
stats_start_timestamp=$(date -jf "%Y-%m-%d" "$start_date" "+%s") | |
stats_start_date=$(date -jf "%s" "$stats_start_timestamp" "+%Y-%m-%d") | |
stats_start_date_str=$stats_start_date | |
else | |
stats_start_timestamp=$start_timestamp | |
stats_start_date=$(date -jf "%s" "$stats_start_timestamp" "+%Y-%m-%d") | |
stats_start_date_str=$stats_start_date | |
fi | |
if [ -n "$end_date" ]; then | |
stats_end_timestamp=$(date -jf "%Y-%m-%d" "$end_date" "+%s") | |
stats_end_date=$(date -jf "%s" "$stats_end_timestamp" "+%Y-%m-%d") | |
stats_end_date_str=$stats_end_date | |
else | |
stats_end_timestamp=$(date +%s) | |
stats_end_date=$(date -jf "%s" "$stats_end_timestamp" "+%Y-%m-%d") | |
stats_end_date_str=$stats_end_date | |
fi | |
echo "π Git Repository Insights" | |
echo "==========================" | |
echo "π Analysis Period: $stats_start_date_str to $stats_end_date_str" | |
echo "" | |
echo "π Code Statistics (Git Tracked Files)" | |
echo "==================================================" | |
# Test files and test cases | |
TEST_FILES=$(git ls-files | grep -E '\.(test|spec)\.(js|ts)$|/__tests__/|/tests?/' | wc -l | tr -d ' ') | |
TEST_LINES=$(git ls-files | grep -E '\.(test|spec)\.(js|ts)$|/__tests__/|/tests?/' | xargs cat 2>/dev/null | wc -l | tr -d ' ') | |
TEST_CASES=$(git ls-files | grep -E '\.(test|spec)\.(js|ts)$|/__tests__/|/tests?/' | xargs grep -E "^\s*(test|it)\s*\(" 2>/dev/null | wc -l | tr -d ' ') | |
# Real code files (excluding docs and data files, including tests) | |
CODE_FILES=$(git ls-files | grep -vE '\.md$|^data/|^logs/' | wc -l | tr -d ' ') | |
CODE_LINES=$(git ls-files | grep -vE '\.md$|^data/|^logs/' | xargs cat 2>/dev/null | wc -l | tr -d ' ') | |
# Documentation files | |
DOC_FILES=$(git ls-files | grep -E '\.md$' | wc -l | tr -d ' ') | |
DOC_LINES=$(git ls-files | grep -E '\.md$' | xargs cat 2>/dev/null | wc -l | tr -d ' ') | |
# Total | |
TOTAL_FILES=$(git ls-files | wc -l | tr -d ' ') | |
TOTAL_LINES=$(git ls-files | xargs cat 2>/dev/null | wc -l | tr -d ' ') | |
echo "β’ Code files (inc. tests): $CODE_FILES ($CODE_LINES lines)" | |
echo "β’ Test files breakdown: $TEST_FILES ($TEST_LINES lines, $TEST_CASES test cases)" | |
echo "β’ Documentation files: $DOC_FILES ($DOC_LINES lines)" | |
echo "β’ Total files tracked: $TOTAL_FILES ($TOTAL_LINES lines)" | |
echo "" | |
echo "π Change Statistics (All Files)" | |
echo "================================" | |
git log --shortstat --no-merges --since=$stats_start_date_str --until=$stats_end_date_str | grep -E "fil(e|es) changed" | awk '{files+=$1; inserted+=$4; deleted+=$6; delta+=$4-$6; ratio=(deleted>0?deleted/inserted:0)} END {printf "β’ Files changed: %s\nβ’ Lines added: %s\nβ’ Lines deleted: %s\nβ’ Net lines: %s\nβ’ Add/Del ratio: 1:%.2f\n", files, inserted, deleted, delta, ratio }' | |
echo "" | |
echo "π Change Statistics (Excluding Data Files)" | |
echo "===========================================" | |
git log --numstat --no-merges --since=$stats_start_date_str --until=$stats_end_date_str | grep -E '^[0-9-]+\s+[0-9-]+' | grep -vE '\s+(data/|logs/)' | awk '{if($1 != "-" && $2 != "-") {inserted+=$1; deleted+=$2}} END {printf "β’ Lines added (code): %s\nβ’ Lines deleted (code): %s\nβ’ Net lines (code): %s\n", inserted+0, deleted+0, inserted-deleted}' | |
echo "" | |
echo "π₯ Contributors" | |
echo "===============" | |
git shortlog -sn --no-merges --since=$stats_start_date_str --until=$stats_end_date_str | while read commits author; do | |
echo "β’ $author: $commits commits" | |
done | |
echo "" | |
echo "β° Peak Activity Hours (All Commits in Period)" | |
echo "==============================================" | |
git log --format="%ad" --date=format:"%H" --since=$stats_start_date_str --until=$stats_end_date_str | sort | uniq -c | sort -nr | head -10 | while read count hour; do | |
echo "β’ ${hour}:00 - $count commits" | |
done | |
echo "" | |
echo "π Most Active Code Files (Including Tests)" | |
echo "===========================================" | |
git log --name-only --pretty=format: --since=$stats_start_date_str --until=$stats_end_date_str | grep -v '^$' | grep -vE '\.md$|^data/|^logs/' | sort | uniq -c | sort -nr | head -10 | while read count file; do | |
echo "β’ $file ($count changes)" | |
done | |
echo "" | |
echo "π§ͺ Most Active Test Files" | |
echo "=========================" | |
git log --name-only --pretty=format: --since=$stats_start_date_str --until=$stats_end_date_str | grep -v '^$' | grep -E '\.(test|spec)\.(js|ts)$|/__tests__/|/tests?/' | sort | uniq -c | sort -nr | head -5 | while read count file; do | |
echo "β’ $file ($count changes)" | |
done | |
echo "" | |
echo "π Most Active Documentation Files" | |
echo "==================================" | |
git log --name-only --pretty=format: --since=$stats_start_date_str --until=$stats_end_date_str | grep -v '^$' | grep -E '\.md$' | sort | uniq -c | sort -nr | head -10 | while read count file; do | |
echo "β’ $file ($count changes)" | |
done | |
echo "" | |
echo "π·οΈ Recent Commits" | |
echo "==================" | |
git log --oneline -10 --since=$stats_start_date_str --until=$stats_end_date_str --pretty=format:"β’ %s (%an)" | head -10 | |
echo "" | |
echo "π Project Timeline" | |
echo "==================" | |
echo "β’ First commit: $first_commit_date" | |
echo "β’ Latest commit: $last_commit_date" | |
echo "β’ Project age: $days_diff days" | |
# Calculate activity metrics | |
COMMITS_IN_PERIOD=$(git rev-list --count --since=$stats_start_date_str --until=$stats_end_date_str HEAD) | |
PERIOD_DAYS=$(days_between "$stats_start_timestamp" "$stats_end_timestamp") | |
if [ "$PERIOD_DAYS" -gt 0 ]; then | |
COMMITS_PER_DAY=$(echo "scale=1; $COMMITS_IN_PERIOD / $PERIOD_DAYS" | bc -l 2>/dev/null || echo "N/A") | |
else | |
COMMITS_PER_DAY="N/A" | |
fi | |
echo "" | |
echo "π Summary for Analysis Period" | |
echo "=============================" | |
echo "β’ $COMMITS_IN_PERIOD commits across $PERIOD_DAYS days" | |
echo "β’ Average commits/day: $COMMITS_PER_DAY" | |
echo "β’ Code lines (inc. tests): $CODE_LINES" | |
echo "β’ Documentation lines: $DOC_LINES" | |
# Get net lines for period and daily average (excluding data files) | |
NET_LINES=$(git log --numstat --no-merges --since=$stats_start_date_str --until=$stats_end_date_str | grep -E '^[0-9-]+\s+[0-9-]+' | grep -vE '\s+(data/|logs/)' | awk '{if($1 != "-" && $2 != "-") {delta+=$1-$2}} END {print delta+0}') | |
if [ "$PERIOD_DAYS" -gt 0 ] && [ -n "$NET_LINES" ]; then | |
DAILY_LINES=$(echo "scale=0; $NET_LINES / $PERIOD_DAYS" | bc -l 2>/dev/null || echo "N/A") | |
echo "β’ Net lines added (code): $NET_LINES" | |
echo "β’ Average lines/day (code): $DAILY_LINES" | |
fi | |
# Peak hours summary | |
PEAK_HOURS=$(git log --format="%ad" --date=format:"%H" --since=$stats_start_date_str --until=$stats_end_date_str | sort | uniq -c | sort -nr | head -3 | awk '{printf "%s:00, ", $2}' | sed 's/, $//') | |
if [ -n "$PEAK_HOURS" ]; then | |
echo "β’ Peak hours: $PEAK_HOURS" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment