gitでマージをプレビューするにはどうすればよいですか?


397

gitブランチ(メインラインなど)があり、別の開発ブランチにマージしたい。それとも私ですか?

このブランチを本当にマージするかどうかを決定するために、マージが何を行うかをプレビューしたいのですが。できれば、適用されているコミットのリストを見ることができます。

これまでのところ、私が思いつくことができる最高のものはmerge --no-ff --no-commit、そしてそれからdiff HEADです。


17
結果が気に入らなかったらいいgit mergeと思いgit reset --keep HEAD@{1}ます。
Jan Hudec

3
コミットのリストとその差分を確認しても、必ずしも全体像がわかるとは限らないことに注意してください。マージが重要な場合、特に競合がある場合、マージの実際の結果は少し興味深いかもしれません。
Cascabel

2
あなたの元の方法はそれを正確に行います。私のコメントの要点は、個々のdiffを確認することはすべて順調で良いことですが、複雑なマージがある場合、マージされたすべてのコミットが個別に良好であったとしても、驚くべき結果になる可能性があるということです。
Cascabel

2
@Jan:何らかの理由で、git reset --keep HEAD@{1}返されたfatal: Cannot do a keep reset in the middle of a merge.ヘルプ?
moey

3
--previewgit-mergeにオプションがないのはなぜですか?
Gaui

回答:


285

私にとって最も効果的な解決策は、マージを実行し、競合がある場合はそれを中止することです。この特定の構文は、私にはすっきりとシンプルに感じられます。これは以下の戦略2です。

ただし、現在のブランチをめちゃくちゃにしないようにしたい場合、または競合の存在に関係なくマージする準備ができていない場合は、そのブランチから新しいサブブランチを作成してマージします。

戦略1:安全な方法–一時的なブランチからマージする:

git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch

そうすれば、競合が何であるかを確認したいだけの場合は、一時的なブランチを破棄できます。マージを「中止」する必要がないため、作業に戻ることができます。「mybranch」をもう一度チェックアウトするだけで、マージされたコードやマージの競合がブランチになくなります。

これは基本的に予行演習です。

戦略2:間違いなくマージしたいが、競合がない場合のみ

git checkout mybranch
git merge some-other-branch

gitが競合を報告した場合(および競合がある場合のみ)、次に次のように実行できます。

git merge --abort

マージが成功した場合、それを中止することはできません(リセットのみ)。

マージする準備ができていない場合は、上記のより安全な方法を使用してください。

[編集:2016年11月-ほとんどの人が「安全な方法」を探しているようで、戦略1を2に交換しました。ストラテジー2は、対処する準備ができていない競合がマージにある場合、マージを単に中止できることを示しています。コメントを読む場合は注意してください!]


2
戦略2の+1。マージ時に何が入るかを正確に示す一時的なブランチ。戦略1は、この特定のケースで回避しようとしていることです。
Gordolio 2015

2
安全な方が最初になるように戦略を変更することをお勧めします(私の心理トレーニングが実施されます-ほとんどの人は、「安全」という言葉を明確に使用しているにもかかわらず、最良の選択肢が最初の選択肢であると想定します)が、それ以外は、優れていますジョブ。
paxdiablo

6
git merge --no-ff --no-commit変更を直接コミットしたくない場合は、これを行うことができます。これにより、別のブランチの「必要性」がなくなり、変更の確認が少し簡単になります。
ジェラルドファンヘルデン2016

まったくマージしたくない場合は、実際にコードをいくつか記述してからブランチにコミットして、ブランチをテストサーバーにデプロイできるようにしても、リバートする必要はありませんgit merge --no-ff --no-commitか?見た目がgit merge --abort気に入らなくても、その後はまだできると思いますか?たとえマージが衝突を引き起こさなくても?
Kasapo

ほとんどの人はコピーアンドペーストを好み、あまり考えないようにしています。したがって、戦略1では、一時的なローカルブランチでマージを中止しgit reset --hard HEAD、別のブランチgit checkout <different branch name>をチェックアウトして一時的なブランチを削除する方法も追加する可能性がありgit delete -b <name of temporary branch>ます。
user3613932 2017

401
  • git log ..otherbranch
    • 現在のブランチにマージされる変更のリスト。
  • git diff ...otherbranch
    • 共通の祖先(マージベース)からマージされるものの先頭への差分。2つのドットと比較して特別な意味を持つ3つのドット注意してください(以下を参照)。
  • gitk ...otherbranch
    • 前回マージされてからのブランチのグラフィカル表現。

空の文字列はを意味するHEADため、の..otherbranch代わりにHEAD..otherbranchです。

2つのドットと3つのドットの意味は、リビジョンを一覧表示するコマンド(log、gitkなど)とは少し異なります。ログや他の人のために2つのドットは(a..b)であるすべてのものを意味bはありませんa(と3つのドットa...b)のみの一つであるすべてのものを意味aかをb。しかし、diffは2つのリビジョンで機能し、2つのドット(a..b)で表されるより単純なケースはato からの単純な違いでbあり、3つのドット(a...b)は共通の祖先とbgit diff $(git merge-base a b)..b)の違いを意味します。


7
3番目の点は、欠けていた部分でした。ありがとう!。ログのアプローチもうまく機能し、-p --reverse ..otherbranchにマージされる内容を確認する良い方法のように思えるログイン
Glenjamin

1
git checkout masterこれを試す前に行方不明でした。私の変更がすべて上書きされると言っているのはなぜだろうと思っていました...
Droogans 2013年

5
git show ..otherbranch現在のブランチにマージされる変更と差分のリストが表示されます。
Gaui、2014年

4
これは、特にチェリーピックの場合、完全に正確ではありません。
void.pointer 16

2
@ void.pointer、gitは通常のマージではサクランボを特別に扱いませんので、ここでも扱いません。マージ戦略を作成することもできますが、私の知る限り、そうではありませんでした。
Jan Hudec

19

私のような人なら、と同等のものを探していますsvn update -n。以下はトリックを行うように見えます。git fetchローカルリポジトリに比較する適切な更新があるように、必ず最初に実行してください。

$ git fetch origin
$ git diff --name-status origin/master
D       TableAudit/Step0_DeleteOldFiles.sh
D       TableAudit/Step1_PopulateRawTableList.sh
A       manbuild/staff_companies.sql
M       update-all-slave-dbs.sh

または、頭からリモコンへの差分が必要な場合:

$ git fetch origin
$ git diff origin/master

IMOこのソリューションは、「マージして中止」を提案するトップソリューションよりもはるかに簡単で、エラーが発生しにくい(したがってリスクがはるかに少ない)。


1
必要が$ git checkout target-branchあります$ git diff --name-status ...branch-to-be-merged(3つのドットが必須なので、そのまま入力します)
Lu55

これに欠けていることが1つあります。どのファイルが競合するかは表示されません。ブランチ上で変更されたファイルと同じ「M」マーカーが付いていますが、競合することなくマージできます。
peterflynn 2016年

2012年は状況が異なっていたかもしれませんが、最近のマージの中止は非常に信頼できるようです。そのため、現時点でこれを「はるかに簡単でエラーが発生しにくい」と特徴づけることは公平ではないと思います。
David Z

8

ここでのほとんどの回答は、クリーンな作業ディレクトリと複数のインタラクティブなステップ(スクリプトには不適切)が必要か、またはすべてのケースで機能しない場合があります。同じ。

masterブランチにマージdevelopした場合、ブランチで何が変わるかを実際に確認するには、次のようにします。

git merge-tree $(git merge-base master develop) master develop

それは配管コマンドなので、それはあなたが何を意味するのかを推測するのではなく、明示する必要があります。また、出力を色分けしたり、ポケットベルを使用したりしないため、完全なコマンドは次のようになります。

git merge-tree $(git merge-base master develop) master develop | colordiff | less -R

https://git.seveas.net/previewing-a-merge-result.html

(リンクを提供してくれたDavid Normingtonに感謝)

PS:

マージの競合が発生すると、通常の競合マーカーが出力に表示されます。例:

$ git merge-tree $(git merge-base a b ) a b 
added in both
  our    100644 78981922613b2afb6025042ff6bd878ac1994e85 a
  their  100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
 a
+=======
+b
+>>>>>>> .their

ユーザー@dreftymacは良い点を示しています。これは、ステータスコードから簡単に把握できないため、スクリプト作成には適していません。競合マーカーは状況(削除されたものと変更されたものなど)によってかなり異なる場合があり、grepも難しくなります。注意してください。


1
@hrabanこれは正解のように見えますが、まだ1つの要素が欠けているようです。このアプローチでは、競合マーカーが存在するかどうかを確認するために、ユーザーが出力を「目玉」にする必要があります。true競合があり、競合falseがない場合に単純に戻るアプローチがありますか(たとえば、「眼球」テストまたは人間の介入を必要としないブール値)。
dreftymac

1
@dreftymacはその効果に対して何も見つけることができません。あなたは次のようなものを使うことができますgit merge-tree ... | grep -q '^[a-z].*in both$' && echo conflict || echo safe to mergeが、それは微妙です。私はおそらく事件を忘れています。代わりに、競合マーカーを確認したいですか?たとえば、これはおそらく「削除された、私たちの変更された」スタイルの競合をキャッチしません。(チェックしたところ、競合マーカーも表示されていないため、ここで安全にするには細心の注意を
払う

1
less -R設定を変更せずにカラー出力を処理するために使用します。
ジャコモアルゼッタ

@GiacomoAlzettaに感謝します。更新しました。
hraban

6

すでに変更を取得している場合、私のお気に入りは次のとおりです。

git log ...@{u}

それにはgit 1.7.xが必要です。 @{u}それは、より汎用性のより少しですので、表記は上流分岐のための「速記」ですgit log ...origin/master

注:zshと拡張glogを使用している場合は、次のようなことを行う必要があります。

git log ...@\{u\}

6

既存の回答に加えて、マージ前に差分やログを表示するエイリアスを作成できます。多くの答えは省略しますfetch、マージを「プレビュー」する前に最初に行うべきことされています。これは、これら2つのステップを1つに結合したエイリアスです(Mercurialのhg incoming/に似たものをエミュレートします)outgoing)。

したがって、「git log ..otherbranch "を基にして、次のものをに追加できます~/.gitconfig

...
[alias]
    # fetch and show what would be merged (use option "-p" to see patch)
    incoming = "!git remote update -p; git log ..@{u}"

対称性のために、次のエイリアスを使用して、プッシュする前にコミットされ、プッシュされるものを示すことができます。

    # what would be pushed (currently committed)
    outgoing = log @{u}..

そして、「git incoming」を実行して多くの変更を表示するか、「git incoming -p」を実行してパッチ(つまり、「diff」)を表示し、「git incoming --pretty=oneline」、簡潔な要約などを表示できます。その後、(オプションで)を実行できますgit pullして実際にマージします。(ただし、すでにフェッチしているため、マージは直接行うことができます。)

同様に、「git outgoing」は、「」を実行した場合に何がプッシュされるかを示しますgit push


3

git log currentbranch..otherbranchマージすると現在のブランチに入るコミットのリストが表示されます。コミットの詳細を提供するログへの通常の引数は、より多くの情報を提供します。

git diff currentbranch otherbranch1つになる2つのコミットの差分を取得します。これは、マージされるすべてのものを提供する差分になります。

これらは役に立ちますか?


2
実際、間違っています。currentbranchgit log otherbranch..currentbranchのコミットのリストを提供しますgit diff otherbranch currentbranchあなたは何をしたいことは、マージベースからマージ頭に差分であるので、それができる役に立たないなどとしてについてです現在の先端までの被マージされたバージョンからdiffを提供します。
Jan Hudec、2011

ありがとう。Treeishesの名前を切り替えました。
Noufal Ibrahim

3

プルリクエスト-私はすでに提出されたアイデアのほとんどを使用しましたが、私がよく使用するものは(特に別の開発者からのものである場合)プルリクエストを実行することです。場所。私はGitHubがgitではないことを知っていますが、便利です。


2

使い捨ての方法で実際にマージを実行する(Kasapoの回答を参照)ことを除けば、これを確認する信頼できる方法はないようです。

そうは言っても、これはわずかに近い方法です。

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

これは、どのコミットがマージに入るのかを公平に示しています。差分を表示するには、を追加し-pます。のいずれかを追加し、ファイル名を表示するには--raw--stat--name-only--name-status

git diff TARGET_BRANCH...SOURCE_BRANCHアプローチの問題(Jan Hudecの回答を参照)は、ソースブランチにクロスマージが含まれている場合、ターゲットブランチにすでにある変更の差分が表示されることです。


1

多分これはあなたを助けることができますか? git-diff-tree -2つのツリーオブジェクトを介して検出されたblobのコンテンツとモードを比較します


1

競合するファイルを確認する前兆としてgit mergeコマンドを使用したくありません。マージしたくないのですが、マージする前に潜在的な問題を特定したいと思います。自動マージによって隠されてしまう可能性のある問題です。私が探していた解決策は、いくつかの共通の祖先に対して、将来マージされる両方のブランチで変更されたファイルのリストをgit spitで出力する方法です。そのリストを入手したら、他のファイル比較ツールを使用して、さらに詳細を調べることができます。私は何度も検索しましたが、ネイティブのgitコマンドで必要なものがまだ見つかりません。

他の誰かを助けるために、ここに私の回避策があります:

このシナリオでは、QAと呼ばれるブランチがあり、最後の製品リリース以降に多くの変更が加えられています。私たちの最後の製品リリースは「15.20.1」でタグ付けされています。QAブランチにマージするnew_stuffという別の開発ブランチがあります。QAとnew_stuffはどちらも、15.20.1タグの「フォロー」(gitkによる報告)をコミットすることを示しています。

git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files

これらの特定のファイルを対象とすることになぜ私が興味を持っているのかについてのいくつかの議論があります:

Gitマージを信頼するにはどうすればよいですか?

/software/199780/how-far-do-you-trust-automerge

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