diff3コマンドは3つのファイルを比較するコマンドになります。一つのファイルを元に複数の人が作業したときにその作業内容の比較を行いたいときやその作業内容を一つのファイルにまとめたいときに利用できます。
diff3コマンドの基本的な構文
diff3コマンドの基本的な構文
1 |
diff3 [option]... MYFILE OLDFILE YOURFILE |
第1引数のMYFILEはOLDFILEから作成されたファイルで、ファイルのマージを考える場合、OLDFILEとYOURFILEの差分を取り込むファイルとして指定します。
ただし、実際のファイル編集はedコマンド等を使用します。
第2引数のOLDFILEはMYFILEとYOURFILEが作成されたときの元になったファイルを指定します。
第3引数のYOURFILEはOLDFILEから作成されたもう一つのファイルを指定します。
diff3コマンドの例で使用するファイル
diff3コマンドを使用する例として、C言語の3つの不完全なプログラムを使用します。1つはプログラムの仮組みの状態のもの、後の2つはその仮組みのプログラムから一部の機能を実装したものになります。以下の3つのプログラムを使用して、diff3コマンドを利用します。
base.c(第2引数のOLDFILEとして使用)
base.cは、後述のmyfile.cとyourfile.cを作成するときに元となっているファイルになっています。プログラムとして行いたいことは単純に数値の足し算と引き算になります。
base.cは不完全なプログラムで、myfile.cとyourfile.cでそれぞれ足し算と引き算の関数を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <stdio.h> int main() { int num1 = 5; int num2 = 3; //add //subtract //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
myfile.c(第1引数のMYFILEとして使用)
base.cを元にして、足し算の関数を作成したものになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <stdio.h> int add(int num1, int num2) { return num1 + num2; } int main() { int num1 = 5; int num2 = 3; int var1; //add var1 = add(num1, num2); //subtract //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
yourfile.c(第3引数のYOURFILEとして使用)
base.cを元にして、引き算の関数を作成したものになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <stdio.h> int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var2; //add //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
また、上の3つのファイルをマージしたときに、意図するマージファイルは以下のファイルになります。
merge.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <stdio.h> int add(int num1, int num2) { return num1 + num2; } int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var1; int var2; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
diff3コマンドの利用例
3つのファイルを比較
diff3コマンドは3つのファイルを引数に取って、利用すると3つのファイルでの差分をそれぞれ表示します。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$diff3 myfile.c base.c yourfile.c ==== 1:3,7c int add(int num1, int num2) { return num1 + num2; } 2:2a 3:3,7c int subtract(int num1, int num2) { return num1 - num2; } ==== 1:12c int var1; 2:6a 3:12c int var2; ====1 1:15c var1 = add(num1, num2); 2:8a 3:14a ====3 1:17a 2:10a 3:17c var2 = subtract(num1, num2); |
差分の見方を説明します。差分の始まりとして最初に「====」のような行が入ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
==== 1:3,7c int add(int num1, int num2) { return num1 + num2; } 2:2a 3:3,7c int subtract(int num1, int num2) { return num1 - num2; } |
それぞれのファイルの箇所で差分のかたまりを表示します。それぞれのファイルの差分については、差分の最初に「1:3,7c」のような行が出力されます。
これは1つ目の引数のファイルで、3行目から7行目までの行の範囲で差分のかたまりが存在することを示しています。そのあとの行は差分に該当する箇所になります。
同様に、「2:2a」のような行もあります。これは2つ目の引数のファイルで、2行目に差分のかたまりが該当して、その2つ目の引数のファイルには差分の行がないことを表しています。
次の「3:3,7c」は、最初の「1:3,7c」と同様で、3つ目の引数のファイルで、3行目から7行目までの行の範囲で差分のかたまりがすることを示しています。そのあとの行も同様に、差分に該当する箇所になります。
「====1」のように「====」の後に数字がある行から始まる差分もあります。
「====1」は、差分個所が3つのファイルの内の2つのファイルが共通で、1つ目の引数のファイルだけが異なることを表しています。
1 2 3 4 5 |
====1 1:15c var1 = add(num1, num2); 2:8a 3:14a |
OLDFILEとYOURFILEの差分をMYFILEに適用するedスクリプトを出力
(-eオプション)
-eオプションは、MYFILEに適用するedスクリプトを出力します。また、このedスクリプトはOLDFILEからYOURFILEの差分(変更箇所)を出力します。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$diff3 -e myfile.c base.c yourfile.c 17a var2 = subtract(num1, num2); . 12c int var2; . 3,7c int subtract(int num1, int num2) { return num1 - num2; } . |
-eオプションにさらに-iオプションを追加することで、ファイルを実際に編集するようなスクリプトになります(最後に書き込みのwと終了のqが追加されます)。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$diff3 -ei myfile.c base.c yourfile.c 17a var2 = subtract(num1, num2); . 12c int var2; . 3,7c int subtract(int num1, int num2) { return num1 - num2; } . w q |
このedスクリプトを適用した結果を表示すると以下のような結果を得ることができます。
実際に-eオプションで作成されたスクリプトをedコマンドで適用すると、MYFILEとYOURFILEで競合する箇所ではYOURFILEの変更が優先されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$(diff3 -e myfile.c base.c yourfile.c;echo '1,$p') | ed - myfile.c #include <stdio.h> int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var2; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$diff3 -me myfile.c base.c yourfile.c #include <stdio.h> int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var2; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
全てのファイルでの競合箇所を含めるedスクリプトを出力
(-Aオプション)
-Aオプションは、MYFILEに適用するedスクリプトを出力します。このedスクリプトは全ての変更点に関して、競合している箇所にコンフリクトマーカーをつけて出力されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$diff3 -A myfile.c base.c yourfile.c 17a var2 = subtract(num1, num2); . 12a ||||||| base.c ======= int var2; >>>>>>> yourfile.c . 11a <<<<<<< myfile.c . 7a ||||||| base.c ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c . 2a <<<<<<< myfile.c . |
コンフリクトマーカーはそれぞれの差分のかたまりについて、
1 2 3 4 5 6 7 |
<<<<<<< myfile.c myfile.c lines ||||||| base.c base.c lines ======= yourfile.c lines >>>>>>> yourfile.c |
のように表示して、全てのファイルの変更点に関しての競合(conflict)を表します。実際に意図したマージファイルを完成させたい場合は、この競合箇所をエディタなどで編集すると簡単にマージしたファイルを作成できます。
上の出力を競合箇所を編集して、merge.edを作成し、edコマンドを適用することでマージファイルの出力を得る事もできます。
merge.ed
1 2 3 4 5 6 7 8 9 10 11 12 13 |
17a var2 = subtract(num1, num2); . 12a int var2; . 7a int subtract(int num1, int num2) { return num1 - num2; } . |
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$(cat merge.ed;echo '1,$p') | ed - myfile.c #include <stdio.h> int add(int num1, int num2) { return num1 + num2; } int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var1; int var2; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
実際にファイルへ編集を保存するには以下のようなコマンドを利用できます(edスクリプトにw(書き込み、write)とq(終了、quit)を追加しています)。
コマンド例と実行結果
1 |
(cat merge.ed;echo 'wq') | ed - myfile.c |
ファイルのマージ
(-mオプション)
-m(--merge)オプションは、ファイルをマージした出力を表示できます。マージした出力とは、-Aオプション(-mオプションのデフォルト)や-eオプションのedスクリプトをMYFILEに適用した結果の出力になります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
$diff3 -m myfile.c base.c yourfile.c #include <stdio.h> <<<<<<< myfile.c int add(int num1, int num2) { return num1 + num2; } ||||||| base.c ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c int main() { int num1 = 5; int num2 = 3; <<<<<<< myfile.c int var1; ||||||| base.c ======= int var2; >>>>>>> yourfile.c //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
上の出力結果をファイルに保存し、viエディタ等で編集することでマージしたファイルを作成することもできます。
merge.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <stdio.h> int add(int num1, int num2) { return num1 + num2; } int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var1; int var2; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
MYFILEとYOURFILEの変更箇所の競合を含めるedスクリプトを出力
(-Eオプション)
-Eオプションは、-eオプションと同じようにMYFILEへ適用するedスクリプトを出力します。
OLDFILEからYOURFILEの差分をMYFILEに適用するためのスクリプトを出力します。
しかし、競合を表示する情報が-Aオプションと比べて少なくなり、このスクリプトを適用したときに、MYFILEから変更する箇所にコンフリクトマーカ―が表示されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$diff3 -A myfile.c base.c yourfile.c 17a var2 = subtract(num1, num2); . 12a ||||||| base.c ======= int var2; >>>>>>> yourfile.c . 11a <<<<<<< myfile.c . 7a ||||||| base.c ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c . 2a <<<<<<< myfile.c . |
-mオプションを利用し、マージした結果は以下のような出力になります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
$diff3 -mE myfile.c base.c yourfile.c #include <stdio.h> <<<<<<< myfile.c int add(int num1, int num2) { return num1 + num2; } ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c int main() { int num1 = 5; int num2 = 3; <<<<<<< myfile.c int var1; ======= int var2; >>>>>>> yourfile.c //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
-Eオプションの競合箇所については
1 2 3 4 5 |
<<<<<<< myfile.c myfile.c lines ======= yourfile.c lines >>>>>>> yourfile.c |
のようになり、-Aオプションと比べて、OLDFILEについての差分個所が現れないのが特徴になります。
MYFILEでの競合しない個所のみを出力
(-3オプション)
-3オプションは、MYFILEに適用するedスクリプトを出力します。また、このedスクリプトはOLDFILEからYOURFILEの差分(変更箇所)で競合していない箇所のみを出力します。
コマンド例と実行結果
1 2 3 4 |
$diff3 -3 myfile.c base.c yourfile.c 17a var2 = subtract(num1, num2); . |
-mオプションを利用し、マージした結果は以下のような出力になります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$diff3 -m3 myfile.c base.c yourfile.c #include <stdio.h> int add(int num1, int num2) { return num1 + num2; } int main() { int num1 = 5; int num2 = 3; int var1; //add var1 = add(num1, num2); //subtract var2 = subtract(num1, num2); //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
MYFILEでの競合する箇所のみを出力
(-xオプション)
-xオプションは、MYFILEに適用するedスクリプトを出力します。また、このedスクリプトはOLDFILEからYOURFILEの差分(変更箇所)での競合する箇所のみを出力します。競合している箇所はYOURFILEの内容が優先になり、MYFILEの内容を上書きするスクリプトが出力されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 |
$diff3 -x myfile.c base.c yourfile.c 12c int var2; . 3,7c int subtract(int num1, int num2) { return num1 - num2; } . |
-mオプションを利用し、マージした結果は以下のような出力になります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$diff3 -mx myfile.c base.c yourfile.c #include <stdio.h> int subtract(int num1, int num2) { return num1 - num2; } int main() { int num1 = 5; int num2 = 3; int var2; //add var1 = add(num1, num2); //subtract //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |
MYFILEでの競合する箇所のみをコンフリクトマーカーをつけて出力
(-Xオプション)
-Xオプションは、MYFILEに適用するedスクリプトを出力します。また、このedスクリプトはOLDFILEからYOURFILEの差分(変更箇所)での競合する箇所のみを出力します。ただし、競合している箇所でMYFILEの内容が上書きされる個所はコンフリクトマーカーをつけて出力されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$diff3 -X myfile.c base.c yourfile.c 12a ======= int var2; >>>>>>> yourfile.c . 11a <<<<<<< myfile.c . 7a ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c . 2a <<<<<<< myfile.c . |
-mオプションを利用し、マージした結果は以下のような出力になります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
$diff3 -mX myfile.c base.c yourfile.c #include <stdio.h> <<<<<<< myfile.c int add(int num1, int num2) { return num1 + num2; } ======= int subtract(int num1, int num2) { return num1 - num2; } >>>>>>> yourfile.c int main() { int num1 = 5; int num2 = 3; <<<<<<< myfile.c int var1; ======= int var2; >>>>>>> yourfile.c //add var1 = add(num1, num2); //subtract //print printf("add:%d subtract:%d\n", var1, var2); return 0; } |