git-merge --dry-runオプションはありますか?


725

多くの競合が発生する可能性があるリモートブランチをマージしています。競合があるかどうかはどうすればわかりますか?

のようなものが表示さ--dry-runれませんgit-merge


5
Gitを使用すると分岐が安価になるので、コピーをチェックアウトしてから、予行演習を行う必要がないのはなぜですか。後でコピーを捨てることができます。
アレクサンダーミルズ

回答:


812

前述のように、--no-commitフラグを渡しますが、早送りのコミットを避けるために--no-ff、次のようにも渡します。

$ git merge --no-commit --no-ff $BRANCH

段階的な変更を確認するには:

$ git diff --cached

また、早送りのマージであっても、マージを元に戻すことができます。

$ git merge --abort

51
これはすばらしいことですが、作業コピーは変更されます。あなたのレポは、ライブウェブサーバであるなら、あなたはで競合してファイルを提供することができます。
dave1010

21
作業コピーに影響を与えずにマージを実際に行うことはできません。
mipadi

55
確かに、しかし、のようなものgit merge --only-if-there-wont-be-any-conflictsか、git diff --show-conflicts <commit>本当に便利になります。残念ながらそれはまだ可能ではありませんか、それとも何か不足していますか?
dave1010 2010

344
@ dave1010ライブウェブサーバーでマージを処理してはいけません。それが開発ボックスの目的です!「prod」ブランチを修正してから、実際のウェブサーバーにプッシュします。
jpswain、2011年

52
ライブ/本番サーバーで作業している場合は、何もしたくありませんgit pull --ff-only
ThiefMaster 2012年

237

リポジトリとそのリモートの間の競合を自動的に検出するメソッドを実装する必要がありました。このソリューションはメモリ内でマージを行うため、インデックスや作業ツリーには影響しません。これは、この問題を解決できる最も安全な方法だと思います。仕組みは次のとおりです。

  1. リモートをリポジトリにフェッチします。例えば: git fetch origin master
  2. git merge-baseを実行します。 git merge-base FETCH_HEAD master
  3. git merge-tree:を実行しますgit merge-tree mergebase master FETCH_HEADmergebaseは、前の手順でmerge-baseが出力した16進数のIDです)

ここで、リモートマスターとローカルマスターをマージしたいとしますが、任意のブランチを使用できます。git merge-treeメモリ内でマージを実行し、結果を標準出力に出力します。パターンのGrep <<または>>。または、出力をファイルに出力して確認することもできます。'changed in both'で始まる行を見つけた場合、おそらく競合が発生しています。


41
この答えは、作業コピーやインデックスに触れずにクリーンなソリューションであるため、過小評価されています。
sschuberth

23
ところで、手順2と3は、バッククォートのLinuxコンソールのオペレータは、インプレース評価し、その内容用いて、1つのステップに併合することができる:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.gを

15
.gitconfigの[alias]に追加:dry = "!f(){git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "#devをマスターにマージする方法を確認:git dry開発者マスター
Noel、

8
私の新しいお気に入りのGITライン:git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"単に素晴らしい!+100
Rudie 2013

4
これをテストしたところ、両方のブランチが同じファイルを変更する「両方で変更された」フラグマージのgreppingが見つかりました。マージの競合が発生しなくてもです。実際の競合のみを特定するには+<<<<<<< .our、次のように始まる競合マークアップをgrepする必要があることがわかりました。そのため、次のようなgrep式を使用しますgrep -q '^+<* \.our$'
Guy

55

これに対する私の単純な総当たりの解決策は次のとおりです。

  1. 「プリマスター」ブランチを作成します(もちろんマスターから)

  2. 必要なすべてのものをこのプレマスターにマージします。
    次に、マスターに触れずにマージがどのように行われたかを確認できます。

    • プレマスターをマスターにマージOR
    • リリースしたいすべてのブランチをマスターにマージします

とにかく、@ orange80のアドバイスに従います。


5
私は@akostajtiソリューションが好きですが、これはまだ別の過小評価されているオプションです。実際、私は防御的になり、新しい一時ブランチを作成することを好みます(もちろん、競合が予想される場合のみです。それ以外の場合は、やり過ぎになります)。問題が発生した場合は、単に削除してください。
jakub.g

1
これが「ダーティ」なソリューションであるかどうかはわかりませんが、実際に機能します。私はそれが好きです!(Y)
サラ2015年

3
これは受け入れられる解決策であるはずです。迅速、簡単、安全、可逆、直感的で、開始前にコミットされていない変更がない限り、副作用はありません。
Bob Ray

3
このソリューションは、gitの動作を理解していないことを示しています。ブランチは単なるポインタであり、冗長なポインタを作成するだけです。ブランチのマージに何らかの影響を与える可能性があるが、それはできないという悪感情を持っています。git merge --abort競合git reset --hard HEAD~1があった場合、マージまたはがあった場合は、いつでも実行できgit reset --hard origin/masterます。別のブランチを作成すると、安心感が得られますが、gitの動作を理解すれば、見当違いの恐れであることを理解できます。作業コピーを変更しないことに懸念がある場合、これは解決策を提供しません。
Thibault D.

@ thibault-dクリーンなブランチから始めない場合のソリューションの複雑さを考えてください。 git merge --no-commit早送りできる場合はマージを中止しません。 git merge --abortマージされた場合は機能しません。これをスクリプトとして記述したい場合はgit merge、さまざまな種類の競合を説明するのに十分なエラーコードを返さないため、扱いにくいです。新しいブランチを操作することで、壊れたスクリプトがリポジトリを手動の操作を必要とする状態のままにしないようにします。もちろん、何も失うことはありません。しかし、他の方法で構築する方が簡単です。
Erik Aronesty

47

gitとのマージを元に戻すのはとても簡単なので、予行演習についても心配する必要はありません。

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

編集:以下のコメントに記載されているように、作業ディレクトリまたはステージング領域に変更がある場合は、上記を実行する前にそれらを隠しておくことをお勧めします(そうしないと、git reset上記に従って非表示になります)


7
マージが早送り(FF)になるかどうかを単にチェックすることは、リストをチェックするか、git branch --contains HEADまたはさらに直接、単に使用することですgit merge --ff-only
ブライアンフィリップス

7
git reset --hardは、gitにある数少ない情報の削除とバックアウトのないコマンドの1つなので、細心の注意を払って使用する必要があります。そのため、-1
Kzqai

8
@Tchalvakまだreflogがあります。
キサキ

3
--dry-run「マージが早送りされるかどうかを単にチェックする」ことはありません。それはマージがする正確な出力を返します:ファイル、競合など。ffは本当に面白くないのでしょうか?
ルディー

3
どうgit stash; git reset --hardですか?@BrianPhillips
コードウィスパー

41

私はこれを行うためのエイリアスを作成し、魅力のように機能します、私はこれを行います:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

今すぐ電話します

git mergetest <branchname>

競合があるかどうかを確認する。


鮮やかさ!私はこれを守っています。
qbert65536

28

現在のブランチをリモートブランチと比較するだけで、プル/マージを実行したときに何が変更されるかがわかります。

#see diff between current master and remote branch
git diff master origin/master

1
面白いアイデア。その出力をどのように見て、マージが機能するかどうかを判断できますか?
MatrixFrog、2011年

6
これは競合が発生するかどうかを通知しません...しかし、プル/マージを実行した場合に何が起こるかについての一般的な考えを提供します。
timh

10
これは、2つのブランチの違いを伝えるだけで、マージの結果がどうなるかはわかりません。マージは、コミットされた時期に応じて、異なるブランチから変更を自動的に取得する場合があるため、これは重要な違いです。したがって、本質的に、差分を実行すると、実際にはマージプロセスが古い変更より新しい変更を自動的に取得するときに、変更の一部が元に戻されると思われる場合があります。それが理にかなっていると思います。
markquezada 2011年

3
@mirthlabのコメントを基に、誰かが以前に「ours」マージ戦略(または他の手動マージ修正プログラム)を使用してマージを実行した場合、diffとmergeの間には大きな違いがあります。差分には、「マージ済み」としてすでにカウントされている差分も表示されます。
タオ

21

それには、request-pull gitコマンドを使用します。これにより、マージ時に発生するすべての変更を確認できますが、ローカルまたはリモートのリポジトリで何も行う必要はありません。

たとえば、「feature-x」という名前のブランチをマスターブランチにマージするとします。

git request-pull master origin feature-x

何が起こるか(何もしないで)の要約が表示されます。

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

-pパラメータを追加すると、変更されたすべてのファイルに対してgit diffを実行した場合とまったく同じように、完全なパッチテキストも取得されます。


3
コマンドラインオプションに何masteroriginして何をするかでこれを少し明確にすることができます。たとえば、ローカルbranch1にいrequest-pullて、ローカルの機能ブランチでを実行したい場合はどうbranch2でしょうか。それでも必要originですか?もちろん、いつでもドキュメントを読むことができます。
Ela782

残念ながら、このコマンドはRev#2がブランチ名である場合にのみ機能し、ハッシュには機能しません:/
Jared Grubb

20

誰もまだパッチの使用を提案していないことに驚いています。

からyour_branchへのマージをテストしたいとmasterします(私はあなたがmasterチェックアウトしたと仮定しています):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

これでうまくいくはずです。

次のようなエラーが発生した場合

error: patch failed: test.txt:1
error: test.txt: patch does not apply

つまり、パッチは成功せず、マージによって競合が発生します。出力がないことは、パッチがクリーンであり、ブランチを簡単にマージできることを意味します


これによって実際に作業ツリーが変更されるわけでないことに注意してください(もちろん、パッチファイルの作成は除きますが、後で安全に削除できます)。git-applyのドキュメントから:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

私よりもgitの方が賢い、または経験が豊富な人への注意:ここで私が間違っていて、このメソッドが通常のマージとは異なる動作をする場合は、私に知らせてください。この質問が存在していた8年以上前に、この一見明白な解決策をだれも提案しなかったことは奇妙に思われます。


この方法はこの質問に受け入れられた回答あり、「gitは「再帰的な」マージ戦略を使用できませんでした」や「パッチファイルは新しいファイルにエラーを与える」などの警告がいくつかあります。そうでなければ、素晴らしいようです。
neno 2017年

1
一時的なパッチファイルを作成しない短い方法:git diff master your_branch | git apply --check
ks1322

9

これは興味深いかもしれません:ドキュメントから:

複雑な競合を引き起こしたマージを試みてやり直したい場合は、git merge --abortを使用して回復できます。

しかし、それを素朴な(しかし遅い)方法で行うこともできます。

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

(注:/ tmpにクローンを作成するだけでは機能しません。コミットされていない変更が競合しないようにするには、コピーが必要です)。


2
必要なのがハンマーだけの場合... :) +1
カイザー2014

クリーンコピーがで得ることができcp -r repository/.git /tmp/repository/.gitcd /tmp/repositorygit reset --hardgit add --allgit reset --hard、(良い測定のために)git status(それはきれいだことを確認するため)。
ADTC 2017年

8

これは古い質問であることは承知していますが、Google検索で初めて表示されます。

Gitはマージ時に--ff-onlyオプションを導入しました。

送信元http : //git-scm.com/docs/git-merge


--ffのみ

現在のHEADが既に最新であるか、マージが早送りとして解決できる場合を除き、マージを拒否してゼロ以外のステータスで終了します。

これを行うと、マージと早送りが試行されますが、それができない場合は中止され、早送りを実行できなかったが、作業中のブランチはそのままになります。早送りできる場合は、作業中のブランチでマージを実行します。このオプションは、でも使用できますgit pull。したがって、次のことができます。

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
元の質問で望んでいなかった早送りで実行できる場合は、マージが行われます。受け入れられた答えにはそれを修正する残りの半分があると思います。
オットー

本当に、派手なgitプロンプトは、私がこの種のことをする必要性を取り除きます。
オットー

2
それは本当に同じではありません。早送りは競合があることを意味しないため、マージを解決できないため、ゼロ以外のステータスで終了します。それは単に歴史が分岐し、マージコミットが必要であることを意味します。
ADTC 2017年

7

git logを使用して、masterブランチからfeatureブランチで何が変更されたかを確認します

git log does_this_branch..contain_this_branch_changes

例-マスターにマージされた/マージされていない機能ブランチのコミットを確認するには:

git log master..feature_branch

3

BからAに早送りしたい場合は、git log B..Aに何も表示されていないことを確認する必要があります。つまり、AにはBにないものはありません。しかし、B..Aに何かがあったとしても、競合なしでマージできる可能性があるため、上記は2つのことを示しています。つまり、早送りが行われるため、競合が発生しません。


2

私の解決策は、後方にマージすることです。

ブランチをリモートの「ターゲット」ブランチにマージする代わりに、そのブランチを自分のブランチにマージします。

git checkout my-branch
git merge origin/target-branch

競合があるかどうかを確認し、解決方法を計画できます。

その後、gitを使用してマージを中止するかmerge --abort、(競合が発生せず、マージが発生した場合)を介して以前のコミットにロールバックできますgit reset --hard HEAD~1


-2

作業コピーの一時的なコピーを作成し、それにマージして、2つを比較します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.