Overview
Neo Git Graph can display avatars for commit authors and committers by fetching images from GitHub, GitLab, or Gravatar based on the repository’s remote origin and user email addresses.
By enabling avatar fetching, you consent to commit author and committer email addresses being sent to GitHub, GitLab, or Gravatar depending on the repository’s remote origin.
Enabling Avatar Fetching
Configuration
Enable avatar support in VS Code settings:
{
"neo-git-graph.fetchAvatars" : false // Set to true to enable
}
Settings UI
settings.json
Open Settings (Cmd/Ctrl + ,)
Search for “neo-git-graph.fetchAvatars”
Check the box to enable
{
"neo-git-graph.fetchAvatars" : true
}
Clearing Avatar Cache
To clear cached avatars:
Open Command Palette (Cmd/Ctrl + Shift + P)
Run: (neo) Git Graph: Clear Avatar Cache
All cached avatars are deleted
Avatars will be re-fetched on next view
// From avatarManager.ts:78-81
public clearCache () {
this . avatars = {};
this . extensionState . clearAvatarCache ();
}
Avatar Sources
The extension automatically determines the avatar source based on your repository’s remote URL:
GitHub
GitHub Detection : Remote URL starts with https://github.com/Method : Fetches avatars via GitHub API using commit dataRate Limit : 60 requests/hour (unauthenticated)
// From avatarManager.ts:116-122
if ( remoteUrl . startsWith ( "https://github.com/" )) {
let remoteUrlComps = remoteUrl . split ( "/" );
remoteSource = {
type: "github" ,
owner: remoteUrlComps [ 3 ],
repo: remoteUrlComps [ 4 ]. replace ( / \. git $ / , "" )
};
}
API Endpoint :
https://api.github.com/repos/{owner}/{repo}/commits/{hash}
GitLab
GitLab Detection : Remote URL starts with https://gitlab.com/Method : Searches users by email via GitLab APIRate Limit : Respects GitLab rate limiting headers
// From avatarManager.ts:123-124
else if ( remoteUrl . startsWith ( "https://gitlab.com/" )) {
remoteSource = { type: "gitlab" };
}
API Endpoint :
https://gitlab.com/api/v4/users?search={email}
Gravatar
Gravatar Detection : Fallback for all other remotes or when GitHub/GitLab failMethod : MD5 hash of email addressFallback : Identicon generation if no avatar found
// From avatarManager.ts:267-282
private async fetchFromGravatar ( avatarRequest : AvatarRequestItem ) {
let hash = crypto . createHash ( "md5" ). update ( avatarRequest . email ). digest ( "hex" );
let img = await this . downloadAvatarImage (
avatarRequest . email ,
"https://secure.gravatar.com/avatar/" + hash + "?s=54&d=404"
),
identicon = false ;
if ( img === null ) {
img = await this . downloadAvatarImage (
avatarRequest . email ,
"https://secure.gravatar.com/avatar/" + hash + "?s=54&d=identicon"
);
identicon = true ;
}
if ( img !== null ) this . saveAvatar ( avatarRequest . email , img , identicon );
}
Avatar Fetching Process
Request Queue
Avatars are fetched asynchronously using a priority queue:
// From avatarManager.ts:30-38
this . queue = new AvatarRequestQueue (() => {
if ( this . interval !== null ) return ;
this . interval = setInterval (() => {
// Fetch avatars every 10 seconds
this . fetchAvatarsInterval ();
}, 10000 );
this . fetchAvatarsInterval ();
});
User Requests Avatar
When an email address appears in the graph, a fetch request is queued
Queue Processing
Requests are processed every 10 seconds to respect rate limits
Source Detection
Remote URL determines GitHub, GitLab, or Gravatar
Image Download
Avatar image is downloaded (54x54 pixels)
Cache Storage
Image is saved to disk and cached in memory
Display Update
Webview receives base64-encoded image for display
Retry Logic
The extension implements smart retry logic:
if ( res . headers [ "x-ratelimit-remaining" ] === "0" ) {
this . githubTimeout = parseInt ( res . headers [ "x-ratelimit-reset" ]) * 1000 ;
}
Requests are paused until rate limit resets
if ( res . statusCode === 422 &&
avatarRequest . commits . length > avatarRequest . attempts + 1 &&
avatarRequest . attempts < 4 ) {
this . queue . addItem ( avatarRequest , 0 , true );
return ;
}
Tries up to 5 different commits from the user’s history
if ( res . statusCode ! >= 500 ) {
this . githubTimeout = t + 600000 ; // Retry after 10 minutes
this . queue . addItem ( avatarRequest , this . githubTimeout , false );
}
. on ( "error" , () => {
this . githubTimeout = t + 300000 ; // Retry after 5 minutes
this . queue . addItem ( avatarRequest , this . githubTimeout , false );
});
Avatar Caching
Cache Duration
Avatars are cached with different expiration times:
// From avatarManager.ts:42-50
if ( this . avatars [ email ]. timestamp < t - 1209600000 || // 14 days
( this . avatars [ email ]. identicon &&
this . avatars [ email ]. timestamp < t - 345600000 )) { // 4 days for identicons
this . queue . add ( email , repo , commits , false );
}
Standard Avatars Cached for 14 days before refresh
Identicons (Fallback) Cached for 4 days - shorter to retry finding real avatars
Storage Location
Avatars are stored in VS Code’s extension storage:
// From avatarManager.ts:305-312
fs . writeFile (
this . avatarStorageFolder + "/" + hash + "." + format ,
Buffer . concat ( imageBufferArray ),
( err ) => {
resolve ( err ? null : hash + "." + format );
}
);
File naming : {MD5_hash_of_email}.{format} (e.g., abc123def456.png)
Cache Management
In-Memory Cache
Persistent Storage
interface Avatar {
image : string ; // Filename
timestamp : number ; // Last fetch time
identicon : boolean ; // Is fallback icon?
}
private avatars : { [ email : string ]: Avatar };
Cache is saved to ExtensionState and persists across VS Code sessions this . extensionState . saveAvatar ( email , this . avatars [ email ]);
Avatars are sent to the webview as base64-encoded data URIs:
// From avatarManager.ts:345-354
this . view . sendMessage ({
command: "fetchAvatar" ,
email: email ,
image:
"data:image/" +
this . avatars [ email ]. image ! . split ( "." )[ 1 ] +
";base64," +
data . toString ( "base64" )
});
Format : data:image/{png|jpeg|gif};base64,{base64_data}
Privacy Considerations
Email Transmission : When avatar fetching is enabled, email addresses from commits are sent to:
GitHub API (for github.com repositories)
GitLab API (for gitlab.com repositories)
Gravatar service (for all other repositories or as fallback)
This is required to fetch avatars but transmits potentially private data.
Best Practices
Consider disabling avatar fetching for repositories with sensitive commit information
Avatar fetching requires internet access and may be blocked by firewalls
GitHub API has strict rate limits for unauthenticated requests. Heavy use may cause delays.
Troubleshooting
Avatars Not Appearing
Check Setting
Verify neo-git-graph.fetchAvatars is set to true
Check Network
Ensure internet connectivity and firewall allows GitHub/GitLab/Gravatar
Check Rate Limits
GitHub: 60 requests/hour may be exhausted - wait for reset
Clear Cache
Run “Clear Avatar Cache” command and refresh graph
Check Console
Open Developer Tools (Help > Toggle Developer Tools) for errors
Identicons Only
If you only see identicons (geometric patterns):
Email address may not be registered with Gravatar
GitHub/GitLab API couldn’t find the user
Commit may not exist on remote (for GitHub)
To get real avatars, ensure:
Email in commits matches GitHub/GitLab account email
Commits are pushed to remote
For Gravatar: Register email at gravatar.com
Avatar fetching is highly optimized:
Asynchronous background processing
Queue-based rate limiting
Persistent caching reduces network requests
No impact on graph rendering speed
Network Usage
Initial fetch : ~10-50 KB per avatar
Refresh : Only after cache expiration (4-14 days)
Queue interval : 10 seconds between requests
Clear Avatar Cache Command : neo-git-graph.clearAvatarCacheRemoves all cached avatar images and metadata, forcing fresh downloads on next view