Last active
May 11, 2026 07:28
-
-
Save ybart/370b512ff2eb2c4bd6a63a502cc143e5 to your computer and use it in GitHub Desktop.
gitlab-condensed-log: HTML git log with GitLab author avatars
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/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