25

'master' と 'release' の 2 つのブランチがあります。

のような 1 つのファイルがあり、fileAこれら 2 つのブランチで異なるバージョンを維持したいと考えています。

しかし、毎回、「リリース」を「マスター」にマージする必要があります。どうすれば達成できますか。「マスター」内がブランチ内「リリース」fileAによって上書きされません。fileA

4

1 に答える 1

17

Pro Gitは、 8.2 Git のカスタマイズ — Git 属性の「マージ戦略」</a> セクションで、この効果を得る方法を説明しています。

マージ戦略

Git 属性を使用して、プロジェクト内の特定のファイルに対して異なるマージ戦略を使用するように Git に指示することもできます。非常に便利なオプションの 1 つは、Git に競合がある場合に特定のファイルをマージしようとせず、他の人のマージよりも自分の側を使用するように指示することです。

これは、プロジェクト内のブランチが分岐しているか特殊化されている場合に役立ちますが、そこから変更をマージして戻したい場合や、特定のファイルを無視したい場合に役立ちます。2 つのブランチで異なるという名前のデータベース設定ファイルがありdatabase.xml、データベース ファイルを台無しにすることなく他のブランチにマージしたいとします。次のように属性を設定できます。

database.xml merge=ours

次に、ダミーのoursマージ戦略を次のように定義します。

$ git config --global merge.ours.driver true

他のブランチでマージすると、マージがdatabase.xmlファイルと競合するのではなく、次のように表示されます。

$ git merge topic
Auto-merging database.xml
Merge made by recursive.

この場合、database.xml元のバージョンのままです。

あなたの状況に適用し、最初に作成しますfileA

$ echo 'master fileA' > fileA
$ git add fileA ; git commit -m "master fileA"
[master (root-commit) fba9f1a] master fileA
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 fileA

そしてそれを特別なものにします。

$ echo fileA merge=ours > .gitattributes
$ git add .gitattributes ; git commit -m 'fileA merge=ours'
[master 98e056f] fileA merge=ours
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 .gitattributes
$ git config --global merge.ours.driver true

次に、代表releaseブランチを作成します。

$ git checkout -b release
Switched to a new branch 'release'
$ echo 'release fileA' > fileA
$ git add fileA ; git commit -m 'release fileA'
[release 53f3564] release fileA
 1 files changed, 1 insertions(+), 1 deletions(-)

まだ特別なことは何も起こっていません。バージョン管理は、現時点では想定どおりに機能しているだけです。

次に、機能 Bを に実装しmasterます。

$ git checkout master
Switched to branch 'master'
$ touch featureB ; echo 'With Feature B' >> fileA
$ git add featureB fileA ; git commit -m 'Feature B'
[master 443030f] Feature B
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 featureB

興奮を抑えるようにしてください。

ここで、特別なマージ ドライバーの出番です。master私たちのヒーローは、新しいコードを からにマージしたいと考えていreleaseます。最初のスイッチ分岐。

$ git checkout release
Switched to branch 'release'

fileA私たちが期待するものを含むサニティチェック。

$ cat fileA
release fileA

からフィーチャ Bをマージしmasterます。

$ git merge master
Auto-merging fileA
Merge made by recursive.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 featureB

この線Auto-merging fileAは、何か特別なことが起こったという手がかりです。それはそう:

$ cat fileA
release fileA

使い方

gitattributes ドキュメントのセクション「カスタム マージ ドライバの定義」</a> で説明しています。

変数のmerge.*.driver値は、祖先のバージョン ( %O)、現在のバージョン ( %A)、および他のブランチのバージョン ( %B) をマージするために実行するコマンドを構築するために使用されます。これら 3 つのトークンは、コマンド ラインのビルド時にこれらのバージョンの内容を保持する一時ファイルの名前に置き換えられます…</p>

マージ ドライバは、マージの結果を with という名前のファイル%Aに上書きして残し、正常にマージできた場合は 0 のステータスで終了し、競合があった場合は 0 以外のステータスで終了することが期待されます。

カスタムoursドライバーは、この機構をほとんど使用せず、ゼロ ステータスで終了するtrueコマンドのみを使用します。fileAこれは、現在使用しているブランチから開始するため、望ましい効果が得られます。これが必要な結果です。その後、マージ上書きフェーズでは何も実行せず (つまり、 によって指定された他のブランチのバージョンを無視します%B)、最後に git に通知します。正常な終了ステータスですべて問題ありません。

于 2017-12-22T19:16:08.880 に答える