93
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

VimAdvent Calendar 2020

Day 16

Gitと連携するツールとしてのVim

Last updated at Posted at 2020-12-15

はじめに

Vimといえば、みなさんご存じテキストエディタですが、テキストエディタである以前に一つのCLIコマンドでもあります。そんなCLIコマンドの利点一つにThe UNIX philosophyの定理として提唱されている『7. Use shell scripts to increase leverage and portability. (シェルスクリプトによって梃子(てこ)の効果と移植性を高める)』というものがあります。

今回は私も普段の仕事で利用しているVimの梃子としての側面をご紹介できればと思います。

GitコマンドとVim

今回Vimと組み合わせるのはシステム開発で避けては通れぬバージョン管理システムGitです。私は普段Gitを使用するときにはSourcetreeGitKrakenなどのGUIクライアントを利用せずにCLIで操作をしています。
皆さんこう思われるかもしれません。「またCLI狂信者か。あんな簡素なインタフェースで、Gitなんて複雑なものを素早く操作できる訳無いだろう。おとなしくGUIクライアントを使えばいいじゃないか。」
ちょっとまってください。私もなにも素のGitコマンドだけですべてを操作することが効率が良いという気はないのです。CLIコマンドだからこそ簡単に他のツールと連携できることこそが魅力だと言いたいのです。

コミットメッセージをVimで入力する

まずは基本のキ、コミットメッセージの入力です。Git管理ファイルを変更し、差分をaddしてstagedにします。そしたらさあコミットの時間です。
皆さんは普段GitのCLIコマンドでコミットするときにどうされるでしょうか?私はそのまま単純にgit commitと入力します。オプションなしで実行するとそのままデフォルトのエディタ(環境変数$EDITORに設定されたコマンド)でGitのメッセージ入力用の一時ファイルを開き、ファイルを閉じたときにファイル入力内容を読み取ってコミットします。

git-commit-plain.gif

補足すると、このとき最優先で開くエディタは.gitconfigファイルに設定されているコマンドなので、明示的に指定したいときは以下のコマンドで指定すると良いでしょう。

git config --global core.editor ${editor}

ここからが面白いところです。素のVimを立ち上げただけだとそれなりに便利ではありますが少し物足りません。そこでいくつかの機能を追加してあげましょう。まずスペルチェックをGitのメッセージ編集時のみ有効にしてあげましょう。

augroup GitSpellCheck
    autocmd!
    autocmd FileType gitcommit setlocal spell
augroup END

スペルチェックだけだと、タイポはわかっても正しいスペルがわからないってときもありますよね。そんなときは辞書を引けばいいのです。deoplete.nvimneco-lookを導入すれば、英単語が自動補完されるので、つまらないタイポとはオサラバです。

Plug 'Shougo/deoplete.nvim'
Plug 'ujihisa/neco-look'
let g:deoplete#enable_at_startup = 1
call deoplete#custom#option('sources', {
\ 'gitcommit': ['look'],
\})

spell-check-and-completion.gif

更にcommittia.vimというプラグインを導入することで、変更したファイル内容などのコミットに付属する各種情報を一目で確認することができます。Vimでコミットメッセージをいじるなら是非入れたいプラグインです。

Plug 'rhysd/committia.vim'
function! g:committia_hooks.edit_open(info)
    " Additional settings
    setlocal spell
    setlocal spelllang+=cjk

    " If no commit message, start with insert mode
    if a:info.vcs ==# 'git' && getline(1) ==# ''
        startinsert
    end

    " Scroll the diff window from insert mode
    " Map <C-n> and <C-p>
    imap <buffer><C-n> <Plug>(committia-scroll-diff-down-half)
    imap <buffer><C-p> <Plug>(committia-scroll-diff-up-half)
endfunction

Screen Capture_Alacritty_20201215215610.png

いかがでしょうか?Gitのコミット時に英単語のスペルチェックと自動補完と各種差分情報を見れてVimキーバインドでテキスト編集できる環境というのはなかなかないと思います。コミットメッセージを書くというVimが最も得意な行為をVimに任せる。それだけでGitコマンド単体と比べ格段に便利になるのです。

Gitの差分をVimで見る

Gitで差分の確認もよくやる作業です。Gitコマンドで差分を見るなら以下のような流れですね。

# 差分を確認するハッシュをログから確認
git log
# 該当のハッシュの差分を見る
git diff ${hash}

git-diff-plain.gif

上記を実行すると、だいたいの環境ではlessコマンドなどのページャが起動してスクロールすると思います。少量ならばこれでもいいですが、多量のdiffを確認するには心もとありません。そこで登場するのがVimです。皆さんVimのことをただのエディタだと思ってますよね?実はVimは差分比較ツールとしても優秀なのです。もし使ったことがないのならば一度でいいからdiffのかわりにvimdiffを使ってみて欲しいです。

Gitは先程のコミットメッセージのように、差分についても別コマンドに連携することができるのです。例えばWindowsで有名な差分ツールのWinMergeでGitの差分を表示したり。なんてこともできます。

このような外部ツールをGitコマンドから起動するときはdiffではなくdifftoolを利用するのですが、このとき起動する外部ツールをeditorの変更をしたとき同様に設定で変更できます。

git config --global diff.tool vimdiff

設定を変更したらあとはコマンドを実行するだけです。

git difftool ${hash}

git-difftool.gif

いかがでしょうか。とても見やすくなったのではないでしょうか?
差分以外の部分は折り畳まれてたりと、いい感じに気を利かせてくれていますね。

なお上記のGIF動画ではファイルごとに確認のプロンプトが表示されていますが、こちらについては設定で有無を選択できます。

git config --global difftool.prompt false

さて差分を確認できるとなると、少し欲が出てきますね。この見やすい差分の画面で、コンフリクト解消ができたらとっても便利なのに。そう思いませんか?

できます!!!!以下の記事に自分が以前参考にした内容が記載されているので見てみてください。

またvimdiffというのは本家Vim側が用意しているコマンドであって、NeoVimのコマンドではありません。そのため、NeoVimで同じことをやろうとするとまた別の設定が必要になります。こちらについては以下の参照ください。

さてここまでくるとだいぶGitとVimの組み合わせのパワーを感じてきたのではないでしょうか?

TigとVim組み合わせてインタラクティブにGit操作しよう

最後に組み合わせの要素をもう一つ追加します。それがTigです。俗に言うインタラクティブなGitコマンドです。
類似のコマンドにGolang製のLazyGitやRust製のGitUIなんかがあります。これらのほうがパフォーマンス面で優れていたりしているのですが、コマンドを形作る思想やカスタマイズ性が自分にマッチしすぎていて、tigを手放す気にはなりません。
tig単体でもかなり強力なツールなのですが、tigとVimを組み合わせることでもっと強力になります。

今回基本的な使い方については解説しないのでマニュアルをご参照ください。

Tigでみた差分からVimを開く

私が多様するのがこれで、TigのDiff Viewからeを押すことで、カーソル位置のファイルをgit editorで開くというものです。シンプルが故にいくらでも応用が効きます。開いた後は普通にエディタとして操作が可能です。私はこれをプロジェクト編集の起点にしたりします。

tig-diff-edit.gif

Tigで差分を見てからrebaseしよう

皆さんチームメンバーに「このコミットとこのコミット粒度が小さすぎるからsquashしておいて、git rebase -iでできるから。」と言われて、ナンノコッチャと調べて悪銭苦闘し、一時間ぐらいかけて2つのコミットをsquashしたことはありませんか?私はあります。
git logで該当のハッシュと差分を調べつつ、恐る恐るgit rebase -iを実行する。そして次回やる頃にはどうやるかを忘れている。そしてrebaseなんかもう二度とやらないと思う。そんなことありませんか?私はあります。

そんな私はTigとたった一行の.tigrc(Tigの設定ファイル)でこの悩みから開放されました。それがこの$HOME/.tigrcです。

.tigrc
bind main R !git rebase -i %(commit)

やってることは単純でTigのmain view閲覧時のRでカーソル配下のcommitを起点にrebase -iを実行するだけです。

tig-rebase-i.gif

なお豆知識なんですが、このrebase -iで起動したファイル上だとcommit hashをカーソル下においてKを押すとdiffが見れます。これはVimにビルドインされているプラグインの機能です。

Tigの差分をVimで見る

自分で紹介しといてなんですがGitの差分をVimで見るを更に便利にしたものをご紹介しましょう。.tigrcに以下を追加することで、その機能を利用できます。なおgit difftoolの設定ができていることを前提とします。

.tigrc
bind main D !sh -c "git difftool %(commit)~ %(commit)"

これはTigでカーソル配下のcommitとその前のcommitの差分をvimdiffで表示できます。Gitコマンドでやっていたことをインタラクティブにできるようにしたと考えれば良いでしょう。

tig-difftool.gif

これはmain viewだけではなくref view(ブランチの一覧)でも使えるため、ブランチの差分なんかを確認するのにも使えます。

.tigrc
bind refs D !sh -c "git difftool %(branch)"

最後に

Vimというコマンドの中だけでも面白いですが、Vimとて一つのCLIコマンドです。その特色を活かして、他のコマンドからVimへ、Vimから他のコマンドへの組み合わせることで、相乗効果が生まれるということが少しでもわかっていただけたなら幸いです。
もし皆さんのオススメの組み合わせなどあれば、ぜひ私に教えてください。

93
80
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
93
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?