# lazygit - Product Requirements Document ## Overview **lazygit** is a simple terminal UI for git commands, written in Go. It provides an intuitive, keyboard-driven interface for managing git repositories without memorizing complex git commands. - **Version**: 0.58.1 - **Author**: Jesse Duffield - **Repository**: https://github.com/jesseduffield/lazygit - **License**: MIT ## Table of Contents 1. [Core Concepts](#core-concepts) 2. [User Interface](#user-interface) 3. [Panel System](#panel-system) 4. [Keybindings](#keybindings) 5. [Git Operations](#git-operations) 6. [Configuration](#configuration) 7. [CLI Interface](#cli-interface) 8. [Automation with VHS](#automation-with-vhs) --- ## Core Concepts ### Design Philosophy - **Keyboard-first**: All operations accessible via keyboard shortcuts - **Context-aware**: Keybindings change based on focused panel and selected item - **Visual feedback**: Real-time diff views, color-coded file states - **Non-destructive**: Confirmation prompts for dangerous operations - **Discoverable**: Built-in help system (`?`) shows available actions ### File States | Indicator | Meaning | |-----------|---------| | `M` | Modified (tracked file changed) | | `A` | Added (new file staged) | | `D` | Deleted | | `R` | Renamed | | `C` | Copied | | `??` | Untracked (new file not staged) | | `UU` | Unmerged (conflict) | --- ## User Interface ### Layout Overview ``` +--[1]-Status---------+--[0]-Main View (Diff/Log/Patch)--------+ | repo-name -> branch | | +--[2]-Files----------+ | | Files/Worktrees/ | | | Submodules | | +--[3]-Branches-------+ | | Local/Remotes/Tags | | +--[4]-Commits--------+-----------------------------------------+ | Commits/Reflog |--Command log---------------------------+| +--[5]-Stash----------+ || | Stash entries | || +---------------------+----------------------------------------++ | Status bar: Quick actions | Keybindings: ? | Version 0.58.1| +------------------------------------------------------------------+ ``` ### Panel Numbers | # | Panel | Description | |---|-------|-------------| | 0 | Main View | Displays diffs, logs, patches, commit details | | 1 | Status | Repository name and current branch | | 2 | Files | Working tree changes, worktrees, submodules | | 3 | Branches | Local branches, remotes, tags | | 4 | Commits | Commit history, reflog | | 5 | Stash | Stash entries | ### Navigation Between Panels | Key | Action | |-----|--------| | `1-5` | Jump directly to panel by number | | `0` | Focus main view | | `h/l` or `Left/Right` | Move between panels | | `Tab` | Toggle between side panels and main view | | `[` / `]` | Switch tabs within a panel | ### Screen Modes | Key | Mode | Description | |-----|------|-------------| | `+` | Next screen mode | Cycles: normal -> half -> full | | `_` | Previous screen mode | Cycles backwards | --- ## Panel System ### Panel 1: Status Displays the repository name and current branch. **Actions:** | Key | Action | |-----|--------| | `Enter` | Recent repositories | | `a` | All branches log graph | | `u` | Check for updates | ### Panel 2: Files / Worktrees / Submodules **Tabs:** Files | Worktrees | Submodules #### Files Tab **File Operations:** | Key | Action | |-----|--------| | `Space` | Stage/unstage file | | `a` | Stage/unstage all files | | `Enter` | Enter staging view (line-by-line staging) | | `d` | Discard changes | | `D` | Reset options menu | | `e` | Edit file | | `o` | Open file | | `i` | Ignore file (.gitignore) | | `r` | Refresh files | | `` ` `` | Toggle file tree view | | `-` | Collapse all directories | | `=` | Expand all directories | **Commit Operations:** | Key | Action | |-----|--------| | `c` | Commit staged changes | | `C` | Commit with editor | | `w` | Commit without pre-commit hook | | `A` | Amend last commit | | `Ctrl+f` | Find base commit for fixup | **Stash Operations:** | Key | Action | |-----|--------| | `s` | Stash all changes | | `S` | Stash options menu | **Stash Options Menu:** - `a` - Stash all changes - `i` - Stash all changes and keep index - `U` - Stash all changes including untracked files - `s` - Stash staged changes - `u` - Stash unstaged changes **Reset Options Menu (`D`):** - `u` - Discard unstaged changes (`git checkout -- .`) - `d` - Discard untracked files (`git clean -fd`) - `S` - Discard staged changes (`stash staged and drop stash`) - `s` - Soft reset (`git reset --soft HEAD`) - `m` - Mixed reset (`git reset --mixed HEAD`) - `h` - Hard reset (`git reset --hard HEAD`) #### Worktrees Tab | Key | Action | |-----|--------| | `n` | New worktree | | `Space` | Switch to worktree | | `d` | Remove worktree | | `w` | View worktree options | #### Submodules Tab | Key | Action | |-----|--------| | `i` | Initialize submodule | | `u` | Update submodule | | `b` | Bulk menu | | `Enter` | Enter submodule | ### Panel 3: Local Branches / Remotes / Tags **Tabs:** Local branches | Remotes | Tags #### Local Branches Tab | Key | Action | |-----|--------| | `Space` | Checkout branch | | `n` | New branch | | `d` | Delete branch | | `r` | Rebase current branch onto selected | | `R` | Rename branch | | `M` | Merge selected into current branch | | `f` | Fast-forward branch | | `F` | Force checkout | | `-` | Checkout previous branch | | `u` | Set upstream | | `i` | View git-flow options | | `o` | Create pull request | | `O` | View pull request options | | `Ctrl+y` | Copy pull request URL | | `T` | Create tag | | `s` | Sort order | **Rebase Menu (`r`):** - `s` - Simple rebase onto selected branch - `i` - Interactive rebase onto selected branch - `b` - Rebase onto base branch #### Remotes Tab | Key | Action | |-----|--------| | `Enter` | View branches | | `n` | New remote | | `d` | Remove remote | | `e` | Edit remote | | `f` | Fetch from remote | | `F` | Add fork remote | #### Tags Tab | Key | Action | |-----|--------| | `Ctrl+o` | Copy tag to clipboard | | `Space` | Checkout tag | | `n` | New tag | | `d` | Delete tag | | `P` | Push tag | | `g` | Reset to tag | | `Enter` | View commits | | `w` | View worktree options | ### Panel 4: Commits / Reflog **Tabs:** Commits | Reflog #### Commits Tab **Navigation & Selection:** | Key | Action | |-----|--------| | `j/k` | Move up/down | | `Space` | Checkout commit | | `Enter` | View commit files | | `v` | Toggle range select | | `*` | Select commits of current branch | **Commit Manipulation:** | Key | Action | |-----|--------| | `r` | Reword commit message | | `R` | Reword with editor | | `e` | Edit commit (start interactive rebase) | | `d` | Drop commit | | `s` | Squash down | | `S` | Squash all above commits | | `f` | Mark as fixup | | `F` | Create fixup commit | | `p` | Pick commit | | `Ctrl+j` | Move commit down | | `Ctrl+k` | Move commit up | | `i` | Start interactive rebase | **Advanced Operations:** | Key | Action | |-----|--------| | `A` | Amend commit with staged changes | | `a` | Reset commit author | | `t` | Revert commit | | `T` | Tag commit | | `C` | Cherry-pick copy | | `V` | Paste (cherry-pick) commits | | `Ctrl+R` | Reset cherry-pick selection | | `B` | Mark as base for rebase | | `b` | View bisect options | | `g` | View reset options | | `y` | Copy commit attribute to clipboard | | `o` | Open commit in browser | | `Ctrl+l` | Open log menu | | `n` | Create new branch off commit | **Bisect Menu (`b`):** - `b` - Mark commit as bad (start bisect) - `g` - Mark commit as good (start bisect) - `t` - Choose bisect terms - Cancel #### Reflog Tab Shows the reference log for recovering lost commits. | Key | Action | |-----|--------| | `Space` | Checkout reflog entry | | `g` | View reset options | | `C` | Cherry-pick copy | | `V` | Paste commits | ### Panel 5: Stash | Key | Action | |-----|--------| | `Space` | Apply stash | | `g` | Pop stash | | `d` | Drop stash | | `n` | New branch from stash | | `r` | Rename stash | | `Enter` | View stash files | --- ## Keybindings ### Global Keybindings **Navigation:** | Key | Action | |-----|--------| | `j/k` or `Up/Down` | Move up/down in list | | `h/l` or `Left/Right` | Move between panels | | `<` / `>` | Go to top/bottom of list | | `Home` / `End` | Go to top/bottom of list | | `,` / `.` | Page up/down | | `PgUp` / `PgDown` | Scroll main window | | `J/K` or `Ctrl+u/Ctrl+d` | Scroll main window | | `H` / `L` | Scroll left/right | **Actions:** | Key | Action | |-----|--------| | `?` | Show keybindings help | | `Enter` | Confirm / Go into | | `Esc` | Return / Cancel | | `Space` | Primary action (context-dependent) | | `/` | Start search | | `n` / `N` | Next/previous search match | | `q` | Quit | | `Q` | Quit without changing directory | | `Ctrl+c` | Quit (alternative) | | `Ctrl+z` | Suspend application | **Git Operations:** | Key | Action | |-----|--------| | `P` | Push | | `p` | Pull | | `f` | Fetch (in files panel) | | `R` | Refresh | | `z` | Undo (reflog) | | `Z` | Redo (reflog) | | `m` | View merge/rebase options | **View Options:** | Key | Action | |-----|--------| | `@` | View command log options | | `+` / `_` | Next/previous screen mode | | `\|` | Cycle pagers | | `W` or `Ctrl+e` | Diffing menu | | `Ctrl+w` | Toggle whitespace in diff | | `}` / `{` | Increase/decrease diff context | | `)` / `(` | Increase/decrease rename similarity threshold | | `Ctrl+t` | Open external diff tool | | `Ctrl+s` | Filtering menu | **Other:** | Key | Action | |-----|--------| | `:` | Execute shell command | | `Ctrl+r` | Switch to recent repo | | `Ctrl+o` | Copy to clipboard | | `Ctrl+p` | View custom patch options | ### Staging View Keybindings When viewing a file's diff (entered via `Enter` on a file): | Key | Action | |-----|--------| | `Space` | Stage/unstage line | | `a` | Toggle select hunk | | `A` | Stage/unstage all changes | | `v` | Toggle range select | | `j/k` | Move up/down | | `J/K` | Scroll diff up/down | | `E` | Edit hunk in editor | | `e` | Edit file | | `o` | Open file | | `Esc` | Return to files panel | | `Tab` | Switch to staged/unstaged changes | | `b` | Pick both hunks (merge conflicts) | --- ## Git Operations ### Committing 1. **Stage changes**: `Space` on files or `a` to stage all 2. **Commit**: `c` to commit with inline message 3. **Commit with editor**: `C` to open editor for commit message 4. **Amend**: `A` to amend the last commit with staged changes 5. **Commit without hooks**: `w` to skip pre-commit hooks ### Branching 1. **Create branch**: `n` in branches panel 2. **Checkout**: `Space` on branch 3. **Delete**: `d` on branch 4. **Rename**: `R` on branch 5. **Checkout previous**: `-` in branches panel ### Merging 1. Navigate to branches panel (`3`) 2. Select the branch to merge 3. Press `M` to merge into current branch **During merge conflicts:** - Files with `UU` status indicate conflicts - Enter file to resolve conflicts line-by-line - Use `b` to pick both sides - Stage resolved files with `Space` - Continue merge with `m` -> continue option ### Rebasing **Simple rebase:** 1. Go to branches panel 2. Select target branch 3. Press `r` to open rebase menu 4. Choose rebase type **Interactive rebase:** 1. Go to commits panel 2. Navigate to the commit before where you want to start 3. Press `i` to start interactive rebase 4. Use `p` (pick), `s` (squash), `f` (fixup), `d` (drop), `e` (edit) 5. Reorder commits with `Ctrl+j/k` 6. Press `m` to view rebase options and continue/abort ### Cherry-picking 1. Navigate to the commit to cherry-pick 2. Press `C` to copy the commit 3. Switch to the target branch 4. Press `V` to paste (cherry-pick) 5. Use `Ctrl+R` to reset cherry-pick selection ### Stashing **Quick stash:** - `s` in files panel stashes all changes **Stash options (`S`):** - Stash all changes - Stash including untracked - Stash only staged - Stash only unstaged - Keep index **Using stashes:** - `Space` - Apply stash (keep stash) - `g` - Pop stash (apply and remove) - `d` - Drop stash ### Bisecting 1. Go to commits panel 2. Press `b` to open bisect menu 3. Mark a known bad commit with `b` 4. Mark a known good commit with `g` 5. Test each commit lazygit checks out 6. Mark as good/bad until bug is found 7. Reset bisect when done ### Working with Remotes **Push:** - `P` globally pushes current branch - Force push available in push options menu **Pull:** - `p` globally pulls current branch - Configurable pull strategy (merge/rebase) **Fetch:** - `f` in files panel fetches from remote - Auto-fetch configurable in settings --- ## Configuration ### Configuration File Location ```bash lazygit --print-config-dir # Shows config directory # Usually: ~/.config/lazygit/config.yml ``` ### Key Configuration Options ```yaml gui: # Panel sizing sidePanelWidth: 0.3333 expandFocusedSidePanel: false mainPanelSplitMode: flexible # flexible | horizontal | vertical # Display options showFileTree: true showIcons: false nerdFontsVersion: "" # Set to "3" for nerd fonts v3 showCommandLog: true showBottomLine: true showPanelJumps: true # Behavior mouseEvents: true skipDiscardChangeWarning: false skipStashWarning: false # Theme colors theme: activeBorderColor: - green - bold inactiveBorderColor: - default selectedLineBgColor: - blue unstagedChangesColor: - red git: # Auto operations autoFetch: true autoRefresh: true fetchAll: true # Commit settings commit: signOff: false autoWrapCommitMessage: true autoWrapWidth: 72 # Merge settings merging: manualCommit: false args: "" # Main branches for rebase targets mainBranches: - master - main # Log display log: order: topo-order # topo-order | date-order | author-date-order showGraph: always # always | never | when-maximised # Refresh intervals (seconds) refresher: refreshInterval: 10 fetchInterval: 60 # Confirmation settings confirmOnQuit: false quitOnTopLevelReturn: false # Custom commands (advanced) customCommands: [] ``` ### Custom Keybindings Keybindings can be customized in `config.yml`: ```yaml keybinding: universal: quit: q return: togglePanel: prevItem: nextItem: # ... etc files: commitChanges: c amendLastCommit: A # ... etc branches: createPullRequest: o rebaseBranch: r # ... etc ``` ### Custom Commands Define custom commands accessible via keybindings: ```yaml customCommands: - key: "C" command: "git cz" # Commitizen context: "files" loadingText: "Opening commitizen" subprocess: true - key: "b" command: "git blame {{.SelectedFile.Name}}" context: "files" loadingText: "Blaming file" ``` --- ## CLI Interface ### Basic Usage ```bash lazygit # Open in current directory lazygit -p /path/to/repo # Open specific repository lazygit status # Focus status panel on open lazygit branch # Focus branch panel on open lazygit log # Focus log panel on open lazygit stash # Focus stash panel on open ``` ### Command Line Flags | Flag | Description | |------|-------------| | `-h, --help` | Display help | | `-v, --version` | Print version | | `-p, --path PATH` | Path to git repo | | `-f, --filter PATH` | Filter log by path | | `-c, --config` | Print default config | | `-cd, --print-config-dir` | Print config directory | | `-ucd, --use-config-dir DIR` | Override config directory | | `-ucf, --use-config-file FILES` | Comma-separated config files | | `-w, --work-tree PATH` | Git work-tree argument | | `-g, --git-dir PATH` | Git git-dir argument | | `-sm, --screen-mode MODE` | Initial screen mode: normal, half, full | | `-d, --debug` | Run in debug mode with logging | | `-l, --logs` | Tail lazygit logs | | `--profile` | Start profiler on port 6060 | ### Examples ```bash # Open repo at specific path lazygit -p ~/projects/myrepo # Filter commits by file path lazygit -f src/main.js # Use custom config lazygit -ucf ~/.config/lazygit/work-config.yml # Start in full screen mode lazygit -sm full # Debug mode lazygit -d # In another terminal: lazygit -l # Watch logs ``` --- ## Automation with VHS [VHS](https://github.com/charmbracelet/vhs) can be used to programmatically control lazygit for demos, testing, and documentation. ### VHS Tape Syntax ```tape # Configure output Output "demo.gif" Set Shell "bash" Set FontSize 14 Set Width 1200 Set Height 800 # Launch lazygit Type "cd /path/to/repo && lazygit" Enter Sleep 2s # Navigate with keyboard Type "2" # Go to files panel Sleep 500ms Type "j" # Move down Sleep 500ms Space # Stage file Sleep 500ms Type "c" # Start commit Sleep 1s Type "Add new feature" Enter Sleep 1s # Capture screenshots Screenshot "commit-complete.png" # Quit Type "q" ``` ### VHS Commands for lazygit | Command | Usage | Description | |---------|-------|-------------| | `Type "x"` | `Type "c"` | Type character (triggers keybinding) | | `Enter` | `Enter` | Press Enter key | | `Escape` | `Escape` | Press Escape key | | `Space` | `Space` | Press Space key | | `Tab` | `Tab` | Press Tab key | | `Up/Down/Left/Right` | `Down` | Arrow keys | | `Sleep Xs` | `Sleep 500ms` | Wait for UI | | `Screenshot "file.png"` | `Screenshot "/tmp/shot.png"` | Capture frame | ### Example: Automated Commit Demo ```tape Output "lazygit-commit-demo.gif" Set Shell "bash" Set Width 1200 Set Height 800 Set Framerate 10 # Setup Type "cd /tmp/test-repo && lazygit" Enter Sleep 2s # Show modified files Type "2" Sleep 1s # Stage all changes Type "a" Sleep 500ms # Open commit dialog Type "c" Sleep 1s # Type commit message Type "feat: add new authentication module" Enter Sleep 1s # Show result Screenshot "commit-complete.png" Sleep 2s # Quit Type "q" ``` ### Running VHS Tapes ```bash # Run tape and generate output vhs demo.tape # Validate tape without running vhs validate demo.tape # Record a new tape interactively vhs record # Publish GIF to share vhs publish demo.gif ``` --- ## Tips and Tricks ### Productivity Tips 1. **Use panel numbers**: Press `1-5` to jump directly to panels 2. **Toggle views**: Press `+` to maximize the current panel 3. **Filter commits**: Use `/` to search in any list 4. **Quick stash**: Press `s` to stash all changes instantly 5. **Undo mistakes**: Press `z` to undo via reflog 6. **Copy commit hash**: Press `y` on a commit for copy options 7. **Open in browser**: Press `o` on a commit to view on GitHub/GitLab ### Advanced Usage 1. **Patch mode**: Use `Ctrl+p` to create partial patches from commits 2. **Custom commands**: Define frequently used git aliases 3. **Multiple configs**: Use `-ucf` for project-specific settings 4. **Filter mode**: Use `-f` to focus on specific file history ### Keyboard Navigation Summary ``` ┌─────────────────────────────────────────┐ │ PANEL NAVIGATION │ ├─────────────────────────────────────────┤ │ 1-5: Jump to panel Tab: Toggle view │ │ h/l: Move left/right [/]: Switch tabs │ │ j/k: Move up/down : Top/bottom │ ├─────────────────────────────────────────┤ │ COMMON ACTIONS │ ├─────────────────────────────────────────┤ │ Space: Primary action Enter: Go into │ │ c: Commit P: Push p: Pull │ │ s: Stash z: Undo ?: Help │ │ /: Search q: Quit │ └─────────────────────────────────────────┘ ``` --- ## Comparison with Other Tools | Feature | lazygit | tig | gitui | git CLI | |---------|---------|-----|-------|---------| | TUI Interface | Yes | Yes | Yes | No | | Staging View | Line-level | Hunk-level | Line-level | Hunk-level | | Interactive Rebase | Visual | No | Visual | Editor | | Merge Conflict UI | Yes | No | Yes | No | | Customizable | YAML config | Limited | TOML config | Aliases | | Language | Go | C | Rust | C | | Cross-platform | Yes | Yes | Yes | Yes | --- ## Resources - **Documentation**: https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings - **Configuration**: https://github.com/jesseduffield/lazygit/blob/v0.58.1/docs/Config.md - **Tutorial Video**: https://youtu.be/VDXvbHZYeKY - **Issues**: https://github.com/jesseduffield/lazygit/issues - **Releases**: https://github.com/jesseduffield/lazygit/releases - **Sponsor**: https://github.com/sponsors/jesseduffield --- *Document generated through programmatic exploration of lazygit v0.58.1 using VHS automation.*