はじめに

会社で使用している版数管理システムではブランチ間のマージができない。。。他人の修正を自分のブランチに取り込めないぽい。。ヽ( ゚д゚)ノ

ブランチ間でマージをするためには、両者のファイルを比較して、手動でマージシなければいけいない。そんなバカな、なにか方法があるのだろうと思い、調べてみた。

やりたいこと

  • ブランチ間の自動マージ。
  • コマンドライン上からサクッとできる。
  • ただし、競合があるときや慎重にやりたいときは、手動マージ。

3 way mergeアルゴリズム

調べてみると、svnやcvsもできないらしい。git やMercurialだとできる。

その違いは何かというと、マージのためのアルゴリズムが違うのだった。

マージ (バージョン管理システム) - Wikipedia

  • 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

Man page of DIFF

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

Man page of SDIFF

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

Man page of DIFF3

まとめ

  • 差分を確認したいときは、sdiff -s で。
  • 自動マージするときは、diff3 -m で。
  • 手動マージするときは、sdiff -o で。

なんとか頑張れそう。