Recursiveマージストラテジーで、ファイル名の変更を検出する差分の量を指定して、マージする
「Recursiveマージストラテジー」では、ファイル名が変更されたファイルが存在するかどうかを検出し、ファイル名が変更されたファイルを、ファイル名が変更される前のファイルと同じファイルとして扱う仕組みがあります。この仕組みでは、それぞれのファイルに対してファイル名が変更されたファイルかどうかをチェックする際、ファイルの比較結果から、差分がない箇所(変更されていない箇所)とファイルサイズとの割合で、ファイル名が変更されたかどうかを判断します。
この割合の基準のことを、「しきい値」と言います。
ユーザーは、このしきい値を指定することができます。
例えば、しきい値に40%を指定した場合、差分がない箇所とファイルサイズとの割合が40%以上であれば、ファイル名が変更されたファイルとして検出される可能性があります。
ファイル名が変更されたファイルの検出を抑制するには
ファイル名が変更されたファイルの検出は、マージを行う際に自動的に行われます。この検出を可能な限り抑制するには、しきい値に「100%」を指定します。
オプションの値としきい値について
オプション(rename-threshold)の値に、しきい値を指定します。しきい値の単位
しきい値の単位は、百分率(%)で指定するか、直接数値で指定します。例えば、しきい値に50%を指定する場合、以下のいずれかの記述で指定します。
- rename-threshold=50%
- rename-threshold=5
- rename-threshold=0.5
「2.」の記述方法は、「0.」を省略した記述方法です。
すなわち、「0.5」を指定したのと同じ扱いになります。
しきい値に指定できる値
しきい値に指定できる値は、百分率(%)で指定する場合、「1」から「100」です。しきい値のデフォルト値
しきい値のデフォルト値は、「50%」です。「rename-threshold」オプションを指定しなかった場合、しきい値に「50%」が指定されます。
ファイル名の変更を検出する例
ファイル名の変更を検出する例です。ここでは、ファイル名が変更されたファイルとして認識されるケースと、別のファイルとして認識されるケースを紹介します。
まずは、状況の確認です。
1.ブランチの確認
現在のブランチ構成を確認すると、以下のようになっています。現在のブランチは、「master」ブランチであることが分かります。
同様に、「HEAD」は「master」ブランチを指していることが分かります。
ここでは例として、「master」ブランチに「fix」ブランチをマージします。
2.ブランチの状態
ブランチの状態を図にすると、以下のようになります。3.Commit2のcommon.txtファイルの中身
「Commit2」に「common.txt」ファイルがあります。「common.txt」ファイルに着目します。
「Commit2」の「common.txt」ファイルの中身は、以下のようになっています。
4.masterブランチのワーキングディレクトリー
「master」ブランチの「ワーキングディレクトリー」は以下のようになっています。「common.txt」ファイルの中身は、以下のようになっています。
このファイルは、「Commit2」の「common.txt」ファイルを編集しています。
5.fixブランチのワーキングディレクトリー
「fix」ブランチの「ワーキングディレクトリー」は以下のようになっています。「rename.txt」ファイルに着目します。
「rename.txt」ファイルの中身は、以下のようになっています。
このファイルは、「common.txt」ファイルの編集とファイル名の変更を行ったファイルです。
6.マージベースの確認
「common.txt」ファイルと「rename.txt」の類似指標を調べるには、「マージベース」と「fix」ブランチのdiffを取る必要があります。まず「マージベース」を調べ「コミットオブジェクト」の識別子を取得します。
7.類似指標の確認
次にdiffを取って、類似指標を調べます。「similarity index」が類似指標です。
「common.txt」ファイルと「rename.txt」の類似指標は、「50%」であることが分かります。
ファイル名が変更されたファイルとして認識されるケース
ファイル名が変更されたファイルとして認識されるケースです。しきい値に「50%」以下のしきい値を指定すれば、ファイル名が変更されたファイルとして認識されます。
「1.」から「7.」までは、上記の「ファイル名の変更を検出する例」と同じです。
8.マージを行う
コマンドのオプションは、以下のオプションを指定します。ショートオプション | ロングオプション | オプションの値 |
---|---|---|
-X | --strategy-option= | rename-threshold=しきい値 |
「端末」から、以下のコマンドを実行します。
コマンドの詳細は、「ファイルのマージを行うコマンドの説明」を参考にしてください。
ポイントは、赤字の箇所です。
git merge --verbose --strategy=recursive --strategy-option=rename-threshold=50% fix
9.マージコンフリクトの発生
上記で紹介した通り、マージするファイルの中身は、変更箇所が衝突するため、「マージコンフリクト」が発生します。メッセージには、「rename.txtでマージコンフリクトが発生した」と出力されています。
これは、「fix」ブランチで行ったファイル名の変更が検出され、「rename.txt」ファイルと「common.txt」ファイルが関連付けられたためです。
10.ワーキングディレクトリーの状態
「ワーキングディレクトリー」の状態を見てみると、以下のようになっています。「common.txt」ファイルは削除されたファイルとして認識されています。
「rename.txt」ファイルは、編集されたファイルとして認識されています。
11.ワーキングディレクトリーの確認
「ワーキングディレクトリー」を見てみると、「rename.txt」ファイルが配置されています。「rename.txt」ファイルを開くと、以下のように「マージコンフリクト」が発生した箇所に「コンフリクトマーカー」が挿入されています。
別々のファイルとして認識されるケース
別々のファイルとして認識されるケースです。しきい値に「51%」以上のしきい値を指定すれば、別々のファイルとして認識されます。
「1.」から「7.」までは、上記の「ファイル名の変更を検出する例」と同じです。
8.マージを行う
コマンドのオプションは、上記の「8.」と同じです。しきい値のみ変更します。
git merge --verbose --strategy=recursive --strategy-option=rename-threshold=51% fix
9.マージコンフリクトの発生
以下のように、「マージコンフリクト」が発生します。メッセージには、「fix」ブランチで「common.txt」ファイルが削除されているが、「master」ブランチには「common.txt」ファイルが存在している、と出力されています。
これは、「rename.txt」ファイルは、ファイル名が変更されたファイルではなく、新規に「fix」ブランチで追加されたファイルとして認識されています。
「master」ブランチには、元々「rename.txt」ファイルが存在しないため、マージにより、「master」ブランチに「rename.txt」ファイルが追加された状態です。
一方、マージする前に「fix」ブランチで「common.txt」ファイルのファイル名を「rename.txt」に変更した際、「common.txt」ファイルを削除して、「rename.txt」を新規に追加した、という手続きになっているため、上記のような状態になっています。
「Git」は、「common.txt」ファイルを削除すべきなのか、削除すべきではないのか判断できないため、「マージコンフリクト」としてユーザーに操作を促します。
10.ワーキングディレクトリーの状態
「ワーキングディレクトリー」の状態を見てみると、以下のようになっています。「rename.txt」ファイルは、新規に追加されたファイルとして認識されています。
「common.txt」ファイルは、「fix」ブランチで削除されたファイルとして認識されています。
11.ワーキングディレクトリーの確認
「ワーキングディレクトリー」を見てみると、「common.txt」ファイルと「rename.txt」ファイルが配置されています。いずれのファイルの中身も、「4.」及び「5.」で紹介したファイルの中身と同じです。