はじめに
vimdiffが使える場合はこの記事は読む必要がありません。
また、はじめには読み飛ばして下さって構いません。
エンジニアにとって、2つのファイルの比較を行うことはよくあることだと思います。
ですが最近仕事で2つのファイルの差分を__誰でも__すぐに読み解ける方法を考え出す必要が出てきました。なお、補足をするとそのプロジェクトではgitを導入できる段階ではありませんでした。
全員がvimを使えるならvimdiffで良いと思います。
ここでは主に__diffコマンドに関することでの視覚的なこと__についてメモしたいと思います。
パッチ等他の形式については Linuxエンジニアらしいパッチのつくりかた がよくまとまっていると思いますので、そちらをご覧ください。
diffコマンド
一般的に差分を取るときは普通はdiffコマンドが思いつきます。diffコマンドの差分の判定についてのオプションについてはここでは省略します。
説明のために以下の2つのファイルを用意します。これ以降このファイルを使用します。
the
quick
brown
fox
jumps
over
the
lazy
dog
the
quick
brown
fox
jumped
over
the
lazy
dogs
この状態でdiff a.txt b.txtを実行すると以下のようになります。
% diff a.txt b.txt
5,6c5
<
< jumps
---
> jumped
8a8
>
10c10
< dog
---
> dogs
ここからは、以下の情報が読み取れると思います。他にも削除(d: deleted)があります。
- a.txtの5, 6行目とb.txtの5行目で改行+
jumpsのjumpedへの変更(c: changed)がされた - a.txtの8行目とb.txtの8行目で改行の追加(
a: added)がされた - a.txtの10行目とb.txtの10行目で
dogのdogsへの変更(c: changed)がされた
読み取ることはできますが誰でも読み解けるか、と言われると疑問が残ります。
Unified形式
-uオプションをつけることで、Unified形式で出力することができます。
-Uオプションで何行(デフォルトは3行)何行ずつ結合するか指定できます。
% diff -u a.txt b.txt
--- a.txt 2016-08-29 06:43:45.000000000 +0900
+++ b.txt 2016-08-29 06:43:59.000000000 +0900
@@ -2,9 +2,9 @@
quick
brown
fox
-
-jumps
+jumped
over
the
+
lazy
-dog
+dogs
ここからは、__a.txtとb.txtの2行目から9行目__にかけて以下の情報が上から順に読み取れます。
- a.txtからb.txtで改行の削除(-)がされた
- a.txtからb.txtで
jumpsの削除(-)がされた - a.txtからb.txtの
jumpedの追加(+)がされた - a.txtからb.txtで改行の追加(+)がされた
- a.txtからb.txtで
dogの削除(-)がされた - a.txtからb.txtで
dogsの追加(+)がされた
Unified形式では__同じ__ファイルの文脈の中で上から順に差分を調べることができます。
Context形式
-cオプションをつけることで、Context形式で出力することができます。
-Cオプションで何行(デフォルトは3行)何行ずつコピーするか指定できます。
% diff -c a.txt b.txt
*** a.txt 2016-08-29 06:43:45.000000000 +0900
--- b.txt 2016-08-29 06:43:59.000000000 +0900
***************
*** 2,10 ****
quick
brown
fox
!
! jumps
over
the
lazy
! dog
--- 2,10 ----
quick
brown
fox
! jumped
over
the
+
lazy
! dogs
ここからはまず、__a.txtの2行目から10行目__にかけて以下の情報が上から順に読み取れます。
- 改行が削除または変更された
-
jumpsが削除または変更された -
dogsが削除または変更された
また、__b.txtの2行目から10行目__にかけて以下の情報が上から順に読み取れます。
-
jumpedが変更された - 改行が追加された
-
dogsが変更された
Context形式では__それぞれの__ファイルの文脈の中で上から順に差分を調べることができます。
2カラム形式
-yオプションをつけることで2カラムにして表示することができます。このとき-Wオプションで合計の横幅(デフォルトは130)を設定することができます。似たものにsdiffがあります。
% diff -y -W 80 a.txt b.txt
the the
quick quick
brown brown
fox fox
| jumped
jumps <
over over
the the
>
lazy lazy
dog | dogs
読み方の説明はもはや不要に思えますが>が追加、<が削除、|が変更を表しています。
2カラム形式は、とても視覚的で誰にとっても読み易いとはと思いませんか?(あくまで私の感想ですが)
しかし、この表示には欠点があります。それは、__行数がつかめない__ことです。
これを解決する方法をコラムの後に述べます。
コラム: diffに色をつけて表示する
色があると読み易さが格段に向上します。
他にも色をつけられるコマンドはたくさんありますが linux(CentOS)のコマンドに色付け の記事にまとまっています。
diffに色をつける場合にはcolordiffがあります。
導入方法
Homebrewの場合
% brew install colordiff
Debian系の場合
# apt-get install colordiff
RHEL系の場合
# yum install colordiff
使い方
diffコマンドではなく、colordiffを実行すれば良いです。
毎回colordiffと打つのが面倒であれば以下のように.bashrcや.zshrcなどに以下を追記します。
alias diff='colordiff'
このときdotfilesをgit管理していて複数の環境で使うという場合などでは以下のように追記すると良いでしょう。
if [[ -x `which colordiff` ]]; then
alias diff='colordiff'
else
alias diff='diff'
fi
icdiffを利用する
行数を表示して2カラムが表示できても行数がなければどこか特定するのは難しくなります。
そこでicdiffの--line-numbersオプションを利用してみます。
導入方法
導入方法は jeffkaufman/icdiff: improved colored diff にもまとまっています。gitで利用したい場合は参照すると良いでしょう。
# pip install git+https://github.com/jeffkaufman/icdiff.git
使い方
-Uオプションで表示される行を少なくしています。
また、icdiffなど色付きコマンドをlessに入れる場合は... | less -Rとすると良いでしょう。
diffコマンドでicdiffコマンドが呼び出されるのは強引な気がしますので、今回はオプションのエイリアスで止めておきます。以下のようにすれば良いでしょう。
alias icdiff='icdiff -U 1 --line-numbers'
まとめ
-
diffの表示形式にはUnified形式、Context形式、2カラム方式がある(RCS formatなどは視覚的でないため除く) - 色をつけるには
colordiffを使うと良い -
icdiffを利用すればは2カラム形式で色をつけ、行番号を簡単につけられる - 全員vimを使えるなら
vimdiffが...いいのです...
