git の拡張

Stefan Saasen
Stefan Saasen
リストに戻る

Mercurial は (内面ではあるものの) 明確に定義された API を備えていて、Mercurial の機能を拡張する拡張機能を書くのに使用できますが、git の拡張モデルは小さくシンプルなプログラムを書くという UNIX 哲学に従いつつ同様の効果を達成しています。つまり、git の "拡張機能" はいくつかの簡単なルールに従って任意の言語によって作成できて、しかも git に内蔵されているかのようなコマンドを追加できるのです。

例: git アクティビティ

リポジトリにあるすべてのブランチのアクティビティを表示するために、私は git activity コマンドを実装しました。git activity はすべてのブランチの最新のコミットを新しいものから順に表示します。

Rails リポジトリで実行すると、次の出力が表示されます。

Rails 出力

スクリプトは bash で記述されていて比較的読みやすいものです。色を設定して、スクリプトがサポートするコマンド ライン オプション (色をオフにする、出力を制限するなど) を解析した後に、git for-each-ref を実行して ref ごとの情報を出力します。

 #!/bin/bash set -e GIT_OPTS="" OUTPUT_FILTER="cat" # no-op commit_id_format=$(tput setaf 1) date_format=$(tput bold; tput setaf 4) author_format=$(tput setaf 2) ref_name_format=$(tput setaf 3) bold=$(tput bold) reset=$(tput sgr0) function usage() { echo "" echo "git activity" echo "" echo " See 'man git-activity' for further information" } # オプションを実際に解析して作業を実行 while [[ $1 = -?* ]]; do case $1 in -h|--help) usage exit 0 ;; --fetch) echo "Fetch updates" git fetch -q ;; -c|--count) shift limit=${1-"10"} #OUTPUT_FILTER="tail -n ${limit}" GIT_OPTS="--count=${limit}" ;; --no-color|--no-color) commit_id_format="" date_format="" author_format="" ref_name_format="" bold="" reset="" ;; *) ;; esac shift done # 改行をフィールドの区切り文字として使用 IFS=$(echo -en "\n\b") # 可能な場合は tac を、可能でない場合は tail を利用 (常に利用可能とは限らない) # -r フラグを指定 (逆順で出力) TAC=$(which tac || echo 'tail -r') for line in $(git for-each-ref ${GIT_OPTS} refs/remotes --format="%(authordate:relative)|%(objectname:short)|%(authorname)|%(refname:short)|%(subject)" --sort="-authordate"); do fields=(`echo $line | tr "|" "\n"`) printf "${date_format}%15s${reset} ${commit_id_format}%s${reset} - ${author_format}[%s]${reset} (${ref_name_format}%s${reset}): %s\n" ${fields[*]} done | eval $TAC # 最新のエントリを最後に表示するため、出力を逆順でソート

このスクリプトを Git のサブコマンドとして利用可能にするために従うべき重要なルールは、次のとおりです。

  • スクリプトには git-COMMANDNAME のように名前を付ける必要があり、この場合は git-activity としています。
  • スクリプトは $PATH 上で実行可能かつ利用可能にする必要があります。私の例では、カスタムの git-activity スクリプトは /usr/local/bin ディレクトリにありますが、$PATH 上にあればどのディレクトリでも構いません。
[5002] λ > type git-activity git-activity is /usr/local/bin/git-activity [5002] λ > git activity [...]

マニュアル/ヘルプ ページの提供

カスタム コマンドに man ページが添付されている場合は、git help コマンドでヘルプ情報も表示されます。たとえば、activity コマンドの man ページは /usr/local/share/man/man1/git-activity.1 にあり、man git-activity または git help activity で表示されます。

manpath コマンドによって、システムが man ページを検索する場所を表示できます。

[5003] λ > manpath /Users/ssaasen/.opam/system/man:/usr/local/share/man:/usr/share/man:\/Users/ssaasen/.cabal/share/man:/opt/scala/man

git help activity の出力は次のようになります (https://bitbucket.org/ssaasen/git-pastiche/src/master/man/git-activity.1 を使用)

Git アクティビティの man ページ

ボーナス ヒント man ページは、Pandoc によってマークダウンから簡単に生成できます。

[5010] λ > pandoc -s -w man doc/git-activity.1.md-o ./distribution/man/git-activity.1 # テストのため man ページを表示 [5011] λ > nroff -man ./distribution/man/git-activity.1 # 実際の man ページを指定された manpath ロケーションにコピーして表示: [5012] λ > man -wa git-activity /usr/local/share/man/man1/git-activity.1

結論

いくつかの単純なルールに従って小規模で焦点を絞ったプログラムやスクリプトから機能を構成する Unix モデルを採用することで、git の機能を拡張してカスタム コマンドを git コマンド スイートの一部にすることが驚くほど簡単であることがわかりました。

その他の拡張機能

git-activity や他のいくつかのコマンドのソースは「https://bitbucket.org/ssaasen/git-pastiche」をご覧ください。

その他の追加 Git コマンドは、次をご覧ください。

Git を学習する準備はできていますか?

この対話式チュートリアルを利用しましょう。

今すぐ始める