Repository navigation
How the Log Works
The Log is the commit history of the active repository, drawn as a branch graph with the details of the selected commit below it. This page explains how it loads, draws and acts on history. For the user side, see History and Log.
People want to scroll the history, see where branches split and merged, read one commit, and act on it. Histories can be huge, so the Log loads history in pages, lays out the graph page by page, and only renders the rows you can see.
LogView.svelte fills the main area. The Log button in the activity bar, the empty main area, Shift+Cmd+L, View > Log and the X at the right end of the Log toolbar all call changesSelection.toggleLog(), which remembers the view you came from, so a second click returns you there. Git > Show Git Log (Cmd+9) and a repository row's ... > Show Log call showLog(repoRoot?) in views/gitActions.ts, which makes the repository active first and only opens the Log, never hides it.
Double-clicking a commit opens it in its own editor tab instead; see How commit tabs work.
Loading a page goes through the usual bridge:
sequenceDiagram
participant LV as LogView
participant API as api.ts
participant CMD as history.rs
participant LOG as git/log.rs
LV->>API: getLog(repoPath, offset, 300, allRefs)
API->>CMD: invoke get_log
CMD->>LOG: page(repo, offset, limit capped at 1000, allRefs)
LOG->>LOG: revwalk, topological and time order
LOG-->>LV: CommitSummary list with ref labels
LV->>LV: GraphBuilder.push(page), append rows
log::page walks from HEAD with git2. When allRefs is set (the logAllRefs setting, on by default) it also pushes every local and remote branch, like git log --branches --remotes (tags and stashes are not walked). Each CommitSummary carries its parents and its ref labels.
GraphBuilder in src/lib/log/graph.ts gives each commit a lane. It keeps its lane state between calls, so page after page gives the same picture as the whole history at once. Rows store edges as flat number quadruples, and the UI library's CommitGraph draws them, with lane colors from ui/design-tokens/palette.json.
flowchart TD
A["Scroll or open the Log"] --> B{"Near the end of loaded rows?"}
B -->|"no"| C["Render only the visible rows plus overscan"]
B -->|"yes, and more exist"| D["loadMore: getLog at offset = loaded count"]
D --> E["GraphBuilder continues the lanes"]
E --> F["Bump version so derived lists update"]
F --> C
A few details keep it fast:
-
Plain arrays, not runes.
commits,rowsandindexByIdlive outside$state, so commits are never wrapped in proxies; aversioncounter tells derived values they changed. - Virtual list. Rows are a fixed 26 px; only the visible range plus 12 rows is rendered, and within 80 rows of the end the next 300 commits load.
-
Reloads keep your place. When
repoStore.historyVersionchanges, the Log refetches as many commits as it had (up to 3000) and keeps the selection. -
Stale answers are dropped through a
generationnumber captured by every load.
The filter searches loaded commits only (hash prefix, summary, author), and the graph collapses to one lane while filtering. Automatic paging pauses while filtering; a Load more button searches deeper. CommitDetails.svelte calls getCommitDetails (files per parent; see How merge commits work) and getCommitFileDiff.
Blame and Back/Forward reach repoStore.showCommit(repoRoot, commitId, filePath, line, lineText). It switches the active repository if needed and sets repoStore.logFocus with a fresh token. An effect in LogView runs focusCommit, which loads pages until the commit appears (at most 20), centers it, and passes the line to CommitDetails, where revealLine uses findLine (src/lib/log/lineMatch.ts). If the commit is not found, a toast says so, and suggests all branches when logAllRefs is off.
The context menu's items write through repoStore.run or runOp with the git CLI (cherry-pick, revert --no-edit, reset, switch --detach); cherry-pick and revert return an OpOutcome, so conflicts are a normal result. They and Interactively Rebase from Here are disabled on merge commits; the rebase also needs a branch and hands over to startInteractiveRebase (How Interactive Rebase Works).
Reset offers Soft, Mixed, Hard and Keep; Hard asks twice. run_reset in commands/history.rs maps them to --soft, --mixed, --hard and --keep, refuses a revision that starts with -, and ends the arguments with -- so a revision named like a file is never read as a path. The Git menu's Reset HEAD dialog uses the same command.
An effect publishes the selected commit to logSelection.current (src/lib/log/logSelection.svelte.ts), and clears it when the Log closes. The Git menu reads it for Create Patch from Commit and Interactive Rebase.
| File | What it does |
|---|---|
src/lib/views/LogView.svelte |
Toolbar, filter, selection, blame focus, details split |
src/lib/log/logHistory.svelte.ts |
LogHistory: pages, reloads, find
|
src/lib/log/LogTable.svelte |
Rows, on the library's DataTable
|
src/lib/log/logFilter.ts, commitMenu.ts
|
Filter and counts; right-click menu |
src/lib/log/graph.ts |
GraphBuilder: incremental lane layout |
ui/web/src/lib/components/CommitGraph.svelte, logic/graphModel.ts
|
Draws one row of the graph (UI library) |
src/lib/log/CommitDetails.svelte, commitLoader.svelte.ts
|
Commit message, changed files and per-file diff, revealLine
|
src/lib/log/lineMatch.ts |
findLine: which diff line to scroll to |
src/lib/log/format.ts |
Dates and ref label sorting |
src/lib/log/logSelection.svelte.ts |
The selected commit, for Git menu items |
src/lib/views/changes/selection.svelte.ts |
toggleLog() and shownView
|
src/lib/stores/repo.svelte.ts |
showCommit, logFocus, historyVersion
|
src-tauri/src/commands/history.rs |
get_log, get_commit_details, get_commit_file_diff, cherry_pick, revert_commit, reset_to (run_reset), checkout_commit
|
src-tauri/src/git/log.rs |
git2 revwalk, ref labels, commit details |
Page the history and lay out the graph incrementally. Loading the whole history first would be slow and heavy on big repositories. The lane state carried between pages gives the same graph without redoing earlier pages. The backend is simpler: each page walks again from the tips and skips offset commits, so deep pages cost more.
Keep commit data outside Svelte runes. Proxies on tens of thousands of objects cost memory and time; one version counter is cheap, but every change must bump it (LogHistory does).
Filter only what is loaded. Filtering loaded commits is instant, and the label says "of N loaded commits" so nobody is misled.
The Log could not be hidden.
- The issue: the Log was a permanent tab in the header, next to a Diff tab, and could not be hidden.
- Why it happened: the header treated the Log as one of several permanent tabs.
-
The fix and why we chose it: at the user's request the Log became an activity bar toggle.
toggleLog()remembers the previous view, so hiding the Log returns you where you were.
A type check failure in focusCommit.
-
The issue:
bun run checkfailed while diff steps were added to Back/Forward. -
Why it happened: a new
tokenparameter clashed with the local load generationtoken. - The fix and why we chose it: renaming the parameter kept the generation check untouched.
-
src/lib/log/graph.test.ts: linear history, merges, lane reuse, octopus merges, several roots, duplicate parents, paging equals all-at-once, rows stay within their width. -
src-tauri/src/git/tests.rs:log_page_orders_newest_first_and_pages,log_page_in_unborn_repo_is_empty,log_page_labels_refs_and_includes_all_refs,log_details_lists_files_with_rename,diff_commit_file_sides. -
src-tauri/src/commands/tests.rs:cherry_pick_conflict_then_continue,revert_conflict_then_continue,reset_and_checkout_commit. -
src-tauri/src/commands/history.rs:reset_keep_moves_the_branch_and_keeps_local_changes, which also checks that an option-like revision and an unknown mode are refused. -
src/lib/log/logFilter.test.ts: matching, counts, the +N chip. -
src/lib/log/lineMatch.test.ts:findLinekeeps or moves the line, ties, no match, CRLF.
Graph changes need a case in graph.test.ts; history command changes need a Rust test on a real repository from test_support.rs.
- Update this page when
LogView.svelte,logHistory.svelte.ts,graph.ts,git/log.rsorcommands/history.rschange behavior, page size or menu items. - Update History and Log for any visible change.
- Retake
log-graph.png,commit-details.pngandlog-context-menu.pngwhen the Log looks different. - See also How Blame Works, How Navigation Works and Frontend.
These pages are generated from docs/wiki. To correct something, open a pull request against the source file; edits made here are overwritten.
Using Nibtree
- Getting Started
- Welcome Screen
- Workspaces
- Files Panel
- File Operations
- File Icons
- Rounded Panels
- Editor and Tabs
- Pin Reorder and Wrap Tabs
- Single Tab Title
- Split Editor
- New File and Unsaved Changes
- Unload Hidden Tabs
- Editing Code
- Code Appearance
- Markdown Editor
- Image and PDF Preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and Replace
- Changes and Commits
- Sign In Prompts
- Commit Box Layout
- Repository Actions
- Commit Options
- Ignoring Files
- Diffs
- Inline Diffs
- Staging View
- Revert a Change
- Resolving Conflicts
- Merge Tool
- Blame
- History and Log
- Merge Commits
- Branches and Tags
- Branches Popup
- Remotes
- Stashes
- Shelf
- Git Menu
- Git Dialogs
- Interactive Rebase
- Worktrees
- AI Agents
- AI Tasks
- AI Usage
- Keep Computer Awake
- Submodules
- Git LFS
- GitHub
- Git Console
- Terminal
- Terminal Features
- Scripts
- Navigation
- Menus
- Settings
- Settings Search
- Color Themes
- Settings Terminal and Automation
- Settings Files
- Updates
- Status Bar and Help
- Notifications
- Memory Use
- Clear Cache
- MCP and CLI
- Git Mergetool
- Keyboard Shortcuts
- Keyboard Shortcuts Editor
- Troubleshooting
- Troubleshooting Git
Developers
- Developer Guide
- Architecture
- Project Layout
- Backend
- How Folder Watching Works
- Folder Watching Bugs We Fixed
- How Workspace Files Work
- How the Preview Scheme Works
- Backend Services
- How Terminal Features Work
- Terminal Bugs We Fixed
- Frontend
- How the Rich Markdown Editor Works
- Rich Markdown Bugs We Fixed
- Git Menu Links
- Menu Keys and Routing
- Frontend Modules
- Blame Bugs We Fixed
- Project Color And Title Bar
- One Diff View
- Diff Bugs We Fixed
- Merge Tool Layouts
- Merge Tool Bugs We Fixed
- Color Theme Bugs We Fixed
- How the Connected Diff Works
- Rounded Panels Bugs We Fixed
- Update Bugs We Fixed
- Status Bar Bugs We Fixed
- MCP and CLI Bugs We Fixed
- Repository Actions Bugs We Fixed
- How the Changes Tab Works
- CodeMirror Patterns
- How the Cursor Works
- How Editor Features Work
- How the Path Bar Works
- Commands and Events
- Settings Reference
- Commands Workspace and Changes
- Commands Branches and Remotes
- Commands History and Extras
- Commands App and Tools
- Testing
- Test Suites
- Debugging
- Debugging with MCP
- Measuring Setting Memory
- How Terminal Memory Is Measured
- How Markdown Diagrams Work
- Releases and CI
- Publishing the Wiki
- Versioning and Changelog
- Browser Version Packages
- Browser Release Checks
- Docker Image
- Platforms and Signing
- Windows Support
- Windows Bugs We Fixed
- Windows MCP and CLI
- Docs and Screenshots
- UI Library
- UI Library MCP
- UI Library Bugs
- UI Library Migration
- Contributing
How features work
- Welcome screen
- Workspaces and folders
- Files panel
- File operations
- File icons
- Editor and tabs
- Pin, reorder and wrap tabs
- Single tab title
- Split editor
- New File and unsaved changes
- Unload hidden tabs
- Editing code
- Code appearance
- Markdown editor
- Image and PDF preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and replace
- Changes and commits
- Sign-in prompts
- Commit box layout
- Repository actions
- Commit options
- Ignoring files
- Diffs
- Inline diffs
- Staging view
- Revert a change
- Resolving conflicts
- Merge tool
- Blame
- History and log
- Merge commits
- Commit tabs
- Branches and tags
- Branches popup
- Remotes
- Stashes
- Shelf
- Git menu
- Git dialogs
- Interactive rebase
- Worktrees
- AI agents
- AI usage
- Keep computer awake
- AI tasks
- Submodules
- Git LFS
- GitHub account
- Git Console
- Back and Forward
- Integrated terminal
- Scripts tool window
- Menu bar
- Settings
- Search in Settings
- Color themes
- Rounded panels
- Updates and release channels
- Status bar and help links
- Notifications
- Memory readout and memory log
- Clear Cache
- MCP server and command line tool
- git mergetool mode