Skip to content

Instantly share code, notes, and snippets.

@di-sukharev
Created November 12, 2024 21:20
Show Gist options
  • Save di-sukharev/969c159518b5177d55b258b8bfd702cf to your computer and use it in GitHub Desktop.
Save di-sukharev/969c159518b5177d55b258b8bfd702cf to your computer and use it in GitHub Desktop.
lines of code per day per person and first/last commit ta
#!/bin/bash
echo "" # Start with a blank line
# Function to calculate time difference in hours and minutes
calculate_duration() {
local diff_seconds=$1
local hours=$((diff_seconds / 3600))
local minutes=$(( (diff_seconds % 3600) / 60 ))
printf "%02d:%02d" $hours $minutes
}
# Function to process commits for an email
process_commits() {
local email=$1
local name=$(git log --author="$email" --format="%aN" -n 1)
echo "Analyzing commits for $name ($email)..."
echo ""
# Create temporary files for sorting
local commits_file=$(mktemp)
local days_file=$(mktemp)
local output_file=$(mktemp)
# Get all commits
git log --author="$email" --format="%at|%h|%s" --date=raw > "$commits_file"
# Get unique dates in reverse chronological order
local total_seconds=0
while IFS="|" read -r timestamp hash message; do
echo "$(date -r "$timestamp" "+%Y%m%d")|$(date -r "$timestamp" "+%d.%m.%Y")" >> "$days_file"
done < "$commits_file"
# Process each day in reverse chronological order
sort -r -u "$days_file" | while IFS="|" read -r sortkey date; do
local first_ts=""
local first_hash=""
local first_msg=""
local last_ts=""
local last_hash=""
local last_msg=""
local day_lines=""
local all_day_hashes=""
# Find first and last commit for this day
while IFS="|" read -r timestamp hash message; do
commit_date=$(date -r "$timestamp" "+%d.%m.%Y")
if [ "$commit_date" = "$date" ]; then
# Collect all hashes for this day
all_day_hashes="$all_day_hashes $hash"
if [ -z "$first_ts" ] || [ "$timestamp" -lt "$first_ts" ]; then
first_ts=$timestamp
first_hash=$hash
first_msg=$(echo "$message" | cut -c 1-40)
fi
if [ -z "$last_ts" ] || [ "$timestamp" -gt "$last_ts" ]; then
last_ts=$timestamp
last_hash=$hash
last_msg=$(echo "$message" | cut -c 1-40)
fi
fi
done < "$commits_file"
if [ ! -z "$first_ts" ]; then
first_time=$(date -r "$first_ts" "+%H:%M")
last_time=$(date -r "$last_ts" "+%H:%M")
day_seconds=$((last_ts - first_ts))
duration=$(calculate_duration $day_seconds)
total_seconds=$((total_seconds + day_seconds))
# Calculate total lines changed for all commits this day
local total_added=0
local total_deleted=0
for hash in $all_day_hashes; do
while IFS=$'\t' read -r add del file; do
# Skip ANY generated/build files
if [[ "$file" != *.wrangler/* ]] &&
[[ "$file" != *.next/* ]] &&
[[ "$file" != *.turbo/* ]] &&
[[ "$file" != */node_modules/* ]] &&
[[ "$file" != */dist/* ]] &&
[[ "$file" != */build/* ]] &&
[[ "$file" != *.lock ]] &&
[[ "$file" != *.map ]] &&
[[ "$file" != *package-lock.json ]] &&
[[ "$file" != *pnpm-lock.yaml ]]; then
if [[ "$add" =~ ^[0-9]+$ ]]; then
total_added=$((total_added + add))
fi
if [[ "$del" =~ ^[0-9]+$ ]]; then
total_deleted=$((total_deleted + del))
fi
fi
done < <(git show --numstat --format="" "$hash")
done
echo "$date"
echo "* from $first_time — $first_hash — $first_msg"
echo "* to $last_time — $last_hash — $last_msg"
echo "— Total hours: $duration (added: $total_added, deleted: $total_deleted)"
echo ""
# Pass total_seconds back through a temporary file
echo "$total_seconds" > "$output_file"
fi
done
# Read final total_seconds from file
if [ -f "$output_file" ]; then
total_seconds=$(cat "$output_file")
total_duration=$(calculate_duration $total_seconds)
echo "Total time: $total_duration"
echo ""
fi
# Cleanup
rm -f "$commits_file" "$days_file" "$output_file"
}
# Get all unique author emails, excluding bots and noreply emails
git log --format="%aE" | grep -vi "bot" | grep -vi "noreply" | sort -u | while read -r email; do
process_commits "$email"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment