Git внутри редактора: fugitive, gitsigns и lazygit

Рейтинг: 56.5% · 9 голосов
Исчерпывающий курс по Vim и Neovim: модальное редактирование и грамматика (операторы, движения, текстовые объекты, точка-команда), регистры, метки, макросы, поиск и :substitute, :global, буферы/окна/quickfix, визуальный режим, конфигурация на Lua, маппинги, плагины (lazy.nvim), LSP, автодополнение (blink.cmp), Treesitter, fuzzy-поиск, Git, эргономика и антипаттерны. 34 главы, актуально на 2026 (Vim 9.1, Neovim 0.11/0.12).
Ответить
Аватара пользователя
Roman_Vim
Сообщения: 34
Зарегистрирован: 11 май 2026, 05:31

Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение Roman_Vim »

Оглавление курса (34)
  1. Философия Vim: модальное редактирование и почему это актуально в 2026
  2. Установка и выживание: первый запуск, режимы, как выйти
  3. Перемещение по тексту: движения как основа эффективности
  4. Базовое редактирование: вставка, удаление, копирование
  5. Грамматика Vim: операторы + движения = команды
  6. Текстовые объекты: оперируем структурой, а не символами
  7. Точка-команда и повторяемость: "один штрих, чтобы повторить"
  8. Регистры: продвинутая работа с буфером обмена
  9. Метки и прыжки: навигация по истории перемещений
  10. Поиск: /, ?, *, # и магия паттернов
  11. Замена :substitute и регулярные выражения Vim
  12. Команда :global - оружие массового редактирования
  13. Буферы, окна и вкладки: организация рабочего пространства
  14. Quickfix и location list: пакетная работа по всему проекту
  15. Навигация по файлам: netrw, fuzzy-поиск и проекты
  16. Макросы: автоматизация повторяющихся правок
  17. Визуальный режим и блочное редактирование
  18. Трюки режима вставки
  19. Свёртки, автодополнение и аббревиатуры (встроенные)
  20. Конфигурация с нуля: init.lua и разумные дефолты 2026
  21. Маппинги: leader, which-key и здравые привычки
  22. Скриптинг: основы Vimscript и Lua для Neovim
  23. Менеджеры плагинов: lazy.nvim и lazy-loading
  24. Neovim в 2026: чем отличается и почему выбирают
  25. LSP в Neovim: умные возможности языка
  26. Автодополнение 2026: blink.cmp против nvim-cmp
  27. Treesitter: точная подсветка и структурное редактирование
  28. Fuzzy-поиск: Telescope, fzf-lua и snacks.picker
  29. Git внутри редактора: fugitive, gitsigns и lazygit (вы здесь)
  30. Дистрибутивы, отладка и терминал: быстрый старт и интеграции
  31. Vim повсюду: IDE, браузер и shell
  32. Эргономика и антипаттерны: как не навредить себе и не застрять
  33. Рабочие рецепты, тренажёры и план обучения
  34. Шпаргалка-справочник: все ключевые команды одним списком
Контроль версий - это не отдельное приложение, в которое вы переключаетесь, а слой, который должен жить прямо под курсором. Когда вы пишете код, у вас постоянно крутятся в голове вопросы: "что я здесь изменил относительно HEAD?", "кто и зачем написал эту строку три года назад?", "можно ли закоммитить только вот эти два изменения, а остальное пока оставить?". Если ради ответа на каждый из них приходится сворачивать редактор и идти в терминал - теряется концентрация и темп.

Современный Neovim 2026 закрывает почти весь повседневный git-воркфлоу не выходя из буфера. Ключевая мысль этой главы: не существует одного "правильного" git-плагина. Есть три уровня задач, и под каждый - свой инструмент:
  1. Inline-операции в буфере (знаки изменений, stage/reset отдельного куска, blame под строкой) - это gitsigns.nvim.
  2. Полноценный интерактивный клиент (коммиты, ветки, rebase, разрешение конфликтов, история) - это TUI вроде lazygit/neogit или Ex-команды vim-fugitive.
  3. Ревью диффов и истории - это diffview.nvim и встроенный vimdiff.
Их используют вместе, а не вместо друг друга. Попытка делать rebase знаками gitsigns или искать inline-ханки в lazygit - это работа не тем инструментом. Разберём каждый уровень.

gitsigns.nvim: git прямо в gutter

gitsigns.nvim - стандарт де-факто для работы с git внутри буфера. Он рисует в знаковой колонке (signcolumn, она же "gutter") маркеры напротив каждой изменённой строки: добавленные, изменённые, удалённые. Это первое, что вы видите, открыв файл под контролем версий, - мгновенная карта ваших правок относительно индекса/HEAD.

Но gitsigns - это далеко не только разноцветные палочки слева. Главная его сила в операциях над ханками (hunk - непрерывный блок изменений). Вы можете застейджить, откатить или предпросмотреть конкретный ханк, не трогая остальные, навигировать между изменениями и смотреть blame под текущей строкой.

Два условия, без которых знаков не будет

Прежде чем настраивать маппинги, важно понять, когда gitsigns вообще включается. Это источник самого частого вопроса новичков - "почему нет знаков?".
  • Файл должен лежать в git-репозитории. gitsigns активируется (вызывает on_attach) только если открытый файл находится внутри дерева с .git и отслеживается git. Открыли файл вне репо, в свежей папке без git init или в новом, ещё не добавленном файле - gitsigns молча не подключится: ни знаков, ни маппингов, без всякой ошибки. Это нормальное поведение, а не баг конфига. Быстрая проверка - :Gitsigns toggle_signs или git status в каталоге файла.
  • Включите signcolumn. Знаки рисуются в знаковой колонке. Если оставить дефолт signcolumn=auto, колонка появляется и исчезает по мере возникновения знаков - текст при этом дёргается влево-вправо, gutter "мигает". Поставьте фиксированную колонку, чтобы она была всегда:

Код: Выделить всё

vim.opt.signcolumn = 'yes'   -- колонка зарезервирована всегда, текст не прыгает
Без этого gitsigns технически работает, но визуально раздражает: каждое первое изменение в файле сдвигает весь текст.

Почему это меняет рабочий процесс

Классический git заставляет вас мыслить файлами целиком: git add file.lua берёт в индекс весь файл. Но реальная правка часто смешанная: вы пофиксили баг и заодно подправили форматирование в другом месте. Хочется закоммитить баг отдельно от косметики. В терминале для этого есть git add -p (patch mode), но это интерактивный диалог с y/n/s. Gitsigns даёт то же самое визуально: курсор стоит на ханке - нажали маппинг - ханк ушёл в индекс. Видно ровно то, что происходит.

Базовая навигация и операции

gitsigns не навязывает маппинги по умолчанию - их принято настраивать в колбэке on_attach. Канонический набор (используется в kickstart.nvim и LazyVim) выглядит так:

Код: Выделить всё

Клавиша     |  Действие                        |  Команда gitsigns
------------+----------------------------------+---------------------------
]c          |  следующий ханк                  |  next_hunk
[c          |  предыдущий ханк                 |  prev_hunk
<leader>hs  |  застейджить ханк (stage)        |  stage_hunk
<leader>hr  |  откатить ханк (reset)           |  reset_hunk
<leader>hS  |  застейджить весь буфер          |  stage_buffer
<leader>hR  |  откатить весь буфер             |  reset_buffer
<leader>hu  |  отменить stage ханка (unstage)  |  stage_hunk (тоггл)
<leader>hp  |  предпросмотр ханка (preview)    |  preview_hunk
<leader>hb  |  blame текущей строки (полный)   |  blame_line
<leader>tb  |  тоггл inline-blame              |  toggle_current_line_blame
<leader>hd  |  diff против индекса             |  diffthis
ih / ah     |  текстовый объект "ханк"         |  select_hunk
Навигация ]c/[c - намеренно та же, что у встроенного vimdiff для прыжков между изменениями (см. раздел про vimdiff ниже). Это позволяет ходить по правкам одинаковыми клавишами и в diff-режиме, и в обычном буфере.

Про <leader>hu (unstage) есть тонкость версий. В актуальном gitsigns отдельной функции undo_stage_hunk больше нет - она deprecated и убрана: stage_hunk стал тогглом, то есть повторный вызов на уже застейдженном ханке снимает его со stage. Поэтому в таблице выше <leader>hu маппится на тот же stage_hunk. Но многие конфиги (исторические версии kickstart.nvim и LazyVim) всё ещё ссылаются на gs.undo_stage_hunk - на свежем gitsigns такой маппинг выдаст ошибку "нет такого поля". Если видите её, замените вызов на stage_hunk.

Текстовый объект ханка ih ("inner hunk") - отдельная жемчужина. Он встраивается в грамматику Vim (оператор + объект, подробнее в главе 6): vih выделит ханк визуально, dih удалит, а в связке со stage-маппингом можно стейджить ровно выделенный диапазон в визуальном режиме. Важно понимать: у gitsigns один объект ханка - select_hunk. У ханка нет "окружения", поэтому реального различия inner/around (как у скобок или тегов) тут не существует. По соглашению select_hunk обычно вешают сразу на оба обозначения - и ih, и ah, - чтобы объект срабатывал с любым оператором независимо от привычки писать i или a; но это один и тот же ханк, а не две разные семантики.

Практика: разбираем смешанные правки

Код: Выделить всё

Состояние: вы отредактировали две функции в одном файле.
Ханк 1 (строки 10-12) - фикс бага, хотим закоммитить.
Ханк 2 (строки 40-45) - эксперимент, пока трогать не надо.

Курсор где-то вверху файла.

Нажимаем ]c          -> курсор прыгает на ханк 1 (строки 10-12)
Нажимаем <leader>hp  -> всплывает окно предпросмотра: видим diff ханка
Нажимаем <leader>hs  -> ханк 1 уходит в индекс, знаки слева гаснут
Нажимаем ]c          -> курсор на ханке 2 (строки 40-45)
                        его НЕ трогаем

Теперь в индексе только фикс бага. Идём коммитить (через fugitive
или lazygit - см. ниже) - закоммитится ровно ханк 1.
Частичный stage внутри ханка тоже возможен: выделите нужные строки в визуальном режиме и вызовите stage_hunk - застейджится только выделение, а не весь ханк. Это прямой аналог git add -p с возможностью s (split), только нагляднее.

Blame: кто и зачем

toggle_current_line_blame включает виртуальный текст в конце текущей строки: автор, дата и сообщение коммита, который последним её менял. Это "летающая" подсказка - она следует за курсором и не засоряет файл. Для подробностей (<leader>hb) открывается полный blame конкретной строки с возможностью прыгнуть в сам коммит.

Код: Выделить всё

set: vim.b.gitsigns_blame_line_dirty показывает, что строка не закоммичена

Курсор на строке 42.
<leader>tb -> в конце строки появляется:
              " Alice, 3 months ago - refactor auth flow"
Двигаем курсор на строку 50 ->
              " Bob, 2 years ago - initial commit"
База сравнения: не только индекс

По умолчанию gitsigns показывает знаки относительно индекса (staged-версия файла): отредактировали строку - появился знак, застейджили ханк - знак погас. Но базу сравнения можно сменить на произвольную ревизию командой :Gitsigns change_base:

Код: Выделить всё

:Gitsigns change_base HEAD~3       -- знаки = дифф против коммита 3 шага назад
:Gitsigns change_base main         -- дифф текущего файла против ветки main
:Gitsigns change_base HEAD~3 true  -- 2-й аргумент true = глобально для всех буферов
:Gitsigns change_base              -- без аргумента вернуть базу к индексу
Это превращает gutter в живую карту "что я наменял в этой ветке относительно main", а не только "что ещё не застейджено". Полезно перед оформлением PR: пройтись ]c/[c по знакам с базой main.. и увидеть весь вклад ветки прямо в редактируемом файле. (Похожую задачу для нескольких файлов решает :DiffviewOpen main..HEAD - см. раздел про diffview.)

vim-fugitive: git как Ex-команды

vim-fugitive от Tim Pope - старейший и самый "вимовый" git-плагин. Его философия противоположна TUI: git здесь - это набор Ex-команд, а его статус-окно встроено в модель буферов и окон Vim. В 2026 fugitive ушёл в нишу для тех, кому ближе Ex-команды и кто хочет, чтобы git подчинялся той же грамматике, что и весь редактор. Но эта ниша устойчивая: fugitive невероятно мощный и отлично работает там, где TUI избыточен.

Центральная команда: :Git

:Git (можно сокращать до :G) без аргументов открывает окно статуса - интерактивный аналог git status. Это не просто текст: внутри работают маппинги.

Код: Выделить всё

Клавиша (в окне :Git)  |  Действие
-----------------------+-------------------------------------------
s                      |  застейджить файл/ханк под курсором
u                      |  unstage (убрать из индекса)
-                      |  тоггл stage/unstage
=                      |  развернуть inline-diff файла под курсором
X                      |  откатить (discard) изменение
cc                     |  создать коммит (:Git commit)
ca                     |  commit --amend
dd / dv                |  открыть diff файла (split/vertical)
<CR>                   |  открыть файл под курсором
gq / q                 |  закрыть окно статуса
Любую git-команду можно вызвать напрямую: :Git push, :Git rebase -i HEAD~3, :Git log --oneline. Fugitive прозрачно прокидывает аргументы в git и красиво показывает вывод. Интерактивный rebase (-i) открывается прямо в Neovim как обычный буфер todo-листа.

:Git blame - навигируемый blame

:Git blame открывает вертикальный сплит-аннотацию слева от файла: каждая строка подписана коммитом, автором и датой. В отличие от inline-blame gitsigns, это полноэкранный навигируемый blame для глубокого расследования истории.

Код: Выделить всё

Клавиша (в окне blame)  |  Действие
------------------------+-----------------------------------------------------
<CR>                    |  открыть коммит этой строки
o / O                   |  открыть коммит в сплите / новой вкладке
~                       |  blame на родительском коммите (шаг назад в историю)
q                       |  закрыть
Приём ~ бесценен: вы видите, что строку трогал коммит-рефакторинг, жмёте ~ и смотрите, как она выглядела ДО него, - и так шаг за шагом до первоисточника изменения.

:Gdiffsplit - трёхпанельное разрешение и сравнение

:Gdiffsplit открывает текущий файл в режиме vimdiff против индекса (или против произвольной ревизии: :Gdiffsplit HEAD~2). Слева - версия из git, справа - ваш рабочий файл. Дальше работают все возможности vimdiff: навигация ]c/[c, перенос изменений do (diff obtain) и dp (diff put).

Во время merge-конфликта :Gdiffsplit! (с восклицательным знаком) открывает трёхпанельный вид: слева "наша" версия (//2), справа "их" (//3), а в центре - файл с маркерами конфликта. Из боковых панелей переносите нужные куски в центр через :diffget //2 или :diffget //3.

Важно: //2 и //3 - это нотация самого fugitive, а не свойство голого vimdiff. За ней стоят имена буферов вида fugitive://.../2/ (наша сторона, :2) и fugitive://.../3/ (их сторона, :3), и :diffget принимает их как часть имени буфера. В чистом vimdiff (без fugitive) такого синтаксиса нет - там источник указывают номером буфера: :diffget {bufnr}, например :diffget 3 (номера смотрите по :ls).

Код: Выделить всё

Конфликт слияния в config.lua. Открываем файл, видим <<<<<<< ======= >>>>>>>

:Gdiffsplit!     -> три окна: //2 (наше) | рабочий | //3 (их)
Курсор в центре на конфликтном ханке.
:diffget //3     -> подтягиваем "их" версию ханка
]c               -> следующий конфликтный ханк
:diffget //2     -> для него берём "нашу" версию
:Gwrite          -> записать результат и застейджить (=git add)
Связанные команды fugitive: :Gwrite (записать файл и застейджить, аналог :w+git add), :Gread (восстановить файл из индекса, аналог checkout), :Gedit для открытия произвольной ревизии файла.

lazygit и neogit: полноценные TUI-клиенты

Когда задача выходит за рамки "застейджить ханк" - интерактивный rebase, перенос коммитов, работа с ветками и стешами, разрешение десятка конфликтов - нужен полноценный git-клиент. Здесь два лидера 2026 года: lazygit и neogit.

lazygit

lazygit - самостоятельный TUI-инструмент на Go, не зависящий от Neovim. Это его главное преимущество: один и тот же интерфейс работает и внутри редактора (во встроенном терминале), и в чистом терминале на сервере. Это самый популярный git-TUI в принципе.

В Neovim его открывают во встроенном терминале (см. главу 30 про терминал). Самый удобный способ в 2026 - через snacks.nvim:

Код: Выделить всё

-- через snacks.nvim (folke)
vim.keymap.set('n', '<leader>gg', function()
  require('snacks').lazygit()
end, { desc = 'Lazygit' })
Альтернатива - плагин toggleterm.nvim с предустановленным терминалом под lazygit. Внутри lazygit панели переключаются по Tab/числам, Space стейджит, c коммитит, P пушит, i - интерактивный rebase. Преимущество snacks.lazygit в том, что он автоматически передаёт текущую тему и конфиг и умеет открывать редактируемые файлы прямо в вашем Neovim, а не во вложенном.

neogit

neogit - это клон Magit из Emacs, написанный на нативном Lua с UI прямо из попапов и буферов Neovim. В отличие от lazygit, он не запускает внешний процесс - всё происходит в родных окнах редактора, что даёт более тесную интеграцию (общие маппинги, единый стиль, интеграция с diffview.nvim для просмотра диффов).

Код: Выделить всё

-- neogit + diffview
{
  'NeogitOrg/neogit',
  dependencies = { 'nvim-lua/plenary.nvim', 'sindrets/diffview.nvim' },
  cmd = 'Neogit',
  keys = { { '<leader>gn', '<cmd>Neogit<cr>', desc = 'Neogit' } },
}
:Neogit открывает статус-буфер. Маппинги в духе Magit: s/u - stage/unstage, c открывает попап коммита (cc - закоммитить, ca - amend), p - попап pull, P - push, b - ветки, r - rebase, Z - стеши. Каждое действие - это попап с подсказками доступных опций, что делает neogit самодокументируемым.

Что выбрать

Код: Выделить всё

                       |  lazygit           |  neogit
-----------------------+--------------------+------------------------
Реализация             |  внешний TUI (Go)  |  нативный Lua UI
Работает вне Neovim    |  да                |  нет
Интеграция с буферами  |  через терминал    |  родная
Интеграция diffview    |  нет               |  да
Зависимости            |  бинарь lazygit    |  plenary, опц. diffview
Practicalli Neovim в 2026 рекомендует связку neogit + diffview как основной интерактивный клиент. Но lazygit остаётся прагматичным выбором №1 за счёт переносимости: вы учите один интерфейс и используете его везде. fugitive при этом не конкурент TUI напрямую - он для тех, кто мыслит Ex-командами.

diffview.nvim: ревью как в pull request

diffview.nvim - это инструмент именно для ревью: детального просмотра диффов и истории. Если gitsigns показывает ваши локальные правки, а fugitive/TUI - управляют коммитами, то diffview даёт обзорный взгляд "что изменилось между двумя точками" в формате, похожем на интерфейс PR на GitHub.

Код: Выделить всё

Команда                      |  Что показывает
-----------------------------+---------------------------------------------------------------
:DiffviewOpen                |  все незакоммиченные изменения (рабочее дерево vs индекс/HEAD)
:DiffviewOpen HEAD~3         |  дифф рабочего дерева против коммита 3 шага назад
:DiffviewOpen main..feature  |  дифф между ветками
:DiffviewFileHistory %       |  история изменений текущего файла
:DiffviewFileHistory         |  история всего репозитория (как git log с диффами)
:DiffviewClose               |  закрыть
Слева - список файлов с изменениями, справа - двухпанельный diff выбранного файла. Вы навигируете по файлам, как по changeset в ревью, и видите каждое изменение в контексте. :DiffviewFileHistory % особенно полезен: это таймлайн правок конкретного файла, по которому можно листать коммиты один за другим, наблюдая эволюцию кода. Внутри diffview работает тот же stage/unstage по файлам и ханкам, так что им можно не только смотреть, но и собирать коммит.

Именно поэтому neogit идёт в связке с diffview: neogit управляет операциями, а diffview обеспечивает качественный просмотр того, что эти операции затрагивают.

Встроенный vimdiff и :diffthis

Под всеми diff-плагинами лежит встроенный движок diff Vim/Neovim. Понимать его полезно, потому что он работает без единого плагина - например, на голом сервере, куда вы зашли по SSH (стратегия "Vim на серверах" из главы 24).

Запустить diff можно несколькими способами:
  • Снаружи: nvim -d file1 file2 (или vimdiff file1 file2).
  • Изнутри: открыть два окна и в каждом выполнить :diffthis. Чтобы выключить - :diffoff.
  • Перечитать diff после правок - :diffupdate.
Изменённые строки подсвечиваются, одинаковые сворачиваются в фолды. Команды работы с diff:

Код: Выделить всё

Клавиша/команда  |  Действие
-----------------+-----------------------------------------------------
]c               |  следующее изменение
[c               |  предыдущее изменение
do               |  diff obtain - взять изменение из другого окна СЮДА
dp               |  diff put - отправить изменение ОТСЮДА в другое окно
:diffget         |  то же что do, но командой (нужно при 3+ окнах)
:diffput         |  то же что dp командой
zo / zc          |  развернуть/свернуть фолд контекста
Мнемоника: do = obtain (получить к себе), dp = put (положить туда). При двух окнах хватает do/dp; при трёх (как в merge-конфликте через fugitive) нужны явные :diffget {bufnr} - например :diffget 3, - потому что Vim не знает, из какого именно окна брать. Узнать номера буферов можно командой :ls.

Для истории правок текущего файла встроенного дерева undo в ядре нет, но есть навигация по веткам undo: :earlier 5m откатывает на состояние пятиминутной давности, :later идёт вперёд, g-/g+ шагают по веткам undo. Если включить персистентный undo (set undofile), история переживает перезапуск. За визуальным деревом undo-веток ставят внешний плагин mbbill/undotree (:UndotreeToggle) - в ядре Neovim такого инструмента нет.

Типовой git-воркфлоу в редакторе 2026

Соберём всё в один связный цикл - как это выглядит на практике за один рабочий заход:

Код: Выделить всё

1. Пишете код. gitsigns рисует знаки изменений в gutter - постоянная
   обратная связь, что вы наменяли относительно HEAD.

2. ]c / [c - прыгаете между ханками, <leader>hp - предпросмотр.
   Сомнительный кусок откатываете <leader>hr (reset_hunk).

3. Собираете коммит по смыслу: <leader>hs на нужных ханках
   (или визуальное выделение + stage для частичного ханка).
   Косметику и эксперименты пока НЕ стейджите.

4. Коммитите интерактивным клиентом:
   - <leader>gg -> lazygit, либо
   - :Neogit -> попап коммита, либо
   - :Git -> cc в fugitive.
   Пишете осмысленное сообщение, при необходимости amend.

5. Ревьюите перед пушем: :DiffviewOpen - пробегаете изменения
   как PR, ловите забытый debug-print.

6. Конфликт после pull? :Gdiffsplit! (fugitive) -> :diffget //2 / //3
   (нотация fugitive) или голый vimdiff -> :diffget {bufnr};
   разрешаете, :Gwrite.

7. Расследование "почему так": <leader>tb (inline blame) для
   быстрого взгляда, :Git blame + ~ для глубокого погружения,
   :DiffviewFileHistory % чтобы пролистать эволюцию файла.

8. Push: P в lazygit/neogit или :Git push.
Заметьте разделение ролей: gitsigns не покидает буфер (шаги 1-3), интерактивный клиент берёт на себя коммиты/ветки (шаг 4), diffview - ревью (шаг 5), а blame/история - расследование (шаг 7).

Лучшие практики 2026
  • Разделяйте задачи между плагинами осознанно. Каноническая связка 2026: gitsigns для inline-операций в буфере + один полноценный клиент (neogit или lazygit) для сложных операций. gitsigns не делает rebase и не разрешает конфликты деревом, а TUI не дают inline-ханков под курсором. Используйте их вместе.
  • gitsigns + lazygit - самый прагматичный набор для большинства. lazygit - отдельный TUI, не зависящий от Neovim, поэтому навык переносится на серверы и в чистый терминал. Открывайте его через snacks.lazygit (часть snacks.nvim) - он передаёт тему и умеет открывать файлы в текущем Neovim, а не во вложенном.
  • neogit + diffview.nvim - если хотите всё нативно в Lua. Practicalli Neovim в 2026 рекомендует именно эту связку: neogit управляет операциями попапами в стиле Magit, diffview обеспечивает качественный просмотр диффов и истории.
  • fugitive - для тех, кому ближе Ex-команды. Не считайте его "устаревшим": для :Gdiffsplit при разрешении конфликтов и навигируемого :Git blame с шагами ~ по истории он по-прежнему один из лучших. Просто это другая парадигма - git как продолжение командной строки Vim.
  • Стейджите ханками, а не файлами. Главная ценность gitsigns - атомарные коммиты по смыслу. Привыкайте к циклу ]c -> <leader>hp -> <leader>hs, а не к git add ..
  • Используйте :DiffviewOpen как обязательный pre-push ритуал. Беглый просмотр всего changeset перед пушем ловит забытые print/console.log и случайно застейдженные файлы лучше, чем git status.
  • Знайте голый vimdiff. На сервере без плагинов :diffthis/do/dp и ]c/[c спасают. Это та же навигация, что у gitsigns, - мышечная память переносится.
Частые ошибки
  • Путать роли плагинов. Ожидать от gitsigns rebase, а от lazygit - inline-ханков под курсором. Это разные уровни; инструменты дополняют друг друга, а не заменяют.
  • do/dp наоборот. В vimdiff do (obtain) тянет изменение к себе, dp (put) отправляет от себя. Перепутав направление, легко затереть не ту версию. Мнемоника: "o - ко мне, p - от меня".
  • :diffget без указания буфера при трёх окнах. В трёхпанельном merge Vim не угадает источник - нужно явно указать, откуда брать. Через fugitive (:Gdiffsplit!) это его нотация :diffget //2 (наше) или :diffget //3 (их); в голом vimdiff - номер буфера, например :diffget 3 (номера по :ls). Без указателя получите ошибку или возьмёте не ту сторону.
  • Стейджить файл целиком, когда правки смешанные. git add file или stage_buffer тащит в индекс и баг-фикс, и эксперимент. Для чистой истории стейджите ханками (<leader>hs) или частями ханка через визуальное выделение.
  • Забыть :Gwrite/сохранение после разрешения конфликта. Разрешили конфликт в diff-окнах, но не записали результат - git по-прежнему считает файл конфликтным. :Gwrite пишет файл И стейджит его.
  • Не настроить on_attach у gitsigns и удивляться, что маппингов нет. gitsigns намеренно не вешает клавиши по умолчанию. Без колбэка on_attach (или явных keys) у вас будут только знаки в gutter, но не операции над ханками.
  • Ждать знаков вне git-репозитория. gitsigns молча не активируется, если файл не в дереве с .git (или ещё не отслеживается git). Нет знаков и не работают маппинги - первым делом проверьте, что вы внутри репо (git status), а не то, что "сломался конфиг".
  • Оставить signcolumn=auto и страдать от дёрганья текста. Без set signcolumn=yes колонка появляется только когда есть знаки, и текст прыгает при каждом первом изменении в файле. Зарезервируйте колонку постоянно.
  • Запускать вложенный редактор внутри lazygit. Если открыть lazygit без snacks/правильной интеграции, команда редактирования (e в lazygit) может запустить ещё один Neovim внутри терминала. snacks.lazygit решает это, открывая файл в вашем текущем экземпляре.
Упражнения
  1. Атомарный коммит. Внесите в один файл две независимые правки в разных местах. С помощью ]c/[c найдите ханки, через <leader>hp просмотрите каждый, застейджите <leader>hs только первый, и закоммитьте его (через :Git, :Neogit или lazygit). Убедитесь по git status, что второй ханк остался незакоммиченным.
  1. Частичный ханк. Создайте ханк из 5 изменённых строк. Выделите визуально 2 из них и застейджите выделение через stage_hunk. Проверьте :DiffviewOpen, что в индекс ушли ровно две строки.
  1. Blame-расследование. Откройте любой файл из реального репозитория, включите inline-blame (<leader>tb), найдите строку с интересным изменением. Затем откройте :Git blame, прыгните на её коммит через <CR> и пройдите на шаг назад в истории клавишей ~.
  1. Голый vimdiff. Сделайте копию файла, измените в ней пару строк. Откройте обе версии и в каждом окне выполните :diffthis. С помощью ]c пройдите по различиям и перенесите одно изменение командой do, а другое - dp. Затем выключите режим через :diffoff.
  1. Ревью changeset. Сделайте 2-3 коммита в ветке. Выполните :DiffviewOpen main..HEAD (подставьте свою базовую ветку) и пройдите по списку файлов, как по pull request. Найдите изменение, которое стоило бы вынести в отдельный коммит.
  1. История файла. Откройте :DiffviewFileHistory % на файле с богатой историей. Пролистайте коммиты от свежих к старым и проследите, как менялась одна конкретная функция.
Главное из главы
  • Git-интеграция в Neovim делится на три уровня, под каждый свой инструмент: gitsigns (inline в буфере), lazygit/neogit/fugitive (интерактивный клиент), diffview (ревью). Их используют вместе.
  • gitsigns.nvim даёт знаки в gutter, навигацию ]c/[c, stage/reset/preview ханка, inline-blame и текстовый объект ханка (select_hunk, обычно на ih/ah). Активируется только внутри git-репо; для стабильного gutter нужен signcolumn=yes. База сравнения по умолчанию - индекс, но меняется на любую ревизию через :Gitsigns change_base. Это инструмент атомарных коммитов по смыслу.
  • vim-fugitive делает git Ex-командами: :Git (статус с маппингами s/u/cc), :Git blame (навигируемый, с шагом ~ в историю), :Gdiffsplit! (трёхпанельное разрешение конфликтов), :Gwrite/:Gread.
  • lazygit - переносимый TUI вне зависимости от Neovim (открывать через snacks.lazygit); neogit - нативный Lua-клон Magit в связке с diffview. Practicalli рекомендует neogit+diffview, но lazygit прагматичнее за счёт переносимости.
  • diffview.nvim - ревью в стиле pull request: :DiffviewOpen, сравнение веток, :DiffviewFileHistory %.
  • Под всем лежит встроенный vimdiff: :diffthis/:diffoff, навигация ]c/[c, перенос do (obtain, к себе) / dp (put, от себя), а в 3+ окнах - явный :diffget {bufnr} (номера по :ls); нотация :diffget //2///3 - это уже fugitive, а не голый vimdiff. Работает без плагинов - незаменимо на серверах.
  • Типовой воркфлоу 2026: пишем -> стейджим ханки gitsigns -> коммитим клиентом -> ревьюим diffview перед пушем -> разбираем конфликты через diff-окна -> расследуем историю blame.
👍4 ❤️1 🔥1 😄 🤔
✔ Лучший ответ сформирован автоматически — joelog
Roman_Vim писал(а):В актуальном gitsigns отдельной функции undo_stage_hunk больше нет - она deprecated и убрана вот на этом и споткнулся, тащил старый конфиг с кикстарта и получал ошибку про нет такого поля на hu. Заменил на stage_hunk и всё, тоггл работает. Кому актуально - не ищите undo_stage_hunk, его правда нет.
Перейти к ответу →
Аватара пользователя
larrydallas
Сообщения: 1
Зарегистрирован: 31 май 2026, 10:29

Re: Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение larrydallas »

О, наконец дошло почему у меня знаков не было в одном проекте - открывал файл в папке где забыл git init. Думал конфиг gitsigns поломал, а оно просто молча не цепляется. Спасибо, теперь первым делом git status проверяю.
👍 ❤️1 🔥 😄 🤔
Аватара пользователя
seniorsegfault
Сообщения: 1
Зарегистрирован: 24 май 2026, 16:02

Re: Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение seniorsegfault »

Поделюсь маппингом который мне зашёл: <leader>hp на preview, и сразу <leader>hs если ок. По привычке ещё ]c crtl ходил, но текстовый объект ih оказался удобнее - vih выделил, глянул, и стейджу выделение если не весь ханк нужен.
👍1 ❤️1 🔥 😄 🤔1
Аватара пользователя
joelog
Сообщения: 1
Зарегистрирован: 19 май 2026, 12:39

Re: Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение joelog »

✔ Лучший ответ — сформирован автоматически
Roman_Vim писал(а):В актуальном gitsigns отдельной функции undo_stage_hunk больше нет - она deprecated и убрана
вот на этом и споткнулся, тащил старый конфиг с кикстарта и получал ошибку про нет такого поля на <leader>hu. Заменил на stage_hunk и всё, тоггл работает. Кому актуально - не ищите undo_stage_hunk, его правда нет.
👍3 ❤️ 🔥 😄 🤔
Аватара пользователя
roman5
Сообщения: 1
Зарегистрирован: 13 май 2026, 22:20

Re: Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение roman5 »

а можно вопрос про change_base. если я сделал :Gitsigns change_base main а потом застейджу ханк - он в индекс уйдёт относительно main или относительно индекса? чёт запутался какая база для самого stage используется когда базу сравнения сменил
👍1 ❤️ 🔥1 😄 🤔1
Аватара пользователя
dev_sergey
Сообщения: 1
Зарегистрирован: 03 июн 2026, 00:53

Re: Git внутри редактора: fugitive, gitsigns и lazygit

Сообщение dev_sergey »

коротко - связка gitsigns + lazygit через snacks огонь, тему сама подхватывает и файл в текущем нвиме открывает а не вложенный. до этого мучался с toggleterm и вложенным редактором.
👍1 ❤️1 🔥2 😄 🤔
Ответить
← Предыдущая глава
Fuzzy-поиск: Telescope, fzf-lua и snacks.picker
Следующая глава →
Дистрибутивы, отладка и терминал: быстрый старт и интеграции

Все главы курса «Vim и Neovim: модальное редактирование от основ до современного Neovim»

Поделиться темой: ✈ Telegram VK

Вернуться в «Vim и Neovim: модальное редактирование от основ до Neovim 2026»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость