はじめに
会社で使用している版数管理システムではブランチ間のマージができない。。。他人の修正を自分のブランチに取り込めないぽい。。ヽ( ゚д゚)ノ
ブランチ間でマージをするためには、両者のファイルを比較して、手動でマージシなければいけいない。そんなバカな、なにか方法があるのだろうと思い、調べてみた。
やりたいこと
- ブランチ間の自動マージ。
- コマンドライン上からサクッとできる。
- ただし、競合があるときや慎重にやりたいときは、手動マージ。
3 way mergeアルゴリズム
調べてみると、svnやcvsもできないらしい。git やMercurialだとできる。
その違いは何かというと、マージのためのアルゴリズムが違うのだった。
- svn、cvs ・・・ 2 way merge(2ウェイマージ)。2つのファイルの差分を比較してマージ。競合の解決は手動。
- git、mercural・・・3 way merge(3ウェイマージ)。2つのファイルの共通の祖先との差分を比較してマージ。競合の解決は自動。
競合を自動マージするためには、3-way mergeを使う必要がある。
GNU Diffutilsを使い倒す!
3 way merge をサクッとこなすコマンドを探しいてたら、diff3というものを発見!これは、GNU Project のDiffutilsに含まれるコマンドの一つらしい。ということで、このDiffutilsを調べた。
Diffutils - GNU Project - Free Software Foundation
diffutils とは、cmp, diff, diff3 そして sdiff のプログラムを含むパッケージ。これらのツール群を駆使して、差分比較やマージをコマンドラインからすることができる。
実験
以下のようなファイルをもとに、ツールを検証してみる。
比較対象
# test1 ファイル
a
a
a
a
a
# test2 ファイル
a
a
b
a
a
diff
まずはdiffから。これはさくっと2つのファイルの差分をみるためにつかう。
[tsu-nera]% diff test1 test2
3c3
< a
---
> b
sdiff
対話的にマージするためのツール。まずは、なにも指定しないと、両者を並べてdiffしてくれる。見やすい。
[tsu-nera]% sdiff test1 test2
a a
a a
a | b
a a
a a
差分だけをみるには、'-s’をつける。
[tsu-nera]% sdiff -s test1 test2
a | b
マージするには、-o “出力ファイル” をオプションでつける。マージする部分で、%のプロンプトがでるので、一つづつどうマージするか答える。手動マージで自動マージはしてくれない。
ed: 両方の版にヘッダーで飾って、利用し、編集。
eb: 両側の版を使用して編集。
el: 左側の版を使用して編集。
er: 右側の版を使用して編集。
e: 新版を編集。
l: 左側の版を使用。
r: 右側の版を使用。
s: 共通行を寡黙に含む。
v: 共通行を饒舌に含む。
q: 終了。
こんな感じでマージ。
[tsu-nera]% sdiff -o output test1 test2
a a
a a
a | b
%r
a a
a a
diff3
3 つのファイル間にある違いを探す 。つまり、
3 way mergeができる!(^_^)v
比較のためのアルゴリズムがdiffと異なるのだ。。基本は以下。
% diff3 MINE OLDER YOURS
- MINE ・・・自分のファイル
- OLDER ・・・ 2つのファイルの共通の先祖
- YOURS ・・・他人のファイル
共通の祖先を指定することがキモ。これで他人の修正を自分のファイルに取り込むことができる。
OLDER - -MINE
|
-YOURES
まずは実行。暗号めいた出力がでる。
[tsu-nera]% diff3 test1 test1 test2
====3
1:3c
2:3c
a
3:3c
b
====3で3つめのファイルに差分があることを示す。
マージするには、-mオプションをつける。すると標準出力にマージ結果が出力されるので、リダイレクトでファイルに書き出せばよい。
[tsu-nera]% diff3 -m test1 test1 test2 > output
[tsu-nera]% less output
a
a
b
a
a
まとめ
- 差分を確認したいときは、sdiff -s で。
- 自動マージするときは、diff3 -m で。
- 手動マージするときは、sdiff -o で。
なんとか頑張れそう。