VimでGitも爆速編集

このエントリーをはてなブックマークに追加

QiitaにVSCodeでのGitの基本操作まとめなる記事が上がっていたので対抗してVimで快適にGitを編集する設定を書きます

プラグインのインストール

[[plugins]]
repo = 'airblade/vim-gitgutter'
[[plugins]]
repo = 'tpope/vim-fugitive'

vim-gitgutterは変更があった行を左端に表示してくれます。

Screenshot

実はこれ以外にも便利機能があるのでそれも紹介します。

更新が反映されるまでの時間を短くしたいのでそれも設定しておきましょう。下の設定だと100msになります。

set updatetime=100

vim-fugitiveはGitコマンドをVim内でも使えるようにしてくれる便利なやつです。これも今から解説していきます。

プラグインの解説

vim-gitgutter

vim-gitgutterは行ごとの変更内容を表示してくれるプラグインですが、 hunk と呼ばれる「変更のカタマリ」ごとに変更を管理することもできます1

(事前2に設定していない場合は)次のようなマッピングが自動でつけられます。

nmap <Leader>hs <Plug>GitGutterStageHunk
nmap <Leader>hu <Plug>GitGutterUndoHunk
nmap <Leader>hp <Plug>GitGutterPreviewHunk
nmap ]c         <Plug>GitGutterNextHunk
nmap [c         <Plug>GitGutterPrevHunk
omap ic         <Plug>GitGutterTextObjectInnerPending
omap ac         <Plug>GitGutterTextObjectOuterPending
xmap ic         <Plug>GitGutterTextObjectInnerVisual
xmap ac         <Plug>GitGutterTextObjectOuterVisual

hunkの管理(上3行で設定されている)

GitGutterStageHunk, GitGutterUndoHunk, GitGutterPreviewHunkはそれぞれ、変更のカタマリをstage、undo、(変更前の状態と)比較するコマンドです。

自分の<Leader>キーの位置が不便な人は各自

nmapあなたのやりたいマッピング<Plug>GitGutterStageHunk

のように設定してもいいでしょう。

もしくは<Leader>キー自体を事前2に変更するのもアリですね。例えば自分は下のようにして<Leader>キーをスペースキーにしている……

let mapleader = "\<Space>"

……ので、上3つは<Space>hsなどで発動します。

hunk間の移動

残りはhunk間を移動したり選択したりするコマンドですね。

]c, [cでそれぞれ次の/前のhunkに移動します。

ac, icでhunkを囲むテキストオブジェクトになります。acの方は後ろの空行も含みます。
例えば、vicでhunk内を選択したり、cacでhunkとその後ろの空行を削除して編集したりできます。

vim-fugitive

こちらは短いマッピングを自動でつけてくれたりはせず、:Gwriteみたいにコマンドが登録されるようになっています。
でもいちいちコマンドを打ちたくはないので、いい感じに設定しましょう。自分の設定を参考までに貼っておきます。

nnoremap <leader>gs :tab sp<CR>:Gstatus<CR>:only<CR>
nnoremap <leader>ga :Gwrite<CR>
nnoremap <leader>gc :Gcommit<CR>
nnoremap <leader>gb :Gblame<CR>
nnoremap <leader>gl :Git log<CR>
nnoremap <leader>gh :tab sp<CR>:0Glog<CR>
" abbrev for `git history`: create new quickfix tab for history
nnoremap <leader>gp :Gpush<CR>
nnoremap <leader>gf :Gfetch<CR>
nnoremap <leader>gd :Gvdiff<CR>
nnoremap <leader>gr :Grebase -i<CR>
nnoremap <leader>gg :Ggrep 
nnoremap <leader>gm :Gmerge 

(先程書いたように、自分の環境では<Leader><Space>に置き換えられているためこのような書き方になっています。各自自分の好きなようにいじってください)

上から順に解説していきますね。

<leader>gs

git statusが新しいタブにフルスクリーンで出てきます3。この中では専用のキーマッピングが使えるようになっています(詳しくは:h fugitive-mappingsを見てください)。 重要なものを解説すると、

マッピング 効果
s ステージ(add)する
u ステージしたものを取り除く(undo)
= diffをその場に開く・閉じる
dv 変化の見やすい、いい感じのdiffを出す(すごく見やすいのでお試しあれ)
<Enter> 編集する
X 変更を取り消す

それが終わったらコミットしましょう。

マッピング 効果
cc コミットする
ca 直前のコミットを変更する形でコミットする(git commit --amend)
ce 直前のコミットを変更する形でコミットするただし、コミットメッセージを変更しない(git commit --amend --no-edit)
cw 直前のコミットのコミットメッセージのみを変更する
cvc verboseモードでコミットする(git commit -v)
cf fixup!でコミットする(git commit --fixup=)これを実行して直後に<Tab><Enter>をおすとHEADにfixupする

<leader>ga

このファイルをgit addします。

<leader>gc

git commitします。

<leader>gb

git blameします。行ごとに最後にコミットされたのはいつなのか・誰なのか一覧できます。

<leader>gl

git logします。でもこれだと見づらいので、自分は

[alias]
    logall = log --graph --pretty=format:'%Cred%h %Cgreen(%>(15,trunc)%cr, %ci) %C(bold blue)<%an>%Creset -%C(yellow)%d%Creset %s' --abbrev-commit --date=relative --all
nnoremap <leader>gl :Git logall<CR>

みたいな感じにして見やすくしてます。

<leader>gh

別タブで今開いているファイルの変更履歴をたどれます。超便利。
Quickfixを使うようになっています。location listを使いたい場合は0Gllogコマンドに替える……

nnoremap <leader>gh :tab sp<CR>:0Gllog<CR>

……と良いです。マッピングはgit historyをイメージしました(実際にはそんなコマンドはありません)。

<leader>gp

git pushします。

<leader>gf

git fetchします。そろそろ飽きてきました

<leader>gd

変化の見やすい、いい感じのdiffをします。<leader>gsdvと同じです

特に、ここでもhunkのような[c``]cによる移動が可能。

更にmerge conflict状態では3つのウィンドウが出てきて、:diffget,:diffput=dpなどでどちらかからコピーすることが簡単にできる。詳しくはこちらを参照。

<leader>gr

git rebase -iします。

<leader>gg

gitgrepでgitリポジトリ全体から高速で検索をかけます。これも、location listを使いたい場合は

nnoremap <leader>gg :Glgrep 

としたらいいです。

<leader>gm

git mergeします。コンフリクトが発生したらそのまま修正作業に入れます。この時便利なdiffも使ってみましょう。

結果

Vim + Git is 最強


  1. 行単位で評価される。git add --patchのそれに近い ↩︎

  2. プラグインを読み込む前 ↩︎

  3. 普通に:Gstatusすると今のタブで起動してしまい狭いので、それを回避する。別に気にしないという人はこうしなくても良いです ↩︎

Share