Skip to content

Instantly share code, notes, and snippets.

@ybart
Last active May 11, 2026 07:28
Show Gist options
  • Select an option

  • Save ybart/370b512ff2eb2c4bd6a63a502cc143e5 to your computer and use it in GitHub Desktop.

Select an option

Save ybart/370b512ff2eb2c4bd6a63a502cc143e5 to your computer and use it in GitHub Desktop.
gitlab-condensed-log: HTML git log with GitLab author avatars
#!/bin/bash
# Script to generate HTML git log with author avatars using glab CLI
# Usage: ./git_log_with_avatars.sh <git-range>
# Example: ./git_log_with_avatars.sh main..HEAD
if [ -z "$1" ]; then
echo "Usage: $0 <git-range>"
echo "Example: $0 main..HEAD"
exit 1
fi
RANGE="$1"
# Format range for display (.. becomes →)
DISPLAY_RANGE=${RANGE//../ → }
# Create output filename
HTML_FILE="git-log-${RANGE//\//-}.html"
# Check if glab is installed
if ! command -v glab &> /dev/null; then
echo "Error: glab CLI is not installed. Please install it first."
exit 1
fi
# Start writing HTML file
{
cat << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$DISPLAY_RANGE</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 16px; }
.commit { display: grid; grid-template-columns: 20px 150px 180px 1fr 65px 50px; align-items: center; gap: 12px; padding: 2px 0; font-size: 13px; line-height: 1.4; }
.avatar { width: 20px; height: 20px; border-radius: 50%; }
.author { font-weight: 600; color: #0366d6; white-space: nowrap; }
.date { color: #6a737d; font-size: 12px; white-space: nowrap; }
.sha { font-family: "SF Mono", Monaco, "Cascadia Code", monospace; color: #6a737d; font-size: 10px; white-space: nowrap; }
.tags { font-size: 10px; color: #28a745; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.message { margin-left: 0px; color: #24292e; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
</style>
</head>
<body>
<h1>$DISPLAY_RANGE</h1>
EOF
# Generate commits
git log --format="%h%n%ae%n%an%n%as%n%ar%n%d%n%s%n---" "$RANGE" | while IFS= read -r line; do
# Initialize field on first iteration
if [ -z "$field" ]; then
field=0
fi
if [ "$line" = "---" ]; then
# End of commit block
if [ -n "$sha" ]; then
# Try to get avatar URL from the GitLab API by username (derived from email prefix)
# </dev/null prevents glab from reading the git log pipe's stdin
username="${email%%@*}"
avatar_url=$(glab api "/users?username=$username" 2>/dev/null </dev/null | jq -r '.[0].avatar_url // empty' 2>/dev/null || echo "")
# Fallback to Gravatar if glab fails
if [ -z "$avatar_url" ]; then
avatar_url="https://www.gravatar.com/avatar/$(echo -n "$email" | shasum -a 256 | cut -d' ' -f1)?s=32&d=identicon"
fi
# Extract tag names from decorated refs (format: "(HEAD -> main, tag: v1.0)")
tag_names=""
if [ -n "$tags" ] && echo "$tags" | grep -q "tag:"; then
tag_names=$(echo "$tags" | grep -o 'tag: [^,)]*' | sed 's/tag: //' | head -1)
fi
# Output commit HTML
echo '<div class="commit">'
echo " <img src=\"$avatar_url\" alt=\"$author\" class=\"avatar\" />"
echo " <span class=\"author\">$author</span>"
echo " <span class=\"date\">$date ($date_rel)</span>"
echo " <span class=\"message\">$message</span>"
echo " <span class=\"tags\">$tag_names</span>"
echo " <span class=\"sha\">${sha:0:8}</span>"
echo '</div>'
fi
# Reset variables and field counter
sha=""
email=""
author=""
date=""
date_rel=""
tags=""
message=""
field=0
else
# Parse commit data using field counter (handles empty lines correctly)
case $field in
0) sha="$line" ;;
1) email="$line" ;;
2) author="$line" ;;
3) date="$line" ;;
4) date_rel="$line" ;;
5) tags="$line" ;;
6) message="$line" ;;
esac
((field++))
fi
done
echo '</body>'
echo '</html>'
} > "$HTML_FILE"
echo "$HTML_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment