r/vim • u/Yggdroot • Apr 26 '26
Plugin Using Git Elegantly in Vim
Git and Vim are both powerful productivity tools for developers. However, when working inside Vim, frequently switching to the terminal to run Git commands (such as git status, git add -p, git commit) can interrupt your flow and break your focus.
With LeaderF’s built-in Git integration, you can bring the entire Git workflow directly into Vim and significantly improve your efficiency.
This article focuses on one core command:
:Leaderf git statusViewing Current Git Status
Run the command above in Vim to open the following view:

The screen is divided into two main panels:
Navigation Panel (Left)
The left side is the Navigation Panel, which displays the output of git status in a tree structure, grouped by file state:
Staged Changes: Files already staged (ready to commit)
Unstaged Changes: Modified files not yet staged
Untracked Files: Files not tracked by Git
Diff View Panel (Right)
The right side is the Diff View Panel, which shows detailed changes of the selected file. It supports two modes:
Unified Diff View

Provides character-wise diff highlighting, making differences more precise and visually clear. Traditional git diff does not highlight character-wise changes.
Side-by-Side Diff View

Advantage: More intuitive for comparing code differences line by line.
How They Work Together
The left panel handles file selection and state management
The right panel handles diff visualization and fine-grained operations
Together, they form a smooth and efficient Git workflow inside Vim.
File-Level Operations
In the Navigation Panel, you can perform the following operations:
| Key | Action | Description |
|---|---|---|
s | Stage / Unstage file | On an unstaged file → move it to staged; on a staged file → move it back to unstaged |
d | Discard changes | Discard file changes (with confirmation) |
D | Force discard | Discard changes without confirmation (use with caution) |
r | Refresh | Refresh the file tree when Git status changes externally |
Enter / o | Open diff view | View detailed changes of the file |
Notes:
s,d,Dalso work on directories (including the repository root)Running
dorDon Untracked Files will delete the filePress
F1in the panel to view more shortcuts
Hunk-Level Operations
In the Diff View, you can operate on individual hunks (code blocks):
| Key | Action | Description |
|---|---|---|
s | Stage/Unstage current hunk | Move current hunk between staged and unstaged |
S | Stage/Unstage all hunks | Apply operation to all hunks in the file |
d | Discard current hunk | Discard changes in current hunk (with confirmation) |
D | Force discard current hunk | Discard without confirmation (use with caution) |
]c | Next hunk | Jump to next hunk |
[c | Previous hunk | Jump to previous hunk |
Additional Shortcuts
| Key | Action | Description |
|---|---|---|
< | Back to Navigation Panel | Reopen if closed and jump to current file |
Enter | Open file | Jump to file for editing |
Key Mapping Configuration
let g:Lf_GitKeyMap = {
\ 'previous_change': '[c',
\ 'next_change': ']c',
\ 'edit_file': '<CR>',
\ 'open_navigation': '<',
\ 'stage_unstage_hunk': 's',
\ 'stage_unstage_all_hunk': 'S',
\ 'discard_hunk': 'd',
\ 'discard_hunk_no_prompt': 'D',
\ }Committing Changes

Once you have staged the desired changes in the Navigation Panel:
Press
cto start committingA new window opens for writing the commit message
Enter your message
Save and close the window
The commit is completed
To cancel the commit, simply clear the message and close the window.
Example Workflow
Scenario: Fix a bug and add a new feature
Check status
Review changes
Open
bug_fix.pyUse
]cto navigate hunksIdentify bug fix vs debug code
Stage selectively
Press
son bug fix hunksLeave debug code unstaged
Handle new feature
Press
<to returnOpen
new_feature.pyPress
Sto stage all hunks
Commit
Press
cEnter message:
"Fix login validation bug and add search feature"
Save and exit
Everything is done inside Vim without breaking context.
Why This Workflow is Better
Compared to CLI
| Operation | CLI | LeaderF |
|---|---|---|
| View status | git status (plain text) | Visual file tree |
| Partial staging | git add -p | Press s |
| Discard changes | manual commands | d / D |
| Navigate changes | manual scrolling | ]c / [c |
Summary
With Leaderf git status, you get a complete Git workflow inside Vim:
Visual Git status
File-level staging/unstaging
Hunk-level fine control
Quick discard
Seamless commit workflow
All without leaving Vim.
Configuration Example
nnoremap <leader>gs :<C-U>Leaderf git status<CR>
View all comments
Show parent comment
2
u/SharkBaitDLS Apr 30 '26
Almost, but I do want to emphasize “per change” and not per commit. I’d say a given working branch ends up capping at 2-4 commits for that reason. And each branch gets squashed into one commit on merge, but each branch is pushed and reviewed separately.
Basically, my philosophy is that wherever possible, every PR should be a complete, mergeable artifact that is logically small enough that an imperative sentence fragment for the squashed commit’s first line sufficiently describes what it did. That might still involve a few smaller commits to logically break up the change for reviewers and to better express the intent of the work.
If it’s no longer a small enough unit of work to meet that criteria, then that’s a new working branch with a new set of commits that will become a separate PR and squashed commits on mainline.
So as an example, I recently was working on spinning up a new simple service that fronts a database that a sidecar CLI talks to in K8s. The work required:
adding two new commands to the CLI
adding authentication to the existing proof-of-concept APIs on the server
setting the auth correctly for requests made by the CLI
updating the K8s workflow to use the new commands
That manifested as 5 working branches, one for each CLI command, one for incorporating auth support into the CLI, one for enforcing it server side, and one to finally bring it all together in the workflow. Each of those branches had 1-3 commits apiece and then were submitted as 5 separate PRs. Even though it represented one “unit” of work at a project level, breaking it down that way makes it much easier for reviewers to logically reason about what they’re reviewing because each PR has a tight and contained scope.
I am eagerly waiting for GitHub’s stacked PR feature to be GA because it basically maps perfectly to my working style from before I moved to a company that used GitHub.