🕴️

Emacs で git jump を使ってみる

2023/12/09に公開

この記事は2023年 Emacs アドベントカレンダーの10日目の記事です。

はじめに

この記事では Emacs における git jump サブコマンドの利用例を紹介します。 結論としては magit があれば git-jump は必要がなさそうだ、というのが私の意見です。 ただ、その周りにある技術は興味深いものですし、私としてもせっかく調べたことなので、ここにまとめたいと思います。

発端

2023年3月 Git のバージョンアップに関する小さなニュースが流れました。

Highlights from Git 2.40 - The GitHub Blog 分散型バージョン管理システム「Git 2.40」が公開 - CodeZine

このニュースには下記のように説明されていました。

「git jump」コマンドが「Emacs」エディタに対応した。git jumpコマンドは、「grep」や「diff」「merge」といったコマンドと組み合わせて使うことで、ファイルの変更点や検索キーワードに該当する部分などをすぐに表示する機能を持っている。従来は「Vim」エディタでしか使えなかったが、今回の新版からEmacsにも対応した。

git jump コマンドとはなんだろう。slack の emacs-jp でも質問してみましたが、特に知っている人はいませんでした。調べてみると git の contrib で作られたツールなのだそうです。

contrib という文化

オープンソースプロジェクトに contrib というディレクトリが配置されていることがあります。 ここには、必須の機能ではないけれど、コミュニティによって提供されているツールが置かれます。 ビルドには含まれず、ドキュメントでは紹介されず、テストも持ちません。 コードオーナーはこれらのツールを一切メンテナンスしません。 そういった標準から外れたディレクトリですが、そこにはプロジェクトのユーザが容易にコードを追加できます。多くの環境で使えるような設定があったり、 サードパーティツールとの連携をするものだったり、さまざまな実験や情報共有に使われます。

git のプロジェクトにも contrib ディレクトリはあります。下記のディレクトリがそうです。ここに git-jump が配置されていました。

https://github.com/git/git/tree/v2.40.0/contrib/git-jump

git のサブコマンド

git jump は標準でインストールされるツールではなく、サブコマンドとして利用します。 git のサブコマンドとは git status のように git xxx の形で実行できるコマンドのことです。 そして、git のサブコマンドは簡単に追加できます。 具体的には git- で始まる実行ファイルを用意し、パスが通っているディレクトリに配置するだけです。実際に簡単なサブコマンドを作ってみます。

mkdir ~/bin
PATH=~/bin:${PATH}
echo "echo 'hogehoge'" > ~/bin/git-hogehoge
chmod +x ~/bin/git-hogehoge

これでコマンド git-hogehoge が定義できました。どこからでもこの git-hogehoge を呼び出すことができます。 このコマンドは単に "hogehoge" を出力するだけの無意味なシェルスクリプトであり git とは無関係です。 しかし git hogehoge を実行してみると、内部的に git-hogehoge が呼び出し可能となっていることがわかります。 下記の記事では、より具体的で便利なサブコマンドの例が紹介されています。

gitをより便利にするsubcommand集を作った - 遺言書

git jump の使い方

git jump は diff や grep の出力結果をエディタに出力し、 エディタの内部で直ちにコードジャンプをするためのツールです。

インストール

標準ではインストールされないので、サブコマンドとしてインストールします。 たとえば ~/bin にパスが通っているなら、下記のようにします。

curl https://github.com/git/git/blob/v2.40.0/contrib/git-jump/git-jump -o ~/bin/git-jump
chmod +x ~/bin/git-jump

このあと git jump を実行して下記のようなエラーが表示されれば成功です。

usage: git jump [--stdout] <mode> [<args>]

Jump to interesting elements in an editor.
The <mode> parameter is one of: ...

もし環境変数 EDITOR を設定していないなら export EDITOR=emacs または export EDITOR=emacsclient を実行しておきましょう。さもないと、ほとんどの環境下で vi が起動してしまいます。

git jump diff

git でバージョン管理された適当なディレクトリへ移動しました。 手始めに下記の二つのファイルを編集してみました。

  • README.md
  • documents/index.md

下記の状態です。

diff --git a/README.md b/README.md
+追加1
+

diff --git a/documents/index.md b/documents/index.md
+追加2
+aaa
+bbb
+ccc

ここで git jump diff を実行すると Emacs 上に下記の grep バッファを生成できました。

-*- mode: grep; default-directory: "~/work/ex_web/" -*-
Grep started at Sat Dec  9 21:27:54

cat /var/folders/j5/gxwchdls4sxdgjg12fhzpz_m0000gr/T/git-jump.XXXXXX.bPkmMxeAdn
README.md:3: 追加1
documents/index.md:5: 追加2

Grep finished with matches found at Sat Dec  9 21:27:54

この各行をクリックするか control+o を押せば変更のあった hunk にジャンプできます。

git jump grep

キーワードはなんでも良いのですが私の書いているドキュメントディレクトリで git jump grep ジャンプ コマンドを試してみました。

-*- mode: grep; default-directory: "~/private/memo/" -*-
Grep started at Sat Dec  9 21:34:55

cat /var/folders/j5/gxwchdls4sxdgjg12fhzpz_m0000gr/T/git-jump.XXXXXX.qvZFrQeDwJ
book/the-typescript-handbook.org:173:7:定義ジャンプや参照の検索もある。ほとんどのエディタでそれらのツールは提供されている。
diary/20221215_rspec-mode-patch.org:44:52:ヘルプページから関数定義のリンクへジャンプすると
diary/20221215_rspec-mode-patch.org:56:98:ここで呼び出している ~rspec-spec-or-target~ にカーソルをあてて ~M-.~ の定義ジャンプで探索します。

Grep finished with matches found at Sat Dec  9 21:34:55

確かに「ジャンプ」を含む行を検索できていますし、コードジャンプもできるようになっていました。

終わりに

Git アップデートのニュースを発端として git-jump を実際に使ってみました。 ただ、私としては、特に今後 git-jump を利用するつもりはありません。 というのも magit を使っていれば、同等のことを、簡単に実行できるからです。

しかしながら git の周辺技術を改めて学ぶのにはちょうど良いニュースだったと思います。 contrib というディレクトリの文化について初耳だったし、サブコマンドが簡単に追加できることも知りませんでした。 そういう意味では良い出会いだったと思いますし、見逃さなくて良かったと思います。

最後に git jump を Emacs 対応された Nakayama さんのスライドをご紹介します。このスライドでは、もともと vi にしか対応していなかった git-jump を Emacs に対応させるためにどのようなステップを踏んだのかが説明されています。興味のある方は読んでみてください。

git-jump を解放する / loosen editor dependency of git-jump - speakerdeck

Discussion