Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/asispts/neo-git-graph/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Neo Git Graph supports workspaces containing multiple Git repositories. The extension automatically discovers repositories in your workspace and provides a dropdown to switch between them.

Repository Discovery

Automatic Scanning

When VS Code opens, the extension scans workspace folders for Git repositories:
// From repoManager.ts:187-201
private async searchWorkspaceForRepos() {
  let rootFolders = vscode.workspace.workspaceFolders,
    changes = false;
  if (typeof rootFolders !== "undefined") {
    for (let i = 0; i < rootFolders.length; i++) {
      if (await this.searchDirectoryForRepos(
          getPathFromUri(rootFolders[i].uri),
          this.maxDepthOfRepoSearch
        )
      ) changes = true;
    }
  }
  if (changes) this.sendRepos();
}

Search Depth

Configure how deep the extension searches for repositories:
{
  "neo-git-graph.maxDepthOfRepoSearch": 0
}
Only checks if workspace folders themselves are Git repositoriesExample:
workspace/
├── .git/          ← Found
├── project-a/
│   └── .git/      ← Not found
└── project-b/
    └── .git/      ← Not found
Increasing search depth can slow down VS Code startup for large workspaces with many directories.

Repository Switching

Using the Dropdown

1

Open Git Graph

Click the Git Graph status bar item or run the command
2

Locate Repository Dropdown

Find “Repo:” dropdown at the top-left of the graph view
3

Select Repository

Click the dropdown and choose from discovered repositories
4

View Updates

Graph immediately loads commits from the selected repository

Last Active Repository

The extension remembers your last viewed repository:
// From gitGraphView.ts:222-225
if (msg.repo !== this.currentRepo) {
  this.currentRepo = msg.repo;
  this.extensionState.setLastActiveRepo(msg.repo);
  this.repoFileWatcher.start(msg.repo);
}
When reopening Git Graph, the last active repository is automatically selected.

Repository State Persistence

Per-Repository Settings

Each repository maintains its own state:
// From types.ts:44-47
export interface GitRepoState {
  columnWidths: number[] | null;
}

export type GitRepoSet = { [repo: string]: GitRepoState };
Persisted State:
  • Column widths in the commit table
  • View preferences (future features)

Saving State

// From repoManager.ts:181-184
public setRepoState(repo: string, state: GitRepoState) {
  this.repos[repo] = state;
  this.extensionState.saveRepos(this.repos);
}
State is saved automatically when you adjust column widths or close the Git Graph view.

File System Watching

Automatic Repository Detection

The extension watches workspace folders for new repositories:
// From repoManager.ts:257-263
private startWatchingFolder(path: string) {
  let watcher = vscode.workspace.createFileSystemWatcher(path + "/**");
  watcher.onDidCreate((uri) => this.onWatcherCreate(uri));
  watcher.onDidChange((uri) => this.onWatcherChange(uri));
  watcher.onDidDelete((uri) => this.onWatcherDelete(uri));
  this.folderWatchers[path] = watcher;
}

Detection Events

When a new .git directory is detected:
// From repoManager.ts:268-276
private async onWatcherCreate(uri: vscode.Uri) {
  let path = getPathFromUri(uri);
  if (path.indexOf("/.git/") > -1) return;
  if (path.endsWith("/.git")) path = path.slice(0, -5);
  
  this.createEventPaths.push(path);
  setTimeout(() => this.processCreateEvents(), 1000);
}
Repository is automatically added to the dropdown
When a .git directory is removed:
private onWatcherDelete(uri: vscode.Uri) {
  let path = getPathFromUri(uri);
  if (this.removeReposWithinFolder(path)) this.sendRepos();
}
Repository is removed from the dropdown
When .git directory is modified:
  • Validates repository still exists
  • Updates repository list if needed

Workspace Folder Management

Adding Folders

When workspace folders are added:
// From repoManager.ts:39-49
this.folderChangeHandler = vscode.workspace.onDidChangeWorkspaceFolders(async (e) => {
  if (e.added.length > 0) {
    let path, changes = false;
    for (let i = 0; i < e.added.length; i++) {
      path = getPathFromUri(e.added[i].uri);
      if (await this.searchDirectoryForRepos(path, this.maxDepthOfRepoSearch)) 
        changes = true;
      this.startWatchingFolder(path);
    }
    if (changes) this.sendRepos();
  }
});
1

Folder Added to Workspace

User adds folder via File > Add Folder to Workspace
2

Repository Search

Extension searches for Git repositories in the new folder
3

File Watching Started

File system watcher monitors the folder for future changes
4

Dropdown Updated

Any discovered repositories appear in the dropdown

Removing Folders

When workspace folders are removed:
// From repoManager.ts:50-59
if (e.removed.length > 0) {
  let changes = false, path;
  for (let i = 0; i < e.removed.length; i++) {
    path = getPathFromUri(e.removed[i].uri);
    if (this.removeReposWithinFolder(path)) changes = true;
    this.stopWatchingFolder(path);
  }
  if (changes) this.sendRepos();
}
Repositories within removed folders are automatically cleaned up.

Repository Validation

Existence Checking

The extension periodically validates that repositories still exist:
// From repoManager.ts:163-180
public checkReposExist() {
  return new Promise<boolean>((resolve) => {
    let repoPaths = Object.keys(this.repos), changes = false;
    evalPromises(repoPaths, 3, (path) => 
      this.dataSource.isGitRepository(path)
    ).then((results) => {
      for (let i = 0; i < repoPaths.length; i++) {
        if (!results[i]) {
          this.removeRepo(repoPaths[i]);
          changes = true;
        }
      }
      if (changes) this.sendRepos();
      resolve(changes);
    });
  });
}
Validation Method:
git rev-parse --git-dir
Validation runs when:
  • Git Graph is opened
  • Workspace folders change
  • Manual refresh is triggered

Multi-Repo Workflows

Monorepo Support

monorepo/
├── .git/
├── frontend/
├── backend/
└── shared/
One repository in dropdown, shows all commits

Workspace Recommendations

  • Use default search depth of 0-1
  • All repositories easily accessible
  • Minimal performance impact
  • Consider organizing into separate workspaces
  • Or use VS Code multi-root workspaces
  • Limit search depth to avoid scanning overhead
  • Increase search depth as needed
  • Be aware of performance impact
  • Consider if nesting is necessary (e.g., git submodules)

Status Bar Integration

Repository Count

The status bar shows the number of discovered repositories:
// From repoManager.ts:157-162
private sendRepos() {
  let repos = this.getRepos();
  let numRepos = Object.keys(repos).length;
  this.statusBarItem.setNumRepos(numRepos);
  if (this.viewCallback !== null) this.viewCallback(repos, numRepos);
}

No Repositories

Status bar item hidden or shows warning

One Repository

Status bar shows Git Graph icon, no count

Multiple Repositories

Status bar shows count: “Git Graph (3)“

Repository Removal

When Repositories Are Removed

1

No Longer in Workspace

Repository path is not under any workspace folder
2

.git Directory Deleted

Repository’s .git directory was deleted or moved
3

Workspace Folder Removed

Folder containing repository was removed from workspace
4

Validation Failure

git rev-parse --git-dir returns an error

Cleanup Process

// From repoManager.ts:134-137
private removeRepo(repo: string) {
  delete this.repos[repo];
  this.extensionState.saveRepos(this.repos);
}
Removing a repository from the dropdown does not delete the repository from disk, only from the extension’s tracking list.

Performance Optimization

Repository searching uses promise-based concurrency:
// From repoManager.ts:231-237
resolve(
  (await evalPromises(dirs, 2, (dir) =>
    this.searchDirectoryForRepos(dir, maxDepth - 1)
  )).indexOf(true) > -1
);
Concurrency: 2 directories searched simultaneously

Debouncing File System Events

File system events are debounced to avoid excessive processing:
// From repoManager.ts:274-276
this.createEventPaths.push(path);
if (this.processCreateEventsTimeout !== null) 
  clearTimeout(this.processCreateEventsTimeout);
this.processCreateEventsTimeout = setTimeout(() => 
  this.processCreateEvents(), 1000
);
Debounce delay: 1000ms (1 second)

Troubleshooting

Repository Not Detected

Repository may be nested deeper than maxDepthOfRepoSearch settingIncrease the depth:
{
  "neo-git-graph.maxDepthOfRepoSearch": 2
}
Verify .git directory exists and is valid:
cd /path/to/repo
git status
Ensure repository is within a VS Code workspace folder
On Linux, you may hit inotify limits with many repositories:
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Repository Disappeared

1

Check if Deleted

Verify .git directory still exists on disk
2

Reload Window

Try reloading VS Code window (Cmd/Ctrl + R)
3

Re-add Folder

Remove and re-add workspace folder
4

Manual Validation

Close and reopen Git Graph to trigger validation
SettingTypeDefaultDescription
maxDepthOfRepoSearchnumber0How deep to search for repositories
showStatusBarItembooleantrueShow Git Graph in status bar

Best Practices

  • Group related repositories in workspace folders
  • Use descriptive folder names
  • Consider VS Code multi-root workspaces for complex setups
  • Limit to 10-20 repositories per workspace
  • Use multiple VS Code windows for more repositories
  • Consider workspace file organization