Skip to main content

Command Palette

Search for a command to run...

Never Leaving the Editor for Git

Updated
3 min readView as Markdown
S
I'm Sushanth, a high school senior in Hyderabad, India. This is where I write about the things I spend time on: learning from mistakes, building things in code, and the tools I actually work with day to day. I hold the Candidate Master title and a FIDE International Master norm, earned across roughly 140 rated tournaments in six countries. I stopped competing in 2025, but the habit competition taught me, sitting down after every loss and figuring out exactly where I went wrong, shapes how I approach everything else. On the technical side, I've gone deep on C/C++ through Duke University and University of London coursework. I'm also someone who likes a good terminal workflow and enjoys exploring (and abandoning) productivity tools. Expect posts on Neovim, tmux, what broke this week, and whatever I'm tinkering with.

Hunk-level staging, a text object I forgot I had, and the line gitsigns.nav_hunk quietly replaced.

I used to tab out to a terminal for anything past git status and git commit -m. Staging specific chunks of a file meant git add -p, reading through hunks in a pager, answering y/n/s prompts. It worked, but it was a switch every time, and I stopped doing it more than I should have. gitsigns.nvim and diffview.nvim got rid of the switch entirely.

The part that actually changed my habits is the hunk as a first-class object. gitsigns gives you a text object for it:

map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", { desc = "Select hunk" })
map("n", "<leader>ghs", gs.stage_hunk,      { desc = "Stage hunk" })
map("n", "<leader>ghr", gs.reset_hunk,      { desc = "Reset hunk" })
map("n", "<leader>ghp", gs.preview_hunk,    { desc = "Preview hunk" })

That ih mapping is doing the same job iw does for a word or ip does for a paragraph, just scoped to "the changed lines around the cursor." Once it's a text object, every operator in Vim works on it for free. dih deletes the hunk's changes back to the committed version: no reset_hunk keymap needed, just an operator I already know applied to a new noun.

One thing that confused me recently: gitsigns renamed its navigation function. The old next_hunk() / prev_hunk() pair is deprecated upstream in favor of a single nav_hunk() that takes a direction:

map("n", "]h", function() gs.nav_hunk("next") end, { desc = "Next hunk" })
map("n", "[h", function() gs.nav_hunk("prev") end, { desc = "Prev hunk" })

Small API change, but it's the kind of thing that breaks a keymap if you copy an old config from a blog post (including, this one: check the gitsigns changelog before you trust anything I just wrote, APIs evolve).

For anything past a single hunk, diffview.nvim takes over — <leader>gd opens a full diff view of the working tree, <leader>gH opens file history for whatever buffer I'm in. It's not trying to replace a terminal git client, it's the two things I actually needed: "what changed" and "what changed over time," both without losing my cursor position in the file I was just editing.

None of this is special. It's the same git operations I'd run from a shell, just addressed as objects in the buffer instead of typed as separate commands. The workflow got shorter mostly by not making me leave.