Di episode ini kita akan menghidupkan Git langsung di dalam Neovim: indikator perubahan di gutter, blame inline, stage/reset hunk dengan gitsigns.nvim, hingga diff dan resolusi merge conflict dengan diffview.nvim.

Setelah di episode 17 sebelumnya kita memastikan kualitas kode dengan formatting otomatis dan linting asinkron, pada episode kali ini kita membahas alat kolaborasi yang sesungguhnya: Git. Kita akan membawa Git ke dalam Neovim dengan dua plugin utama — gitsigns.nvim untuk visualisasi perubahan di gutter dan diffview.nvim untuk diff serta resolusi merge conflict.
Di dunia nyata, hampir tidak ada software engineering yang berjalan sendirian. Setiap hari kita melakukan hal yang sama: melihat apa yang berubah sejak terakhir kali, memeriksa hunk yang diubah rekan kerja, membatalkan satu baris yang salah, atau menyelesaikan conflict setelah pull. Bagi developer yang berpindah-pindah antara editor dan terminal, pekerjaan semacam ini memecah fokus: buka terminal, jalankan git diff, baca output mentah, kembali ke editor, temukan barisnya... Di episode ini, kalian akan belajar menjalankan seluruh workflow itu tanpa meninggalkan editor — dan inilah yang membuat Neovim terasa seperti IDE kolaboratif yang sesungguhnya.
Git sendiri adalah tool CLI yang hebat, tapi output-nya berbentuk teks statis. Yang kita butuhkan adalah connection antara hasil git diff dengan buffer yang sedang kita edit. Di sinilah kedua plugin ini punya peran:
| Plugin | Peran | Analogi |
|---|---|---|
gitsigns.nvim | Visualisasi perubahan di dalam buffer | Lampu indikator di pinggir file |
diffview.nvim | Diff antar commit/branch & merge tool | Jendela perbandingan ala GUI Git |
neogit / fugitive | Git client lengkap dalam editor | Alternatif GUI Git tanpa meninggalkan Neovim |
Analogi paling pas: gitsigns adalah dashbor mobil (menunjukkan perubahan saat ini tanpa membuka panel lain), sedangkan diffview dan neogit adalah garasi tempat kalian melakukan perbandingan dan perawatan kendaraan secara menyeluruh.
gitsigns.nvim menampilkan tanda +, ~, - di kolom sign (gutter) untuk baris yang ditambah, diubah, atau dihapus sejak commit terakhir. Ia dihitung secara asinkron oleh git diff, sehingga tidak membebani editor. Berikut konfigurasinya:
return {
{
"lewis6991/gitsigns.nvim",
event = { "BufReadPre" },
opts = {
signs = {
add = { text = "+" },
change = { text = "~" },
delete = { text = "_" },
topdelete = { text = "‾" },
changedelete = { text = "~" },
},
on_attach = function(bufnr)
local gitsigns = require("gitsigns")
local opts = { buffer = bufnr, silent = true }
vim.keymap.set("n", "<leader>gp", gitsigns.preview_hunk, opts)
vim.keymap.set("n", "<leader>gs", gitsigns.stage_hunk, opts)
vim.keymap.set("n", "<leader>gr", gitsigns.reset_hunk, opts)
vim.keymap.set("n", "<leader>gS", gitsigns.stage_buffer, opts)
vim.keymap.set("n", "<leader>gu", gitsigns.undo_stage_hunk, opts)
vim.keymap.set("n", "<leader>gb", function()
gitsigns.blame_line({ full = true })
end, opts)
vim.keymap.set("n", "[h", gitsigns.prev_hunk, { buffer = bufnr, silent = true })
vim.keymap.set("n", "]h", gitsigns.next_hunk, { buffer = bufnr, silent = true })
end,
},
},
}Bedah keymap yang baru kita definisikan:
<leader>gs — stage hunk di bawah kursor (menandai perubahan untuk di-commit). Ini adalah pengganti git add -p dalam bentuk yang jauh lebih visual.<leader>gr — reset hunk, membatalkan perubahan di hunk tersebut dan mengembalikannya ke kondisi commit terakhir. Berhati-hatilah — operasi ini menghapus perubahan secara permanen.<leader>gp — preview hunk: membuka jendela kecil yang menampilkan diff persis hunk tersebut, tanpa berpindah buffer.<leader>gu — undo stage: menarik hunk yang sudah di-stage kembali ke working directory (kebalikan dari stage).<leader>gb — inline blame: menampilkan sha1 author tanggal pada baris tempat kursor berada. Fungsi ini memicu baris blame satu baris saja dengan blame_line({ full = true }) untuk detail lengkap.[h / ]h — lompat ke hunk sebelumnya / berikutnya. Berguna sebelum melakukan preview atau stage berurutan.Skenario paling umum dalam kehidupan nyata — bekerja dengan dua file yang dicampur dalam satu working tree:
1. Buka file yang sudah diubah → gutter menampilkan + ~ - sesuai perubahan.
2. Tekan ]h untuk lompat ke hunk pertama.
3. Tekan <leader>gp untuk preview diff hunk tersebut.
4. Jika sudah yakin, tekan <leader>gs untuk men-stage hunk.
5. Ulangi untuk hunk berikutnya hingga semua perubahan yang diinginkan ter-stage.
6. Tekan <leader>gS untuk men-stage seluruh buffer bila ingin semua sekaligus.
7. Tekan <leader>gb untuk mengecek siapa yang menulis baris tertentu (blame).Tip
Kekuatan stage-hunk dibanding git add .: kalian bisa memisahkan perubahan yang tidak berhubungan di file yang sama. Misalnya satu file berisi perbaikan bug dan penambahan fitur — stage hanya hunk yang relevan untuk commit pertama, lalu commit hunk sisanya. Ini menjaga setiap commit tetap fokus dan riwayat Git tetap bersih — praktik yang sangat dihargai reviewer.
Untuk melihat perbandingan antar commit, antar branch, atau menyelesaikan conflict, diffview.nvim adalah jawabannya. Ia menyediakan file explorer khusus diff plus window split untuk membandingkan.
return {
{
"sindrets/diffview.nvim",
cmd = { "DiffviewOpen", "DiffviewFileHistory", "DiffviewClose" },
keys = {
{ "<leader>gd", "<cmd>DiffviewOpen<CR>", desc = "Buka diff view" },
{ "<leader>gh", "<cmd>DiffviewFileHistory<CR>", desc = "Riwayat file" },
},
opts = {
enhanced_diff_hl = true,
view = {
merge_tool = {
layout = "diff3_mixed",
},
},
},
},
}Perintah-perintah yang akan sering kalian pakai:
| Perintah | Fungsi |
|---|---|
:DiffviewOpen | Diff antara working tree dan HEAD |
:DiffviewOpen <branch> | Diff working tree dengan branch lain |
:DiffviewOpen HEAD~2..HEAD | Diff antar range commit |
:DiffviewFileHistory % | Riwayat commit untuk file aktif |
:DiffviewClose | Tutup panel diff |
:DiffviewToggleFiles | Toggle panel daftar file yang berubah |
Ketika ada conflict, jalankan :DiffviewOpen pada state conflict dan pakai merge_tool layout diff3_mixed — tampilan tiga panel: BASE (kiri), ours (kanan atas), theirs (kanan bawah), dan hasil merge di tengah. Dengan konfigurasi ini, menyelesaikan conflict menjadi visual, bukan membabi-buta membaca <<<<<<< dan >>>>>>> di file mentah.
Caution
Selama resolusi conflict di :DiffviewOpen, jangan lupa bahwa hasil merge harus disimpan ke file yang benar. Diffview menampilkan file hasil merge sebagai buffer yang bisa diedit — pastikan kalian menyelesaikan semua marker (<<<<<<<, =======, >>>>>>>) sebelum menutup view, dan verifikasi dengan :diffoff / :DiffviewClose bahwa tidak ada marker tersisa. Git akan menolak commit jika masih ada conflict marker.
Setelah memahami diff, langkah berikutnya adalah membaca riwayat. Ada tiga cara berbeda untuk menelusuri masa lalu sebuah file — masing-masing menjawab pertanyaan berbeda:
1. <leader>gb → blame 1 baris : "siapa yang menulis BARIS ini?"
2. <leader>gh → :DiffviewFileHistory % : "commit apa saja yang MENYENTUH file ini?"
3. :Git log → fugitive/neogit log : "cerita lengkap branch ini?"Skenario klasik di tim production: sebuah baris timeout = 30 di file config tiba-tiba bermasalah. Kalian letakkan kursor di baris tersebut, tekan <leader>gb, dan langsung tahu — a1b2c3d — John Doe — 2026-07-12 — fix: raise api timeout. Jika butuh konteks lebih luas, buka :DiffviewFileHistory % untuk melihat serangkaian commit yang menyentuh file, atau gunakan :Git log -- <file> untuk daftar commit-nya. Dari posisi di riwayat, tekan Enter pada diffview untuk membuka diff lengkap commit tersebut. Seluruh investigasi berlangsung tanpa berpindah aplikasi.
Note
Di dalam panel diffview, navigasi antar hunk dan file juga memakai keymap Vim yang sudah kalian kenal: ]c / [c untuk berpindah antar hunk dalam diff (ini keymap bawaan Vim untuk change navigation, bukan konflik dengan [h/]h milik gitsigns — keduanya hidup di buffer berbeda). Gunakan :DiffviewToggleFiles untuk melihat daftar file yang berubah, lalu Enter untuk melompat ke file tersebut dalam diff.
Untuk operasi Git yang lebih besar (commit, branch, log, push), kita butuh sebuah git client. Dua opsi paling populer:
Neogit — TUI git client gaya Magit (dari Emacs), dengan antarmuka berpanel yang menampilkan status, diff, log, dan staging dalam satu window:
return {
{
"NeogitOrg/neogit",
dependencies = {
"nvim-lua/plenary.nvim",
"sindrets/diffview.nvim",
},
keys = {
{ "<leader>gg", "<cmd>Neogit<CR>", desc = "Buka Neogit" },
{ "<leader>gc", "<cmd>Neogit commit<CR>", desc = "Commit" },
},
},
}Di dalam Neogit: s untuk stage file/hunk, c untuk commit, p untuk push, l untuk log, ? untuk daftar keymap lengkap.
Fugitive — plugin legendaris karya Tim Pope yang memakai command Ex (:Git), paling populer di ekosistem Vim/Neovim. Keymap dasar yang perlu dihapal:
:Git status
:Git commit
:Git log
:Gdiffsplit " diff file aktif vs index
:Gblame " blame visual per barisNote
Memilih antara neogit dan fugitive soal selera: fugitive terasa "Vim-native" (command Ex, jarang perlu mouse), sedangkan neogit terasa seperti GUI Git karena menampilkan daftar status dengan panel navigasi. Banyak developer memakai keduanya: fugitive untuk operasi cepat, neogit untuk menjelajah status secara visual. Kalian juga bisa mulai dengan keduanya — konfigurasi di atas tidak saling mengganggu.
| Shortcut | Aksi | Plugin |
|---|---|---|
<leader>gs | Stage hunk | gitsigns |
<leader>gr | Reset hunk (batalkan) | gitsigns |
<leader>gp | Preview hunk | gitsigns |
<leader>gS | Stage seluruh buffer | gitsigns |
<leader>gu | Undo stage hunk | gitsigns |
<leader>gb | Inline blame baris kursor | gitsigns |
[h / ]h | Hunk sebelumnya / berikutnya | gitsigns |
<leader>gd | Buka diff view | diffview |
<leader>gh | Riwayat file | diffview |
<leader>gg | Buka Neogit | neogit |
<leader>gc | Buka panel commit | neogit |
| Kesalahan | Gejala | Solusi |
|---|---|---|
| Blame tidak keluar | <leader>gb tidak menampilkan apa-apa | Blame butuh baris aktif — pastikan kursor berada di baris yang memang punya perubahan atau kode |
| Gutter kosong | Tidak ada tanda +/~ padahal file berubah | Pastikan buffer punya file yang benar-benar di-track Git; cek git status; coba buka ulang buffer |
| Merge conflict membingungkan | Banyak <<<<<<< tanpa petunjuk | Gunakan :DiffviewOpen saat conflict dan layout diff3_mixed untuk melihat BASE/ours/theirs |
| Neogit tidak terbuka | Error git tidak ditemukan | Install Git di sistem (sudo apt install git); neogit butuh binary git di PATH |
| Diffview menampilkan file salah | Perbandingan tidak sesuai harapan | Pahami argumen: :DiffviewOpen <range>; tanpa argumen, ia membandingkan dengan HEAD |
| Stage hunk menghilangkan perubahan | Perubahan hilang setelah reset | reset_hunk menghapus perubahan secara permanen — pastikan hunk yang direset memang ingin dibuang, atau lakukan undo (u) jika langsung menyesal |
| Undo tidak bisa mengembalikan hunk | u tidak mengembalikan file | Reset hunk menulis ulang buffer; jika undofile (episode 7) aktif, undo Vim bisa menyelamatkan — selalu aktifkan |
| Diff line highlight aneh | Warna diff tidak jelas | Aktifkan enhanced_diff_hl = true di diffview (sudah di config kita) |
| Performance menurun di repo besar | Gutter terasa lambat di file raksasa | Batasi scope gitsigns (diff_opts) atau matikan untuk buffer tertentu yang sangat besar |
Warning
Kesalahan yang paling berbahaya dan paling sering terjadi: menekan <leader>gr (reset hunk) pada baris yang tidak dimaksudkan. Reset hunk tidak memiliki tombol konfirmasi — perubahan langsung hilang. Selalu preview dengan <leader>gp terlebih dahulu untuk memastikan hunk yang benar, dan pastikan undofile aktif (konfigurasi episode 7) sebagai jaring pengaman terakhir.
Pada episode 18 ini kita telah menghadirkan Git sepenuhnya ke dalam Neovim: gitsigns.nvim dengan indikator tambah/ubah/hapus di gutter, workflow stage-preview-reset hunk, inline blame, hingga navigasi hunk ([h, ]h). Kita juga menguasai diffview.nvim untuk diff antar branch dan resolusi merge conflict dengan layout diff3_mixed, plus dua pilihan git client — neogit dengan UI berpanel dan fugitive dengan command Ex.
Dengan ini, kalian telah menyelesaikan Fase 4: MODERN IDE CAPABILITIES. Neovim kalian sekarang bukan sekadar editor teks — ia memahami kode secara grammar (Treesitter), semantik (LSP), melengkapi secara kontekstual (nvim-cmp), menjaga konsistensi (conform & nvim-lint), dan hidup berdampingan dengan Git (gitsigns & diffview).
Di episode 19 selanjutnya, kita akan masuk ke Fase 5: Advanced Workflow, Productivity & AI, dimulai dengan Integrated Terminal & Task Management menggunakan toggleterm.nvim — menjalankan terminal, lazygit, dan task runner langsung di dalam Neovim. Perjalanan semakin menarik — pastikan tetap semangat!