A blazingly fast terminal UI for viewing git file history and diffs
Geschichte (German for "history") is a fast, keyboard-driven terminal UI for exploring git file history. Navigate through commits, view diffs, and understand how your files evolved over time—all without leaving your terminal.
Unlike full-featured git clients, Geschichte focuses specifically on single-file history exploration. It's designed for developers who want to quickly understand how a particular file changed over time, not for managing branches, commits, or other git operations. Think of it as a specialized tool that does one thing exceptionally well: showing you the story of your file.
Geschichte is not meant to replace your favorite git tools. Instead, it complements them by providing a fast, focused way to explore file history directly in your terminal. Geschichte is a read-only client for git history, allowing you to view and understand changes without the overhead of a full git client.
I wrote this because I was badly missing this feature in 'Zed', my primary IDE. Geschichte can be opened in a terminal window in your favorite IDE.
Default view with file picker and commit history

- Interactive file picker - Fuzzy search and select any tracked file with popup interface
- File history visualization with commit dates, hashes, authors, and subjects
- Working directory support - See uncommitted changes as the top entry
- Interactive navigation with vim-style keybindings and focus-aware panels
- Colorized diffs with visual highlighting for additions, deletions, and context
- In-diff search - Find specific code patterns with context-aware highlighting
- Commit-to-commit diff - Select any two commits to see changes between them
- Rename tracking - Follow files across renames and moves (with
--follow) - Performance optimized with LRU caching for instant diff switching
- Split-pane interface with resizable panels and help overlay
- Side-by-side diff view - Three-panel layout with old/new file comparison
- Detailed commit popups - View comprehensive commit metadata with scrollable interface
- Copy functionality - Copy commit SHA, message, author, date, GitHub URLs, or file paths to clipboard
- Enhanced commit metadata - Author/committer details, timestamps, refs, and PR information
- Pull request detection - Automatic detection and display of GitHub PR information from commit messages
- Branch and tag refs - See which branches and tags contain each commit
- Commit statistics - View files changed, insertions, and deletions for each commit
- Seamless file switching - Switch between files without losing context using 'f' key
- External editor integration - Press 'e' to open current file in your preferred editor at the current line
- Mac-friendly navigation - Multiple scroll options (PageUp/Down, Ctrl+D/U, Ctrl+F/B)
- Mouse support - Scrolling support with mouse
- Focus-aware controls - Arrow keys work differently based on active panel
- Comprehensive keybindings - Vim, emacs, and traditional navigation styles
- Merge commit handling - Proper parent resolution for complex histories
- Configurable context - Adjust diff context lines via CLI arguments
- Rust 1.80+ - Update with
rustup updateif you encounter edition2024 errors
git clone https://github.com/yourusername/geschichte.git
cd geschichte
cargo build --release
cargo install --path .Using the Makefile (Recommended for Development):
make help # Show all available commands
make dev # Format + lint + test + build
make install # Install to ~/.cargo/bin
make test # Run all tests
make lint # Run clippy + format checkcargo install geschichtebrew install geschichteGeschichte can be integrated into the Zed IDE for a seamless development experience. You can open Geschichte in a terminal window within Zed to quickly access file history. To set up Geschichte in Zed, follow these steps:
- Open Zed and go to the settings.
- Create a Task in ~/config/zed/tasks.json with the following configuration:
{
"label": "Geschichte - Show File history",
"command": "geschichte \"$ZED_RELATIVE_FILE\"",
}- Use custome key bindings to run the task, or run it from the command palette.
[
{
"context": "Workspace",
"bindings": {
"alt-g": [
"task::Spawn",
{ "task_name": "Geschichte - Show file history", "reveal_target": "center" }
]
}
}
]# Open file picker to browse and select any tracked file
geschichte
# View history for a specific file
geschichte src/main.rs
geschichte README.md
geschichte path/to/any/file.txtgeschichte [OPTIONS] [FILE]
Arguments:
[FILE] Path to the file to view history for (optional - opens file picker if not provided)
Options:
-C, --repo <DIR> Repository root directory (auto-discovered if not specified)
-L, --lines <CONTEXT_LINES> Number of context lines in diffs [default: 3]
--full-file Show full file content in diffs instead of just context around changes
-s, --side-by-side Enable side-by-side diff view (three-panel layout)
--layout <MODE> Layout mode: unified, side-by-side, or auto [default: unified]
--first-parent Show only first-parent commits (linearize merges)
--no-follow Disable rename tracking
--debug Enable debug logging
-h, --help Print help
-V, --version Print version# Open file picker to browse all tracked files
geschichte
# Side-by-side diff view (three-panel layout)
geschichte --side-by-side src/main.rs
geschichte -s README.md
# Auto layout mode (switches based on terminal width)
geschichte --layout auto src/app.rs
# More context in diffs
geschichte -L 10 src/main.rs
# Show full file content in diffs (useful for small files)
geschichte --full-file src/config.rs
# Disable rename tracking for performance
geschichte --no-follow large-file.txt
# Linear history only (ignore merge commits)
geschichte --first-parent main.rs
# Combine options
geschichte -s -L 5 --first-parent src/main.rs
geschichte --full-file --side-by-side README.md| Key | Action |
|---|---|
Tab |
Switch between commit list and diff panels |
↑↓ / j/k |
Navigate commits OR scroll diff (focus-aware) |
h/l |
Resize split panes |
| Key | Action | Style |
|---|---|---|
PageUp/PageDown |
Scroll diff | Traditional |
Ctrl+U/Ctrl+D |
Scroll diff | Vim-style |
Ctrl+B/Ctrl+F |
Scroll diff | Emacs-style |
| Key | Action |
|---|---|
f |
Open file picker to switch to another file |
d |
Mark/diff between commits - select two commits to compare |
| Key | Action |
|---|---|
/ |
Start search in diff content |
n |
Navigate to next change (or next search result when searching) |
N |
Navigate to previous change (or previous search result when searching) |
e |
Open current file in external editor at current line |
| Key | Action |
|---|---|
i / Enter |
Show detailed commit information popup |
y |
Start copy mode - then press target key |
yy |
Copy full commit SHA (vim-style) |
Y |
Copy short commit SHA |
c |
Copy full commit SHA (in popup) |
| Key | Action |
|---|---|
s |
Copy full SHA |
h |
Copy short SHA |
m |
Copy commit message (subject + body) |
a |
Copy author name and email |
d |
Copy commit date |
u |
Copy GitHub/GitLab URL |
p |
Copy file relative path |
y |
Copy full SHA (same as s) |
| Key | Action |
|---|---|
↑↓ / Ctrl+P/N |
Navigate file list |
Enter |
Select file and view history |
Ctrl+Q |
Return to previous file (or quit if no previous file) |
| Type characters | Fuzzy search files |
Ctrl+U |
Clear search |
| Key | Action |
|---|---|
| Type characters | Search for text in diff content |
Enter |
Finish typing and navigate to first result |
q / Esc |
Cancel search and return to normal mode |
| Key | Action |
|---|---|
? |
Show/hide help overlay |
q |
Quit (context-aware) |
Geschichte offers a powerful three-panel layout that shows old and new file versions side-by-side, making it easier to compare changes visually.
- Unified (default): Traditional two-panel layout with commits on left, unified diff on right
- Side-by-Side: Three-panel layout with old/new files on top, commits on bottom
- Auto: Automatically switches based on terminal width (≥120 characters for side-by-side)
┌─ Old File (deletions) ────────┐┌─ New File (additions) ─────────┐
│ 1 fn calculate() { ││ 1 fn calculate(x: i32) { │
│ 2 - let result = 10; ││ 2 + let result = x * 2; │
│ 3 println!("{}", result);││ 3 println!("{}", result);│
│ ││ 4 + // Return the value │
│ ││ 5 + result │
├────────────────────────────────┴─────────────────────────────────┤
│ > Working Dir Modified │
│ 2025-08-17 abc123 Add parameter to calculate function │
│ 2025-08-16 def456 Initial implementation │
└───────────────────────────────────────────────────────────────────┘
- Syntax highlighting: Full language-aware highlighting in both panels
- Line numbers: Accurate line numbers for old and new versions
- Background colors: Deletions highlighted in red (left), additions in green (right)
- Synchronized scrolling: Both panels scroll together for easy comparison
- Dynamic titles: Panel headers show commit hashes being compared
- Full feature parity: All unified mode features work in side-by-side mode
- Unified mode: Better for reviewing overall changes, seeing context, and narrow terminals
- Side-by-side mode: Ideal for comparing implementations, refactoring reviews, and wide screens
- Auto mode: Let Geschichte choose the best layout based on your terminal size
Geschichte allows you to compare any two commits to see exactly what changed between them. This is perfect for understanding the evolution of your code across multiple commits.
- Mark First Commit: Navigate to any commit and press
d- you'll see a green►marker - Select Second Commit: Navigate to another commit and press
dagain - View Diff: The diff panel automatically updates to show changes between the two commits
- Clear Selection: Press
qto clear the selection and return to normal mode
- Green
►arrow: Shows which commit is marked for comparison - Header format:
Diff (older..newer)shows the range being compared - Selection mode:
Diff (abc123) [Selecting...]when first commit is marked - Chronological order: Always shows older→newer regardless of selection order
# 1. Navigate to an older commit (bottom of history)
# 2. Press 'd' → see green arrow marker
# 3. Navigate to newer commit (top of history)
# 4. Press 'd' → see diff between the commits
# 5. Green lines show code added in newer commit
# 6. Red lines show code removed from older commitThe range diff works across any two commits - compare your working directory with any historical commit, or see what changed between two releases!
Geschichte seamlessly integrates with your favorite text editor, allowing you to quickly jump from viewing history to editing the actual file.
- Navigate to any line in the diff view using arrow keys or vim-style navigation
- Press
eto open the current file in your external editor - Editor opens at the current line - no need to scroll or search for the right location
- Make your edits in the familiar environment of your preferred editor
- Exit the editor - Geschichte automatically refreshes and shows updated content
Geschichte respects your $EDITOR environment variable:
# Set your preferred editor (examples)
export EDITOR="vim" # Use vim
export EDITOR="nvim" # Use Neovim
export EDITOR="code -w" # Use VS Code (wait for window to close)
export EDITOR="cursor -w" # Use Cursor (wait for window to close)
export EDITOR="zed -w" # Use Zed (wait for window to close)
export EDITOR="subl -w" # Use Sublime Text (wait for window to close)
export EDITOR="nano" # Use nanoIf no $EDITOR is set, Geschichte defaults to vim.
Terminal Editors: vim, nvim, nano, emacs - work seamlessly with line number positioning
GUI Editors: VS Code, Cursor, Zed, Sublime Text, Atom - use the -w flag to make Geschichte wait for the editor to close
Geschichte automatically passes the current line number to editors that support it:
- Vim/Neovim:
vim +42 file.rs(opens at line 42) - VS Code:
code -g file.rs:42(opens at line 42) - Nano:
nano +42 file.rs(opens at line 42)
# 1. View history of a file
geschichte src/main.rs
# 2. Navigate to interesting commit and line in diff
# 3. Press 'e' to edit
# 4. Editor opens: vim +127 src/main.rs
# 5. Make changes and save
# 6. Exit editor - back to Geschichte with updated viewGeschichte automatically handles terminal state restoration after returning from external editors, ensuring a clean interface without artifacts or display issues.
Geschichte provides comprehensive commit metadata through an interactive popup that shows everything you need to know about a commit.
- From commit list: Press
iorEnteron any commit - Navigation: Use
↑↓orj/kto scroll through the popup content - Copy shortcuts: Press
cto copy the commit SHA directly from the popup - Close: Press
qto close the popup
Basic Information:
- Full commit SHA (clickable/copyable)
- Author name and email
- Commit date and time
- Subject line
Extended Metadata (when available):
- Committer information (if different from author)
- Commit timestamp (if different from author date)
- Branch and tag references
- Pull request information (auto-detected from commit messages)
- Commit statistics (files changed, insertions, deletions)
Full Message Content:
- Complete commit message body
- Scrollable interface for long messages
- Preserves original formatting
The commit popup integrates seamlessly with the copy system - you can copy any commit information directly from the detailed view without leaving the popup.
Geschichte provides powerful search functionality to help you find specific code patterns, functions, or text within diff content across all your commits.
- Start Search: Press
/while viewing a diff to enter search mode - Type Query: Start typing your search term (case-insensitive by default)
- Navigate Results: Press
Enterto finish typing, then usen/Nto move between matches - Exit Search: Press
qorEscto clear search and return to normal navigation
Regex-Powered Search:
- Full regex support: Use patterns like
searc.to match "search",fn.*testto find functions,[0-9]+for numbers - Case-insensitive by default: Searches ignore case automatically
- Graceful error handling: Invalid regex patterns simply show no results
Smart Scope:
- Searches only code content: Excludes file headers, hunk headers, and metadata
- Includes all relevant lines: Addition lines (
+), deletion lines (-), and context lines - Works across commits: Search persists when navigating between commits until cleared
Visual Highlighting:
- Context-aware colors: Highlights adapt to diff line backgrounds for maximum visibility
- Current match emphasis: Active search result uses bright highlighting
- Multiple match support: All matches on a line are highlighted with distinct colors
Navigation Integration:
- Smart
n/Nkeys: Automatically switch between search navigation and change navigation - Status bar feedback: Shows match count, current position, and search query
- Cross-layout support: Works in both unified and side-by-side diff views
When searching with regex patterns:
# Literal search: "function"
# Status bar: "3/7 matches for 'function' | n/N: next/prev | q/Esc: exit search"
# Regex search: "fn.*test"
# Status bar: "2/4 matches for 'fn.*test' | n/N: next/prev | q/Esc: exit search"
@@ -10,6 +10,8 @@ impl MyStruct {
impl MyStruct {
- fn old_function() { # ← highlighted if matches pattern
+ fn new_function(x: i32) { # ← highlighted if matches pattern
// implementation
}
}- Full regex support: All regex features work - wildcards (
.), quantifiers (*,+,?), character classes ([a-z]), word boundaries (\b), etc. - Case-insensitive by default: All patterns are automatically case-insensitive
- Real-time updates: Results update as you type (invalid patterns show no matches)
- Memory efficient: Only searches visible diff content, not entire repository
- Cross-view consistency: Same regex experience in unified and side-by-side modes
| Pattern | Matches | Use Case |
|---|---|---|
searc. |
"search", "searck" | Find similar words |
fn.*test |
"fn my_test", "function test_case" | Find functions containing "test" |
[0-9]+ |
"123", "42" | Find numbers |
\btest\b |
"test" (whole word only) | Exact word match |
(let|const) |
"let" or "const" | Multiple alternatives |
TODO.*: |
"TODO: fix this" | Find TODO comments |
┌─ Commit Details ──────────────────────────────────┐
│ Hash: abc123def456789abcdef123456789abcdef12 │
│ Author: Jane Developer <jane@company.com> │
│ Date: 2023-08-15 14:30:22 │
│ Refs: (branch:main, tag:v1.2.0) │
│ PR: #142 - Add authentication system │
│ Stats: 5 files, +120 -30 lines │
│ │
│ ┌─ Full Message ─────────────────────────────────┐ │
│ │ Implement user authentication system │ │
│ │ │ │
│ │ Added JWT token support and password hashing. │ │
│ │ │ │
│ │ This commit includes: │ │
│ │ - JWT token generation │ │
│ │ │ - Password validation │ │
│ │ │ - Session management │ │
│ │ └─────────────────────────────────────────────────┘ │
│ [↑↓/jk] Scroll [c] Copy hash [q] Close │
└────────────────────────────────────────────────────────┘
| Key | Action |
|---|---|
m |
Cycle merge parents |
┌─ Select File ─────────────────────────┐
│ ┌─ Search ─────────────────────────┐ │
│ │ 🔍 main │ │
│ └─────────────────────────────────────┘ │
│ ▲ src/main.rs Modified │
│ > src/app.rs 2024-08-15 │
│ src/cli.rs 2024-08-14 │
│ README.md 2024-08-13 │
│ Cargo.toml 2024-08-12 │
│ ... │
│ 📁 42 files • 4 matches • ↑↓: navigate • Enter: select • Ctrl+Q: quit
└───────────────────────────────────────┘
┌─ Commits ─────────────────────┐┌─ Diff ─────────────────────────┐
│ > Working Dir Modified ││ diff --git a/src/main.rs │
│ 2025-08-15 77942bc Latest ││ @@ -10,6 +10,8 @@ fn main() { │
│ 2025-08-14 3f30143 Feature ││ fn main() { │
│ 2025-08-13 603c9b0 Phase-2 ││ - println!("Hello"); │
│ ... ││ + println!("Hello, world!");│
└───────────────────────────────┘└─────────────────────────────────┘
[main.rs@77942bc] Tab: switch panels | f: switch file | d: range diff | ?: help
┌─ Commits ─────────────────────┐┌─ Diff (603c9b0..77942bc) ─────┐
│ Working Dir Modified ││ diff --git a/src/main.rs │
│ ► 2025-08-15 77942bc Latest ││ @@ -15,4 +15,12 @@ fn handle() { │
│ 2025-08-14 3f30143 Feature ││ fn handle() { │
│ ► 2025-08-13 603c9b0 Phase-2 ││ + // New error handling │
│ ... ││ + if error.is_fatal() { │
└───────────────────────────────┘└─────────────────────────────────┘
[Range: 603c9b0..77942bc] Shows changes between two selected commits
Fast & Focused: Unlike heavyweight GUI tools, Geschichte is built for speed and terminal workflows.
Rename-Aware: Tracks files across renames and moves, showing the complete evolution of your code.
Working Directory Integration: See your uncommitted changes alongside git history in one unified view.
Keyboard-Driven: Efficient navigation with vim-style keybindings, plus Mac-friendly alternatives.
Developer-Friendly: Built by developers, for developers who live in the terminal.
- External editor integration - Open current file in your preferred editor (vim, VS Code, etc.) at the current line
- In-diff search - Search within diff content with context-aware highlighting
- Copy commit hash - Quick clipboard integration with multiple formats
- Detailed commit information - Comprehensive metadata popups
- Enhanced commit metadata - Author/committer details, refs, PR detection
- Commit statistics - Files changed, insertions, deletions display
- Merge parent cycling - Navigate through merge commit parents
- Enhanced copy options - More format options and integrations
- Advanced search options - Regex patterns, match case toggle, and search history
- Performance optimizations - Handle massive repositories efficiently
- Enhanced syntax highlighting - More language support and themes
- Configuration files - Customizable themes and keybindings
- Blame view - See who changed each line and when
- Commit editing workflows - Interactive rebase, cherry-pick support
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
git clone https://github.com/yourusername/geschichte.git
cd geschichte
make dev # Format + lint + test + build
make demo # Install and run with demo filemake build # Debug build
make release # Optimized build
make test # Run all tests
make lint # Clippy + format check
make fmt # Format code
make clean # Clean build artifacts
# Workflows
make dev # Full development workflow
make ci # Continuous integration checks
make pre-release # Release preparation- Startup time: < 500ms for typical repositories
- Memory usage: < 20MB for 1000+ commits
- Diff caching: LRU cache holds 50 diffs for instant navigation
- Large repositories: Tested with 10k+ commit histories
Built with these excellent Rust crates:
- ratatui - Terminal UI framework
- crossterm - Cross-platform terminal manipulation
- clap - Command line parsing
- anyhow - Error handling
- arboard - Cross-platform clipboard access
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by
tig,lazygit, and other excellent terminal git tools - Built with the amazing Rust ecosystem
- Special thanks to the
ratatuicommunity for the excellent TUI framework
Etymology: Geschichte is German for "history" or "story" - fitting for a tool that helps you explore the story of your code.
