1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Git Custom Merge Driver

Last updated at Posted at 2021-06-19

環境

Envrionment Version
Ubuntu 20.04.2 LTS
Windows 10.0.19041
Git 2.25.1

Git Custom Merge Driverとは

Gitのマージ処理を低レベルでカスタマイズできるGitに備わっている機構のこと。
強力な反面、事故りやすいので理解したうえで利用が必要。

作り方

  1. Custom Merge Driverの設定
  2. 適用ファイルの指定

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へ追記する。

フォーマット

 .gitattributes
ファイルパス merge={戦略名}

注意

./{filename}この書き方だと動かなかった。

{filename}ルート直下のreadme.mdならば、以下のように記載する。

readme.md merge=alwaysTheirs

実際に作ってみる。

いつでもマージする側(featureブランチ)が優先されるマージ戦略を作る。
対象ファイルは、readme.txtにする。

Custom Merge Driverの設定

Sh作成

mergeAlwaysTheirs.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リポジトリに入れる。

適用ファイルの指定

PORJECT_ROOT/.gitattributes
.readme.md merge="alwaysTheirs"

実際の動き

masterブランチの内容

readme.md
# Title
## Header

featureブランチの更新内容

readme.md
# Title2
## Header2

masterブランチの更新内容

readme.md
# 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

readme.md
# 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演算で実行する &&
「>」と「>>」はどちらもファイル出力使うコマンド

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?