環境
Envrionment | Version |
---|---|
Ubuntu | 20.04.2 LTS |
Windows | 10.0.19041 |
Git | 2.25.1 |
Git Custom Merge Driverとは
Gitのマージ処理を低レベルでカスタマイズできるGitに備わっている機構のこと。
強力な反面、事故りやすいので理解したうえで利用が必要。
作り方
- Custom Merge Driverの設定
- 適用ファイルの指定
Custom Merge Driverの設定
2つの方法がある。
- Inline
- sh
Driverが呼び出される際に利用可能な変数に%O
, %A
, %B
がある。他にもあるが、よくわからなかった。気になる方はリファレンス読み解いて下さい。
Driverの終了時に終了ステータスが
- 0(正常)の場合、
%A
をマージ後のファイル内容として採用する。 - 0(正常)以外の場合、コンフリクトが発生したとする。
%O
祖先のバージョンの内容を持つ一時ファイル名。
%A
oursのバージョンの内容を持つ一時ファイル名。
マージ後のファイル内容として採用する。
%B
theirsのバージョンの内容を持つ一時ファイル名
設定コマンド
git config merge.{戦略名}.name '戦略名でも概要でも'
git config merge.{戦略名}.driver '{Inlineコマンド or sh}'
適用ファイルの指定
.gitattributesへ追記する。
フォーマット
ファイルパス merge={戦略名}
注意
./{filename}
この書き方だと動かなかった。
{filename}
ルート直下のreadme.mdならば、以下のように記載する。
readme.md merge=alwaysTheirs
実際に作ってみる。
いつでもマージする側(featureブランチ)が優先されるマージ戦略を作る。
対象ファイルは、readme.txtにする。
Custom Merge Driverの設定
Sh作成
#!/bin/sh
echo "`date` custom merge start" >> mergeAlwaysTheirs.log
# 動作イメージをつかみたいときに
# O="$1" # prev version
# A="$2" # ours version
# B="$3" # theirs version
# cat $A > A.txt
# cat $O > O.txt
# cat $B > B.txt
# always theirs ($B)
# $B -> $A
cp -f $B $A
echo "`date` custom merge end" >> mergeAlwaysTheirs.log
exit 0
merge戦略の追加
git config merge.alwaysTheirs.name 'always theirs'
git config merge.alwaysTheirs.driver 'PATH=$PATH:
pwd && mergeAlwaysTheirs.sh %O %A %B'
2行目は、リポジトリ直下でマージ操作を行う前提だが、pathをいちいち通すのも面倒なので。
shへパス通しているなら不要。
確認
git config -l
merge.alwaysTheirs.name=always theirs
merge.alwaysTheirs.driver=PATH=$PATH:`pwd` && mergeAlwaysTheirs.sh %O %A %B
merge用のshは、Gitリポジトリに入れる。
適用ファイルの指定
.readme.md merge="alwaysTheirs"
実際の動き
masterブランチの内容
# Title
## Header
featureブランチの更新内容
# Title2
## Header2
masterブランチの更新内容
# Title1
## Header1
Merge実行
GUIツールベース
手持ちのIntelliJでpull featureブランチすると、問題なく、Theirs(featureブランチ)で上書き出来た。
コマンドベース
git pull origin feature/test
コマンドベースだと、プロンプトが立ち上がる
git merge
時に、マージコミットを編集するプロントが立ち上がる。
Merge branch 'feature/test' of https://github.com/{User}/git-test
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
一行目のコミットメッセージで良いならば、上書き更新(viならESC->:wqとかの保存操作)。
merge後のmaster
# Title2
## Header2
DriverをInlineで記載する例
ours, theirs程度の操作なら、InlineでOK。
常にtheirsを採用
git config merge.alwaysTheirs.name 'always theirs'
git config merge.alwaysTheirs.driver 'cp -f %B %A'
常にoursを採用
git config merge.alwaysOurs.name 'always ours'
git config merge.alwaysOurs.driver 'exit 0'
Windows
Git Bash上やそれを呼び出すようになっているTortoiseGitならまったく同じコマンドラインで可能。
参考
git-mergeの挙動をカスタマイズする
git-merge
gitattributes
cpコマンド
複数コマンドをAND演算で実行する &&
「>」と「>>」はどちらもファイル出力使うコマンド