neovimから抜けずにgit commitをしたい

やりたいこと

neovimでファイルを編集していると, 作業がひと段落ついたタイミングなどでgit commitをしたい時があります。他にも誰によって追加されたコードなのかを確認したり, リモートで変更されたコードをローカルに取り込んだり, 開発作業中にもgit操作は欠かせません。

これらの作業は本来gitコマンドによってなされるので, neovim上ではなくターミナル上で行われるのが通常です。したがってこれらの作業をする際には毎回neovimを終了させてターミナルに戻ったり, neovim内でターミナルを起動させたりしてから, gitコマンド操作を行うしかありませんでした。 しかし, たかが一つ二つのgitコマンドを実行したいだけのためにわざわざエディタを終了させたりターミナル起動させるのは面倒くさいです。

そういうわけで, neovimで編集中の画面を抜けずにgitの操作を行うことができるのが今回の目標です。 vim上でgitを操作することを便利にしてくれるプラグインを紹介し, 僕が使用しているカスタマイズもお伝えします。

vimでgit操作をいい感じにしてくれるプラグイン

vimでgit操作をするためにいろいろいい感じにしてくれるプラグインは複数あるのですが, 僕が以下の二つを使用しています。 大きく分けてfugitive.vimでは具体的なgitコマンドの操作するため, vim-gitgutterではファイル単位やより細かい単位での差分を確認するために使用しています。

fugitive.vim

fugitive.vimのリポジトリ fugitive.vimはvim上でgitを便利に扱えるようにするプラグインです。名前の由来などは公式リポジトリを見るとわかります。

fugitive.vimはvimのターミナルモードにおいて:Gitコマンドを提供することでgitの操作を行いやすくしています。これは一見ターミナルモードで外部コマンドを呼び出すやり方でgitを操作する:!gitと同じように感じられますが, fugitive.vimではよりvimと一緒に使いやすくなる機能を:Gitに盛り込んでいます。

今回の記事でもメインで紹介するのはこのプラグインになります。

アップデートで以前の設定が使えなくなりました

2020年の2月頃に行われた変更:Gblameなど多くのコマンドが変更になりました。それ以前に書かれている記事の設定を参照しても動かないことが考えられるので, 他の記事を見る際は注意してください。

具体的な変更はドキュメントのDEPRECATIONSの項に詳しく書いてあるのでそちらを参照してください。

vim-gitgutter

vim-gitgutterはvimのバッファ内でgit diffの内容を表示してくれるプラグインです。どの行が追加, 修正, 削除されたかなどを表示してくれます。 また, ハンク単位でgitのstage設定にあげたりなどの操作も提供してくれています。

fugitive.vimが全体的なgitコマンドの操作を提供するのに対して, vim-gitgutterではハンク単位というより細かい単位での操作をやりやすくしてくれています。

導入方法

僕の設定ではdein.vimを使用してプラグインを管理しているので, それに準拠した導入方法を紹介します。 neovimで使えるプラグインマネージャーはvim-plugなど他にもあるので, 他のものを使っている方は適宜読み替えてください。

deinに読み込んで欲しいプラグインを記入するファイルdein.tomlには以下のように二つのプラグイン名を記入しています。 hook_sourceの部分ではそれぞれのプラグインごとの設定ファイルを別ファイルに分けて記入しているのでここではパスだけ通しています。

~/.config/nvim/dein.toml
[[plugins]]
repo = 'tpope/vim-fugitive'
hook_source = '''
source ~/.config/nvim/plugins/fugitive.vim
'''

[[plugins]]
repo = 'airblade/vim-gitgutter'
hook_source = '''
source ~/.config/nvim/plugins/gitgutter.vim
'''

各プラグインは基本的にノーマルモードにいる時に動かすようにしています。 インサートモードにいるタイミングではファイルを編集しているところなので、ある程度編集を終えてインサートモードを抜けたタイミングでgitを操作したいという意図があります。

例えばノーマルモードでgsとタイプすると, 現在のプロジェクトのgit satusのようなものが新規バッファとして立ち上がりデフォルトでは下側のスプリットウィンドウ上に表示されます。 このバッファはfiletypeがfugitiveに設定されており, このバッファないではfugitive専用のキーバインドもいくつか定義されています。例えばunstagedなファイルにカーソルを移動させてsをタイプするとgit stage .と同等な編集したファイルをstage環境にあげることができる。 ただ, この設定ではgaとタイプするだけで同様に編集したファイルをstage環境にあげられるようにしてあります。

~/.config/nvim/plugin/fugitive.vim
nnoremap <silent> gs :Git<CR>
nnoremap <silent> gps :Git push<CR>
nnoremap <silent> gpl :Git pull<CR>
nnoremap <silent> gc :Git commit<CR>
nnoremap <silent> gb :Git blame<CR>
nnoremap <silent> ga :Git add -A<CR>

vim-gitgutterは先ほども軽く説明した通り, より小さい範囲であるHunk(git上では一編集箇所という意味)をそれぞれ個別に操作するためのプラグインです。 細かい単位ごとに細かくstage環境にあげたい時は,shでできるように設定しています。

~/.config/nvim/plugin/vim-gitgutter.vim
set signcolumn=yes
set updatetime=1000
nmap <silent> <Leader>nh <Plug>(GitGutterNextHunk)
nmap <silent> <Leader>ph <Plug>(GitGutterPrevHunk)
nmap <silent> <Leader>uh <Plug>(GitGutterUndoHunk)
nmap <silent> <Leader>vh <Plug>(GitGutterPreviewHunk)
nmap <silent> <Leader>sh <Plug>(GitGutterStageHunk) 

また, 僕の設定では通常\(バックスラッシュ)に割り当てられている<Leader>,(コンマ)に割り当てて、指の移動距離を少なくする工夫を追加。 この部分はShougoさんの設定ファイルを参考にしました。

~/.config/nvim/init.vim
" Use ',' instead of '\'.
" Use <Leader> in global plugin.
let g:mapleader = ','

使用感, おすすめ機能

個人的におすすめな機能なのは:Git blameです。 gbをタイプすることで画面左側にコミットログとともに誰がどの部分を編集したかが表示されるようになっているので, チームで開発していてコードについてわからないことが会った時に誰に聞けばいいかすぐにわかるのが便利。

また, fugitiveの専用バッファでもできることが多いので, 細かくやりたい動作を実行する子ことができます。

About the author

日本の大学を休学してスノーボードするためにノルウェーで1年間生活。腰椎分離症になってしまったため、現在は様子を見ながらニセコで滑っています。プロでもなんでもないですが、行けるとこまで行ってやろうと毎日滑ってます