Skip to content

shortlog Git Command Guide

The git shortlog command summarizes Git commit history by author, providing contributor statistics and formatted output for release notes and project documentation. It groups commits by author and displays them in a concise, readable format.

Terminal window
git shortlog [<options>] [<revision-range>] [[--] <path>...]
git shortlog [--mailmap | --no-mailmap] [--stdin]
OptionDescription
-c, --committerGroup by committer rather than author
-n, --numberedSort output by number of commits per author
-s, --summaryShow only commit count and author name
-e, --emailShow author email addresses
--group=<type>Group commits by: author, committer, trailer
--format[=<format>]Custom output format
--no-mergesExclude merge commits
--mergesInclude only merge commits
OptionDescription
--since=<date>Show commits after date
--until=<date>Show commits before date
--author=<pattern>Limit to authors matching pattern
--committer=<pattern>Limit to committers matching pattern
--grep=<pattern>Limit to commits with message matching pattern
--all-matchAll grep patterns must match
--invert-grepShow commits not matching grep
-i, --regexp-ignore-caseCase insensitive matching
OptionDescription
--stdinRead commits from stdin
--mailmapUse mailmap to map author names/emails
--no-mailmapDon’t use mailmap
OptionDescription
-w[<width>[,<indent1>[,<indent2>]]]Linewrap width and indentation
--in-place-of=<string>Replace author name with string
--as=<string>Format author name as string
ParameterDescription
<revision-range>Range of commits to analyze
<path>Limit analysis to specific paths
Author Name (commit count):
commit subject line
another commit subject
...
Another Author (count):
their commit subjects
...
commit_count Author Name
commit_count Another Author
...
Author Name <email@domain.com> (commit count):
commit subject
...
# By author (default)
John Doe (5):
Fix login validation
Add user registration
...
Jane Smith (3):
Update documentation
Refactor API endpoints
...
# By committer (-c)
John Doe <john@company.com> (5):
Fix login validation
...
# Summary only (-s)
5 John Doe
3 Jane Smith
2 Bob Wilson
Terminal window
# Show all contributors and their commit counts
git shortlog
# Show summary only (commit counts)
git shortlog -s
# Show with email addresses
git shortlog -e
# Sort by number of commits (most active first)
git shortlog -n
# Show by committer instead of author
git shortlog -c
Terminal window
# Contributors in the last month
git shortlog --since="1 month ago"
# Contributors since specific date
git shortlog --since="2023-01-01"
# Contributors in date range
git shortlog --since="2023-01-01" --until="2023-12-31"
# Recent contributors (last 3 months)
git shortlog --since="3 months ago" -n
Terminal window
# Contributors to specific directory
git shortlog -- src/
# Contributors to specific file
git shortlog -- README.md
# Contributors to multiple paths
git shortlog -- src/ docs/ tests/
Terminal window
# Contributors matching pattern
git shortlog --author="John*"
# Contributors by email domain
git shortlog --author="*@company.com"
# Contributors with commits matching pattern
git shortlog --grep="bug\|fix"
# Case insensitive search
git shortlog -i --grep="BUG"
Terminal window
# Custom format for authors
git shortlog --format="%h %s"
# Wrap long lines
git shortlog -w80
# Custom indentation
git shortlog -w80,4,9
# Replace author names
git shortlog --in-place-of="John Doe" "Johnny D"
Terminal window
# Use mailmap for author name normalization
git shortlog --mailmap
# Don't use mailmap
git shortlog --no-mailmap
# Check mailmap configuration
cat .mailmap
Terminal window
# Exclude merge commits
git shortlog --no-merges
# Include only merge commits
git shortlog --merges
# Analyze merge commit authors
git shortlog --merges -e
Terminal window
# Analyze specific branch
git shortlog main
# Compare branches
git shortlog main..feature-branch
# Analyze tag range
git shortlog v1.0..v2.0
# Analyze specific commits
git shortlog abc123..def456
Terminal window
# Configure shortlog behavior
git config shortlog.mailmap true # Use mailmap by default
git config shortlog.summary true # Show summary by default
# Configure mailmap
# Add to .mailmap file:
# Proper Name <proper@email.com> <commit@email.com>
# Proper Name <proper@email.com> Bad Name <bad@email.com>
Terminal window
# Use mailmap for consistent author names
echo "John Doe <john@company.com> <john.doe@personal.com>" >> .mailmap
# Regular contributor analysis
git shortlog -n -s | head -10
# Generate contributor lists for releases
git shortlog --since="last release" -e
# Analyze contribution patterns
git shortlog --since="6 months ago" -n
Terminal window
# Check repository state
git status
# Verify commit range exists
git log --oneline "$range" | head -5
# Handle large repositories
git shortlog -s "$range" | head -20 # Limit output
#!/bin/bash
# Generate contributor list for releases
generate_contributors() {
local since_tag="$1"
local output_file="${2:-CONTRIBUTORS.md}"
echo "Generating contributor list since $since_tag"
cat > "$output_file" << EOF
# Contributors
Contributors to this release (since $since_tag):
EOF
# Add contributor statistics
git shortlog -n -s --since="$(git tag -l "$since_tag" --format="%(creatordate)")" >> "$output_file"
echo "" >> "$output_file"
echo "## Detailed Contributions" >> "$output_file"
echo "" >> "$output_file"
# Add detailed shortlog
git shortlog --since="$(git tag -l "$since_tag" --format="%(creatordate)")" >> "$output_file"
echo "Contributor list generated: $output_file"
}
generate_contributors "v1.0.0"
Terminal window
# Analyze team contribution patterns
team_analysis() {
echo "=== Team Contribution Analysis ==="
# Overall statistics
echo "Total commits by team:"
git shortlog -s -n | head -10
# Recent activity (last 30 days)
echo ""
echo "Active contributors (last 30 days):"
git shortlog --since="30 days ago" -s -n
# New contributors
echo ""
echo "New contributors (last 90 days):"
git log --since="90 days ago" --format="%an" | sort | uniq > recent_authors.txt
git log --since="180 days ago" --until="90 days ago" --format="%an" | sort | uniq > older_authors.txt
comm -23 recent_authors.txt older_authors.txt
# Contribution distribution
echo ""
echo "Contribution distribution:"
total_commits=$(git rev-list --count HEAD)
top_contributor_commits=$(git shortlog -s -n | head -1 | awk '{print $1}')
concentration=$(( top_contributor_commits * 100 / total_commits ))
echo "Total commits: $total_commits"
echo "Top contributor concentration: $concentration%"
if [ "$concentration" -gt 50 ]; then
echo "⚠ High concentration - consider team balance"
fi
# Cleanup
rm -f recent_authors.txt older_authors.txt
echo "Analysis complete"
}
team_analysis
Terminal window
# Generate changelog with contributor info
generate_changelog() {
local version="$1"
local previous_tag="$2"
cat > "CHANGELOG-$version.md" << EOF
# Changelog v$version
## Contributors
$(git shortlog -n --since="$(git tag -l "$previous_tag" --format="%(creatordate)")" | head -10)
## Changes
$(git log --oneline --since="$(git tag -l "$previous_tag" --format="%(creatordate)")")
## Statistics
- Total commits: $(git rev-list --count "$previous_tag..HEAD")
- Contributors: $(git shortlog -s --since="$(git tag -l "$previous_tag" --format="%(creatordate)")" | wc -l)
- Files changed: $(git diff --name-only "$previous_tag..HEAD" | wc -l)
EOF
echo "Changelog generated: CHANGELOG-$version.md"
}
generate_changelog "2.1.0" "v2.0.0"
Terminal window
# Fix inconsistent author names with mailmap
echo "Correct Name <correct@email.com> Wrong Name <wrong@email.com>" >> .mailmap
# Check current mailmap
cat .mailmap
# Test mailmap application
git shortlog --mailmap | head -10
Terminal window
# Speed up analysis on large repos
git shortlog -s --since="1 year ago" # Limit time range
# Use summary mode for quick counts
git shortlog -s -n | head -20
# Limit to specific paths
git shortlog --since="6 months ago" -- src/
Terminal window
# Handle encoding problems
git shortlog --encoding=UTF-8
# Configure repository encoding
git config i18n.logOutputEncoding UTF-8
Terminal window
# Fix invalid ranges
git tag -l # Check available tags
git branch -a # Check available branches
# Use valid ranges
git shortlog main..feature-branch
git shortlog v1.0..HEAD
Terminal window
# Understand author vs committer
git shortlog # Shows authors
git shortlog -c # Shows committers
# Check for differences
git log --format="Author: %an, Committer: %cn" | grep -v "Author:.*Committer:"
Terminal window
# Fix line wrapping
git shortlog -w120
# Handle long author names
git shortlog -w80,2,10
# Custom formatting
git shortlog --format="%h %s"
#!/bin/bash
# Open source contributor management
project_contributors() {
echo "=== Open Source Contributor Report ==="
# Overall contributor statistics
echo "All-time contributors:"
git shortlog -s -n | head -20
# Recent contributors (last 6 months)
echo ""
echo "Active contributors (last 6 months):"
git shortlog --since="6 months ago" -s -n
# New contributors (first commit in last 3 months)
echo ""
echo "New contributors (last 3 months):"
git log --since="3 months ago" --format="%an" | sort | uniq > recent_contributors.txt
git log --until="3 months ago" --format="%an" | sort | uniq > established_contributors.txt
comm -23 recent_contributors.txt established_contributors.txt | while read -r contributor; do
first_commit=$(git log --author="$contributor" --oneline | tail -1)
echo "$contributor: $first_commit"
done
# Contributor diversity
echo ""
echo "Contributor diversity:"
total_contributors=$(git shortlog -s | wc -l)
active_contributors=$(git shortlog --since="1 year ago" -s | wc -l)
diversity_percentage=$(( active_contributors * 100 / total_contributors ))
echo "Total contributors: $total_contributors"
echo "Active contributors (1yr): $active_contributors"
echo "Activity ratio: $diversity_percentage%"
# Top contributors by impact
echo ""
echo "Top contributors by lines changed:"
git log --shortstat --no-merges | grep -E "commit [a-f0-9]+| [0-9]+ files? changed" | paste - - | awk '
{
commit=$0
getline
insertions=0
deletions=0
if (match($0, /([0-9]+) insertions/, arr)) insertions=arr[1]
if (match($0, /([0-9]+) deletions/, arr)) deletions=arr[1]
author=$(git show --no-patch --format="%an" '"'"$(echo "$commit" | cut -d" " -f2)"'"')
total[author] += insertions + deletions
}
END {
for (author in total) {
print total[author], author
}
}' | sort -nr | head -10
# Cleanup
rm -f recent_contributors.txt established_contributors.txt
echo "Report complete"
}
project_contributors
Terminal window
# Corporate team analytics
corporate_analytics() {
echo "=== Corporate Development Analytics ==="
# Team contribution breakdown
echo "Team contributions by department:"
git shortlog -s -n --since="1 year ago" | while read -r count name; do
# Categorize by email domain or name pattern
if [[ "$name" == *"engineering"* ]] || [[ "$name" == *"dev"* ]]; then
echo "Engineering: $count commits - $name"
elif [[ "$name" == *"design"* ]] || [[ "$name" == *"ux"* ]]; then
echo "Design: $count commits - $name"
elif [[ "$name" == *"qa"* ]] || [[ "$name" == *"test"* ]]; then
echo "QA: $count commits - $name"
else
echo "Other: $count commits - $name"
fi
done | sort -k3 -nr
# Sprint velocity (commits per 2-week period)
echo ""
echo "Sprint velocity (commits per 2 weeks):"
for i in {0..12}; do
start_date=$(date -d "$i weeks ago" +%Y-%m-%d)
end_date=$(date -d "$((i-2)) weeks ago" +%Y-%m-%d)
commit_count=$(git rev-list --count --since="$end_date" --until="$start_date" HEAD)
echo "Sprint ending $start_date: $commit_count commits"
done
# Code review participation
echo ""
echo "Code review participation (merge commits):"
git shortlog --merges -s -n --since="6 months ago"
# Feature ownership
echo ""
echo "Feature ownership (by branch):"
git branch -r | grep -v HEAD | while read -r branch; do
branch_name=$(basename "$branch")
if [[ "$branch_name" == feature/* ]] || [[ "$branch_name" == bugfix/* ]]; then
commits=$(git rev-list --count "$branch")
author=$(git log --format="%an" "$branch" | head -1)
echo "$branch_name: $commits commits by $author"
fi
done | sort -k2 -nr | head -10
echo "Analytics complete"
}
corporate_analytics
Terminal window
# Academic research contribution tracking
research_tracking() {
echo "=== Research Contribution Tracking ==="
# Researcher productivity
echo "Researcher productivity (last 12 months):"
git shortlog --since="12 months ago" -s -n
# Publication-related commits
echo ""
echo "Publication-related work:"
git shortlog --grep="paper\|publication\|journal\|conference" -s -n --since="2 years ago"
# Collaboration analysis
echo ""
echo "Collaboration patterns:"
git log --since="1 year ago" --format="%an" | sort | uniq -c | sort -nr | while read -r count name; do
co_authors=$(git log --since="1 year ago" --author="$name" --format="%an" | grep -v "$name" | sort | uniq | wc -l)
echo "$name: $count commits, $co_authors co-authors"
done | head -10
# Research area focus
echo ""
echo "Research area focus:"
git log --since="2 years ago" --oneline | cut -d' ' -f2- | grep -o -i '\b\w*\b' | tr '[:upper:]' '[:lower:]' | grep -E "(algorithm|model|analysis|optimization|simulation|validation|experiment)" | sort | uniq -c | sort -nr | head -15
# Timeline of contributions
echo ""
echo "Contribution timeline (by month):"
git log --since="2 years ago" --format="%ai" | cut -d'-' -f1-2 | sort | uniq -c | while read -r count month; do
echo "$month: $count commits"
done
# Impact metrics
echo ""
echo "Impact metrics:"
total_commits=$(git rev-list --count HEAD)
total_contributors=$(git shortlog -s | wc -l)
avg_commits_per_contributor=$(( total_commits / total_contributors ))
echo "Total commits: $total_commits"
echo "Total contributors: $total_contributors"
echo "Average commits per contributor: $avg_commits_per_contributor"
# Most impactful contributors (by lines changed)
echo ""
echo "Most impactful contributors (lines changed):"
git log --shortstat --no-merges | grep -E "commit [a-f0-9]+| [0-9]+ files? changed" | paste - - | awk '
{
commit=$0
getline
insertions=0
deletions=0
if (match($0, /([0-9]+) insertions/, arr)) insertions=arr[1]
if (match($0, /([0-9]+) deletions/, arr)) deletions=arr[1]
author=$(git show --no-patch --format="%an" '"'"$(echo "$commit" | cut -d" " -f2)"'"')
total[author] += insertions + deletions
}
END {
for (author in total) {
print total[author], author
}
}' | sort -nr | head -10
echo "Research tracking complete"
}
research_tracking
Terminal window
# CI/CD contributor validation
ci_contributor_check() {
echo "=== CI/CD Contributor Validation ==="
# Validate current commit author
current_author=$(git show --no-patch --format="%an" HEAD)
current_email=$(git show --no-patch --format="%ae" HEAD)
echo "Current commit by: $current_author <$current_email>"
# Check if author is in contributor list
if git shortlog -e | grep -q "$current_author"; then
echo "✓ Author is recognized contributor"
else
echo "⚠ Author not in contributor list - possible external contribution"
fi
# Check commit frequency (detect potential bot commits)
recent_commits=$(git log --since="1 hour ago" --author="$current_author" --oneline | wc -l)
if [ "$recent_commits" -gt 10 ]; then
echo "⚠ High commit frequency detected - possible automated commits"
fi
# Validate email domain
allowed_domains=("company.com" "contributor.org")
email_domain=$(echo "$current_email" | cut -d'@' -f2)
domain_allowed=false
for domain in "${allowed_domains[@]}"; do
if [ "$email_domain" = "$domain" ]; then
domain_allowed=true
break
fi
done
if [ "$domain_allowed" = false ]; then
echo "⚠ Email domain not in allowed list: $email_domain"
else
echo "✓ Email domain validated"
fi
# Check for co-authors (pair programming)
co_authors=$(git show --format="%b" HEAD | grep -c "Co-authored-by:")
if [ "$co_authors" -gt 0 ]; then
echo "✓ Commit includes $co_authors co-author(s)"
fi
# Generate contributor attribution
cat > "contributor-attribution.txt" << EOF
Contributor Attribution for $(git rev-parse HEAD)
Commit Author: $current_author <$current_email>
Co-authors: $co_authors
Recent Contributions by Author:
$(git shortlog --author="$current_author" --since="6 months ago" | head -10)
Overall Project Contributors:
$(git shortlog -s -n | head -5)
EOF
echo "✓ Contributor validation complete"
echo "Attribution saved: contributor-attribution.txt"
}
ci_contributor_check
Terminal window
# Generate comprehensive contributor reports
contributor_reports() {
echo "=== Contributor Report Generation ==="
# Monthly activity report
echo "Generating monthly activity report..."
cat > "monthly-activity-$(date +%Y%m).md" << EOF
# Monthly Activity Report - $(date +%Y-%m)
## Active Contributors
$(git shortlog --since="$(date -d 'first day of this month' +%Y-%m-%d)" -s -n)
## New Contributors
$(comm -23 <(git log --since="$(date -d 'first day of this month' +%Y-%m-%d)" --format="%an" | sort | uniq) <(git log --until="$(date -d 'first day of this month' +%Y-%m-%d)" --format="%an" | sort | uniq))
## Top Contributors This Month
$(git shortlog --since="$(date -d 'first day of this month' +%Y-%m-%d)" -n | head -10)
## Commit Activity Timeline
$(git log --since="$(date -d 'first day of this month' +%Y-%m-%d)" --format="%ai" | cut -d' ' -f1 | sort | uniq -c | while read count date; do echo "$date: $count commits"; done)
EOF
# Annual summary
echo "Generating annual summary..."
cat > "annual-summary-$(date +%Y).md" << EOF
# Annual Summary - $(date +%Y)
## Year Overview
- Total commits: $(git rev-list --count --since="$(date +%Y)-01-01" HEAD)
- Total contributors: $(git shortlog --since="$(date +%Y)-01-01" -s | wc -l)
- Most active month: $(git log --since="$(date +%Y)-01-01" --format="%ai" | cut -d'-' -f2 | sort | uniq -c | sort -nr | head -1 | awk '{print $2}')
## Top Contributors
$(git shortlog --since="$(date +%Y)-01-01" -s -n | head -15)
## Monthly Breakdown
$(for month in {01..12}; do
commits=$(git rev-list --count --since="$(date +%Y)-$month-01" --until="$(date +%Y)-$month-$(cal $month $(date +%Y) | awk 'NF {DAYS = $NF}; END {print DAYS}') 23:59:59" HEAD 2>/dev/null || echo "0")
contributors=$(git shortlog --since="$(date +%Y)-$month-01" --until="$(date +%Y)-$month-$(cal $month $(date +%Y) | awk 'NF {DAYS = $NF}; END {print DAYS}') 23:59:59" -s | wc -l 2>/dev/null || echo "0")
echo "$(date -d "$(date +%Y)-$month-01" +%B): $commits commits by $contributors contributors"
done)
## Contribution Types
$(git log --since="$(date +%Y)-01-01" --oneline | cut -d' ' -f2- | sed 's/:.*//' | sort | uniq -c | sort -nr | head -10)
EOF
echo "Reports generated:"
echo " - monthly-activity-$(date +%Y%m).md"
echo " - annual-summary-$(date +%Y).md"
}
contributor_reports

What’s the difference between git shortlog and git log —author?

Section titled “What’s the difference between git shortlog and git log —author?”

git shortlog groups commits by author and shows summaries, while git log —author filters commits by author but shows individual commits. shortlog is better for contributor statistics.

How do I see contributors sorted by number of commits?

Section titled “How do I see contributors sorted by number of commits?”

Use git shortlog -n -s to sort by commit count in descending order.

Yes, use git shortlog -e to include email addresses in the output.

How do I limit shortlog to a specific time period?

Section titled “How do I limit shortlog to a specific time period?”

Use —since and —until options: git shortlog —since=“1 month ago”

What’s the difference between author and committer in shortlog?

Section titled “What’s the difference between author and committer in shortlog?”

By default, shortlog groups by author (who wrote the code). Use -c to group by committer (who created the commit object).

Can git shortlog work with specific file paths?

Section titled “Can git shortlog work with specific file paths?”

Yes, add path arguments: git shortlog —since=“1 year ago” — src/

git shortlog —mailmap uses .mailmap file to normalize author names and emails.

Can shortlog show only summary statistics?

Section titled “Can shortlog show only summary statistics?”

Yes, git shortlog -s shows only commit counts and author names, no commit subjects.

How do I see contributors for a specific branch?

Section titled “How do I see contributors for a specific branch?”

Specify the branch: git shortlog feature-branch or git shortlog main..feature-branch

—no-merges excludes merge commits from the analysis, showing only regular commits.

Yes, git shortlog v1.0..v2.0 analyzes commits between those tags.

Use —format option with format specifiers like %h for hash, %s for subject.

Yes, git shortlog —stdin reads commit information from standard input.

How do I see contributors by email domain?

Section titled “How do I see contributors by email domain?”

Use grep with shortlog output: git shortlog -e | grep “@company.com”

—group allows grouping by different criteria: author (default), committer, or trailer fields.

Can shortlog handle very large repositories?

Section titled “Can shortlog handle very large repositories?”

Yes, but use time limits (—since) and summary mode (-s) for better performance.

How do I export shortlog data for analysis?

Section titled “How do I export shortlog data for analysis?”

Pipe to files: git shortlog -s -n > contributor-stats.txt

Use git submodule foreach ‘git shortlog -s’ to analyze each submodule separately.

How do I see new contributors in a time period?

Section titled “How do I see new contributors in a time period?”

Compare author lists: comm -23 <(recent authors) <(older authors)

What’s the performance impact of shortlog?

Section titled “What’s the performance impact of shortlog?”

Generally fast, but analyzing large histories may take time. Use —since to limit scope.

Use mailmap to normalize names, then shortlog will properly group them.

Section titled “How do I see contribution trends over time?”

Use —since with different time periods and compare the output.

  1. Contributor Recognition: Acknowledging project contributors in releases and documentation
  2. Team Analytics: Analyzing contribution patterns and team productivity
  3. Release Management: Generating contributor lists for changelogs and release notes
  4. Project Governance: Understanding contribution distribution and team balance
  5. Open Source Management: Tracking community contributions and engagement
  6. Performance Reviews: Analyzing individual and team contribution metrics
  7. Academic Attribution: Tracking research contributions and collaborations
  8. Corporate Reporting: Generating contribution reports for management and stakeholders