Gitでマージの競合を解決する方法


4769

Gitでマージの競合を解決するにはどうすればよいですか?


31
次のブログ投稿は、正しい方向に進むはずのGitとのマージ競合を処理する方法に関する非常に良い例を示しているようです。取り扱いとGitの中で競合の回避
mwilliams

4
マージツール(kdiff3jebaird.com/2013/07/08/…)を構成してから、git mergetoolを使用できます。大規模な開発チームで作業しているときは、常にマージの競合が発生します。
Grady G Cooper、

定期的にダウンストリームをマージすることで、ほとんどのマージの競合を軽減できることを忘れないでください!
Ant P


8
興味深い質問:2008年に尋ねられたところ、100%オープンエンドで、それが本当に何であるかについてのヒントはまったくありません(GUIについてですか?gitコマンドについてですか?セマンティクスについてですか?プッシュ/プルまたは単なる一般的な競合についてですか?)-完全に答えられません。30の回答、それらすべて(一目でわかる限り)は、多かれ少なかれ、さまざまなdiff3およびマージツールについて進んでいますが、どれも受け入れられません。トップ投票の回答は、デフォルトのgitインストールではそのままでは機能しないコマンドについて言及しています。2017年の今日、SEのスタートページに到達し、130万回の視聴と数千の投票がありました。魅力的です。
AnoE 2017

回答:


2912

試してください: git mergetool

競合ごとに手順を示すGUIが開き、マージ方法を選択できます。後で少し手作業で編集する必要がある場合もありますが、通常はそれだけで十分です。手作業ですべてを行うよりもはるかに優れています。

@JoshGloverコメントによると:

コマンド

GUIをインストールしない限り、必ずしもGUIを開くとは限りません。git mergetool私のために実行すると、vimdiff使用されました。あなたが代わりにそれを使用するには、次のいずれかのツールをインストールすることができますmeldopendiffkdiff3tkdiffxxdifftortoisemergegvimdiffdiffuseecmergep4mergearaxisvimdiffemerge

以下は、vimdiffマージの競合を解決するために使用するサンプル手順です。このリンクに基づく

ステップ1:端末で次のコマンドを実行する

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

これにより、vimdiffがデフォルトのマージツールとして設定されます。

手順2:端末で次のコマンドを実行します

git mergetool

手順3:次の形式でvimdiffディスプレイが表示されます

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

これらの4つのビューは

LOCAL –これは現在のブランチからのファイルです

BASE –共通の祖先、両方の変更前のファイルの外観

REMOTE –ブランチにマージするファイル

マージ–マージ結果、これがリポジトリに保存されます

ctrl+ を使用して、これらのビュー間を移動できますwctrl+にw続けてを使用して、マージされたビューに直接アクセスできjます。

ここここに vimdiffナビゲーションに関する詳細情報

ステップ4。次の方法でマージされたビューを編集できます

REMOTEから変更を取得する場合

:diffg RE  

BASEから変更を取得したい場合

:diffg BA  

ローカルから変更を取得したい場合

:diffg LO 

ステップ5。保存、終了、コミット、クリーンアップ

:wqa 保存してviを終了

git commit -m "message"

git clean diffツールで作成された余分なファイル(* .origなど)を削除します。


54
git mergetool -y一度に多くのファイルをマージする場合、いくつかのキーストロークを保存するために使用できます。
davr

373
まあ、それをインストールしない限り、それは必ずしもGUIを開くわけではありません。git mergetool私のために実行すると、vimdiff使用されました。代わりに、次のいずれかのツールをインストールして使用できますmeld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge
Josh Glover、

31
良い点ジョシュ。ubuntuでは、私はmeldで最高の幸運を手に入れました。その3方向マージ表示は悪くありません。OSXではgitが適切なデフォルトを選択しました。
Peter Burns、

18
これはKDiff3を開きました。使い方が全くわかりません。
デビッドマードック

7
Beyond Compare 3を今すぐ使用することもできます(git mergetool -t bc3)。
AzP 2012

1703

上から考えられる使用例を以下に示します。

あなたはいくつかの変更をプルするつもりですが、おっと、あなたは最新ではありません:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

したがって、最新の状態に戻って再試行しますが、競合があります。

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

したがって、変更を確認することにします。

git mergetool

ああ、ああ、私の上流はいくつかのことを変更しましたが、私の変更を使用するだけです...いいえ...彼らの変更...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

そして最後に

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

たーだ!


19
私はいつもではなく、新しいファイルで上書きする必要があり、私はバイナリファイル(アートアセット)としてマージエラーがたくさんあったので、これは超便利だったものは必ず失敗するようでマージ、ので「マージ」
petrocket

188
気をつけて!--oursと--theirsの意味が逆になります。--ours ==リモート。--theirs ==ローカル。参照git merge --help
mmell

57
私の場合、-theirs =リモートリポジトリ、-ours =自分のローカルリポジトリであることを確認します。@mmellコメントの反対です。
Aryo

24
@mmellどうやらリベースでのみ。参照this question
Navin、2013年

184
みんな、「私たち」と「彼ら」は、あなたがマージするかリベースするかどうかに関係しています。あなたのしている場合、マージ、そして、「私たち」とあなたにマージしている支店、そして「彼らは」あなたがマージしているブランチです。いつだリベース、その後、「私たち」とコミットしているあなたにリベースをへ一方、「それら」は、リベースするコミットを指します。

736

マージツールが競合や解決策を理解するのに役立つことはめったにありません。私は通常、テキストエディターで競合マーカーを確認し、補足としてgit logを使用する方がうまくいきます。

ここにいくつかのヒントがあります:

ヒント1

私が見つけた最良のことは、「diff3」マージ競合スタイルを使用することです。

git config merge.conflictstyle diff3

これにより、次のような競合マーカーが生成されます。

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

中央のセクションは、共通の祖先がどのように見えるかです。これは、上位バージョンと下位バージョンと比較して、各ブランチで何が変更されたかをよりよく理解できるため、便利です。これにより、各変更の目的がよりよくわかります。

競合が数行しかない場合、これにより、一般的に競合が非常に明白になります。(競合を修正する方法を知ることは非常に異なります。他の人が取り組んでいることを認識する必要があります。混乱している場合は、その人をあなたの部屋に呼び、彼らがあなたが探しているものを見ることができるようにするのがおそらく最善です。で。)

競合がさらに長い場合は、3つのセクションをそれぞれ切り取り、「mine」、「common」、「theirs」などの3つの個別のファイルに貼り付けます。

次に、次のコマンドを実行して、競合を引き起こした2つの差分ハンクを確認できます。

diff common mine
diff common theirs

これは、マージツールを使用する場合とは異なります。マージツールには、競合しないdiffハンクもすべて含まれるためです。気が散ることがわかります。

ヒント2

誰かがすでにこれについて述べていますが、各diff hunkの背後にある意図を理解することは、一般に、競合がどこから発生し、どのように対処するかを理解するのに非常に役立ちます。

git log --merge -p <name of file>

これは、共通の祖先とマージする2つのヘッドの間でそのファイルに接触したすべてのコミットを示しています。(したがって、マージする前に両方のブランチにすでに存在するコミットは含まれません。)これにより、現在の競合の要因ではないことが明らかなdiff hunkを無視できます。

ヒント3

自動化ツールで変更を確認します。

自動テストがある場合は、それらを実行します。lintがある場合は、それを実行します。ビルド可能なプロジェクトの場合は、コミットする前にビルドするなどしてください。すべての場合において、変更が何かを壊していないことを確認するために、少しテストを行う必要があります。(いや、衝突のないマージでさえ、動作しているコードが壊れる可能性があります。)

ヒント4

事前に計画します。同僚と通信します。

事前に計画を立て、他の人が取り組んでいることを認識することは、マージの競合を防ぎ、かつ/またはそれらをより早く解決するのに役立ちます-詳細はまだ新鮮です。

たとえば、あなたと別の人が両方とも同じファイルセットに影響する異なるリファクタリングに取り組んでいることがわかっている場合は、事前に互いに話し合い、それぞれがどのような種類の変更であるかをよりよく理解する必要があります作る。計画した変更を並行ではなく逐次的に実行すると、時間と労力を大幅に節約できます。

大量のコードにまたがる主要なリファクタリングの場合、逐次作業を強く検討する必要があります。一人が完全なリファクタリングを実行している間、誰もがコードのその領域での作業を停止します。

(時間のプレッシャーなどが原因で)連続して作業できない場合は、予想されるマージの競合について連絡することで、詳細を考慮した上で問題を早期に解決できます。たとえば、同僚が1週間の間に一連の中断を伴うコミットを行っている場合、その週の間に1日に1回または2回、その同僚のブランチをマージ/リベースすることを選択できます。こうすることで、マージ/リベースの競合が見つかった場合、数週間待ってすべてを1つの大きな塊にマージするよりも早く解決できます。

ヒント5

マージが不確かな場合は、強制しないでください。

特に多数の競合するファイルがあり、競合マーカーが数百行をカバーしている場合、マージは圧倒的に感じるかもしれません。多くの場合、ソフトウェアプロジェクトを見積もるとき、危険なマージの処理などのオーバーヘッドアイテムのための十分な時間が含まれていないため、各競合の分析に数時間を費やすのは本当の抵抗のように感じられます。

長期的には、事前に計画を立て、他の人が取り組んでいることを認識することは、マージの競合を予測し、短時間でそれらを正しく解決するための準備をするための最良のツールです。


6
diff3オプションは、マージで使用できる優れた機能です。私が遭遇した唯一のGUIは、それがPERFORCEのそれであることを示しています。これはp4merge、PERFORCEの他のツール(私は使用していませんが、不満を聞いた)とは別にインストールして使用できます。
alxndr 2014年

3
マージの競合が発生したリベースの試行後:$ git log --merge -p build.xml output:fatal:--merge without MERGE_HEAD?
Ed Randall

Branch1からの1つのファイルに変更があり、Branch2でそのファイルが削除された場合はどうなりますか。どうすればマージの競合を解決できますか?1つのブランチの変更を維持してマージできるgitを使用する方法はありますか?
Honey

git config merge.conflictstyle diff3- ありがとうございます。これは驚くべきことであり、優れた3方向マージGUIを見つけて(そして$$を支払う)ことから解放されました。IMOは、ローカル/リモートだけでなく、共通の祖先を示しているので、これは良いです、そしてショーは最後にはGUIはしません(私の知る限り)ログの行をコミットします。コミットは、どのコードがどのブランチに属しているかを特定するのに役立ちます。
ffxsam 2017

私は時々、diff3衝突スタイルが大部分が同一である巨大なdiff hunkをもたらす一方で、デフォルトはより小さく、より管理しやすいhunkを生成することを発見しました。残念ながら、バグレポートに使用できる再生プログラムがありません。ただし、この問題が発生した場合は、オプションを一時的にオフにすることを検討してください。
Dave Abrahams 2017

348
  1. 競合しているファイルを特定します(Gitがこれを通知するはずです)。

  2. 各ファイルを開き、差分を調べます。Gitはそれらを区別します。うまくいけば、各ブロックのどのバージョンを保持するかは明らかです。コードをコミットした他の開発者と話し合う必要があるかもしれません。

  3. ファイルの競合を解決したら git add the_file

  4. すべての競合を解決git rebase --continueたら、完了時にGitが実行するように指示したコマンドを実行します。


38
@Justin Git は、ファイルを追跡するのではなく、コンテンツを追跡すると考えてください。次に、更新したコンテンツがリポジトリにないため、追加する必要があることが簡単にわかります。この考え方は、Gitが空のフォルダーを追跡しない理由も説明します。これらは技術的にはファイルですが、追跡するコンテンツはありません。
Gareth

7
コンテンツが存在する場合、コンテンツの2つのバージョンがあるため、競合が発生します。したがって、「git add」は正しく聞こえません。そして、競合が解決された後にその1つのファイルだけをコミットしたい場合(git add、git commit)は機能しません(致命的:マージ中に部分的なコミットを実行できません。)
Dainius

1
はい、技術的には、これは尋ねられたとおりの質問に答えますが、私の意見では申し訳ありません。あるブランチを別のブランチと同じにすることの意味は何ですか?もちろん、マージは、競合を持つことになりますの...
Thufir

5
Thulfir:あるブランチを別のブランチと同じにすることについて誰が言ったのですか?「あるブランチを別のブランチと同じにする」ことなく、マージする必要があるさまざまなシナリオがあります。1つは、開発ブランチが完了し、その変更をマスターブランチに組み込みたい場合です。この後、開発ブランチを削除できます。もう1つは、最終的な最終的なマージをマスターに簡単にするために、開発ブランチをリベースする場合です。
Teemu Leisti 2012

4
@JustinGrantはgit addファイルをインデックスにステージングします。リポジトリには何も追加されませgit commitリポジトリに追加します。この使用法は、マージにとって意味があります。マージは、自動的にマージできるすべての変更を自動的にステージングします。残りの変更をマージし、完了したらそれらをインデックスに追加するのはユーザーの責任です。
Mark E. Haase

105

Stack Overflowの質問の回答、Gitでのマージの中止、特に問題のあるファイルのさまざまなバージョンを表示する方法を示すCharles Baileyの回答を確認してください。

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

また、「-m」オプションを「git checkout -m」にチェックアウトします。これにより、さまざまなハエをワークスペースに抽出して戻すことができます
qneill

これは私を救った。各ファイルを個別に見ると、各ブランチで何をしていたのかを思い出すことができました。その後、私は選択する決定を下すことができました。
ローマー

99

マージの競合は、ファイルに同時に変更が加えられると発生します。これを解決する方法は次のとおりです。

git CLI

競合状態になった場合の簡単な手順は次のとおりです。

  1. 競合するファイルのリストに注意してください:(git statusUnmerged pathsセクションの)。
  2. 次のいずれかの方法で、ファイルごとに競合を個別に解決します。

    • GUIを使用して競合を解決します:(git mergetool最も簡単な方法)。

    • リモート/その他のバージョンを受け入れるには、次を使用しますgit checkout --theirs path/file。これにより、そのファイルに対して行ったローカルでの変更が拒否されます。

    • ローカル/私たちのバージョンを受け入れるには、次を使用します: git checkout --ours path/file

      ただし、競合するリモート変更が何らかの理由で行われたため、注意が必要です。

      関連:gitの「ours」と「theirs」の正確な意味は何ですか?

    • 競合するファイルを手動で編集し、<<<<</の間のコードブロックを探して>>>>>から、上または下からバージョンを選択します=====。参照:競合の表示方法

    • パスとファイル名の競合はgit add/ で解決できますgit rm

  3. 最後に、次のコマンドを使用して、コミットの準備ができているファイルを確認しますgit status

    の下にまだファイルがありUnmerged paths、競合を手動で解決した場合は、次の方法で解決したことをGitに知らせますgit add path/file

  4. すべての競合が正常に解決された場合は、次の方法で変更をコミットし、git commit -a通常どおりリモートにプッシュします。

参照:GitHubのコマンドラインからのマージ競合の解決

実際のチュートリアルについては、シナリオ5-Katacodaによるマージの競合の修正を確認してください。

DiffMerge

Windows、macOS、Linux / Unixでファイルを視覚的に比較およびマージできるDiffMergeをうまく使用しました。

3つのファイル間の変更をグラフィカルに表示でき、自動マージ(安全な場合)と、結果のファイルの編集を完全に制御できます。

DiffMerge

画像ソース:DiffMerge(Linuxスクリーンショット)

単にダウンロードして、次のようにリポジトリで実行します。

git mergetool -t diffmerge .

マックOS

macOSでは、次の方法でインストールできます。

brew install caskroom/cask/brew-cask
brew cask install diffmerge

そしておそらく(提供されていない場合)PATHに次の追加の単純なラッパーを配置する必要があります(例:) /usr/bin

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

その後、次のキーボードショートカットを使用できます。

  • - Alt- Up/ Down前/次の変更にジャンプします。
  • - Alt- Left/ Right左または右からの変更を確定します

または、opendiff(Xcode Toolsの一部)を使用して、2つのファイルまたはディレクトリをマージし、3つ目のファイルまたはディレクトリを作成することもできます。


79

小さなコミットを頻繁に行う場合は、まずでコミットコメントを確認しgit log --mergeます。次にgit diff、競合を表示します。

数行を超える競合については、外部GUIツールで何が起こっているかを確認するのが簡単です。私はopendiffが好きです-Gitはvimdiff、gvimdiff、kdiff3、tkdiff、meld、xxdiffもサポートしており、すぐに使用できgit config merge.tool "your.tool"ます。他のものをインストールできます。選択したツールを設定してからgit mergetoolます。

競合を解決するためにファイルを編集するたびにgit add filename、はインデックスを更新し、diffはそれを表示しなくなります。すべての競合が処理され、それらのファイルがgit add-ed git commitされると、マージが完了します。


8
ここでは「git add」を使用するのが本当のトリックです。あなたはコミットしたくないかもしれません(多分あなたは隠したいかもしれません)が、マージを完了するには "git add"を実行する必要があります。(manpageにはありませんが)mergetoolが追加を行うと思いますが、手動でマージを行う場合は、「git add」を使用して完了する必要があります(コミットしたくない場合でも)。
nobar

47

マージの競合マーカーとは何かを理解するには、競合がどのように提示されるか、またはGitのgit mergeドキュメントを参照してください。

また、「競合を解決する方法セクションでは、競合を解決する方法について説明しています。

競合が発生した後、次の2つのことを行うことができます。

  • マージしないことを決定します。必要なクリーンアップは、インデックスファイルをHEADコミットにリセットして2を元に戻し、2と3によって行われた作業ツリーの変更をクリーンアップすることだけです。git merge --abortこれに使用できます。

  • 競合を解決します。Gitは作業ツリーで競合をマークします。ファイルを形に編集git addし、インデックスに追加します。git commit契約を結ぶために使用します。

多くのツールを使用して競合を回避できます。

  • mergetoolを使用します。git mergetoolマージを実行するグ​​ラフィカルなマージツールを起動します。

  • 差分を見てください。とバージョンのgit diff両方からの変更を強調する3方向の差分が表示されます。HEADMERGE_HEAD

  • 各ブランチの差分を見てください。git log --merge -p <path>最初にHEADバージョンの差分を表示し、次にMERGE_HEADバージョンを表示します。

  • オリジナルを見てください。git show :1:filenameショー共通の祖先、git show :2:filenameショーHEADバージョン、およびgit show :3:filenameショーMERGE_HEADバージョン。

マージ競合マーカーとその解決方法については、Pro Gitブックのセクション「基本的なマージ競合」を参照してください。


42

私または自分のバージョンを完全なものにするか、個々の変更を確認して、それぞれについて決定する必要があります。

私または彼らのバージョンを完全に受け入れます

私のバージョンを受け入れる(ローカル、私たちのもの):

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

彼らのバージョンを受け入れます(リモート、彼ら):

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

すべての競合ファイルに対して実行したい場合は、以下を実行します。

git merge --strategy-option ours

または

git merge --strategy-option theirs

すべての変更を確認し、個別に受け入れます

  1. git mergetool
  2. 変更を確認し、それぞれのバージョンを受け入れます。
  3. git add <filename>
  4. git commit -m "merged bla bla"

デフォルトmergetoolコマンドラインで動作します。コマンドラインのmergetoolの使い方は別の質問です。

このためのビジュアルツールをインストールして実行することもできmeldます。

git mergetool -t meld

ローカルバージョン(ours)、 "base"または "merged"バージョン(現在のマージ結果)、およびリモートバージョン(theirs)が開きます。完了したら、マージしたバージョンを保存し、git mergetool -t meld「マージする必要のあるファイルがなくなる」まで再度実行し、ステップ3と4に進みます。


このコマンド:git checkout --theirs-<filename>はすべてのファイルを<filename>ではなくすべてのファイルに変更しました
Donato

実は私は間違っていました。これは指定されたファイルのみを更新します。
Donato

40

マージの競合を半手動で解決したいEmacsユーザーの場合:

git diff --name-status --diff-filter=U

競合解決が必要なすべてのファイルを表示します。

これらのファイルを1つずつ開くか、次のように一度にすべて開きます。

emacs $(git diff --name-only --diff-filter=U)

Emacsで編集が必要なバッファーにアクセスするときは、次のように入力します。

ALT+x vc-resolve-conflicts

これにより、3つのバッファー(mine、theirs、およびoutputバッファー)が開きます。「n」(次の領域)、「p」(プロビジョニング領域)を押して移動します。'a'と 'b'を押して、鉱山またはその地域をそれぞれ出力バッファーにコピーします。または、出力バッファを直接編集します。

終了したら、「q」を押します。Emacsは、このバッファーを保存するかどうかを尋ねます:はい。バッファを完了した後、終端から実行することで解決済みとしてマークします。

git add FILENAME

すべてのバッファタイプが終了したら

git commit

マージを終了します。


33

ボーナス:

上記の回答のプル/フェッチ/マージと言えば、興味深い生産的なトリックを共有したいと思います。

git pull --rebase

この上記のコマンドは、私のgitライフで最も便利なコマンドであり、多くの時間を節約しました。

リモートサーバへ新しくコミット変更をプッシュする前に、してみてくださいgit pull --rebaseというgit pullとマニュアルmerge、それが自動的に同期、最新のリモートサーバーの変更(+マージフェッチで)でしょうし、あなたの地元の最新のgitのログに先頭にコミット入れます。手動のプル/マージについて心配する必要はありません。

競合する場合は、

git mergetool
git add conflict_file
git rebase --continue

詳細はhttp://gitolite.com/git-pull--rebase


32

簡単に言うと、リポジトリの1つでの変更が重要ではないことをよく知っており、他の変更を優先してすべての変更を解決したい場合は、以下を使用します。

git checkout . --ours

リポジトリを優先して変更を解決する、または

git checkout . --theirs

他のリポジトリまたはメインリポジトリを優先して変更を解決します

または、GUIマージツールを使用してファイルを1つずつステップ実行するか、マージツールがp4mergeであると言うか、すでにインストールした名前を書き込む必要があります

git mergetool -t p4merge

ファイルを完成させたら、保存して閉じる必要があるため、次のファイルが開きます。


2
git checkout。
Ramesh Chand

競合を手動で解決したい場合は、Visual Studio Codeでフォルダーを開いてみてください。これにより、ファイルに競合のマークが付けられ、すべての内部に競合行が色付けされます
Mohamed Selim

31

次の手順に従って、Gitのマージの競合を修正してください。

  1. Gitステータスを確認します: git status

  2. パッチセットを入手する: git fetch(Gitコミットから適切なパッチをチェックアウト)

  3. ローカルブランチをチェックアウトします(この例ではtemp1): git checkout -b temp1

  4. マスターから最近のコンテンツをプルしますgit pull --rebase origin master

  5. mergetoolを起動し、競合をチェックして修正します...そしてリモートブランチの変更を現在のブランチで確認します: git mergetool

  6. ステータスをもう一度確認してください: git status

  7. mergetoolによってローカルに作成された不要なファイルを削除します。通常、mergetoolは* .orig拡張子を持つ追加ファイルを作成します。そのファイルは重複しているため、削除してローカルで変更を修正し、正しいバージョンのファイルを追加してください。 git add #your_changed_correct_files

  8. ステータスをもう一度確認してください: git status

  9. 変更を同じコミットIDにコミットします(これにより、新しい個別のパッチセットが回避されます): git commit --amend

  10. マスターブランチにプッシュgit push(Gitリポジトリに)


28

3つのステップがあります。

  1. コマンドによって競合を引き起こすファイルを見つける

    git status
    
  2. 次のようにマークされた競合が見つかるファイルを確認します

    <<<<<<<<head
    blablabla
    
  3. それをあなたが望む方法に変更してから、コマンドでコミットしてください

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

私のために働いた!ありがとう!
Nuwan Jayawardene 2017

リベース中にこれを行う場合は注意が必要です。git commitではなくgit rebase --continueを使用する必要があります
Samuel Dauzon

27

他の人が詳しく述べているように、いくつかの方法でマージの競合を修正できます。

本当の鍵は、変更がローカルおよびリモートのリポジトリでどのように流れるかを知ることだと思います。これの鍵は追跡ブランチを理解することです。私は、トラッキングブランチを、ローカルの実際のファイルディレクトリと起点として定義されたリモートとの間の「中間の欠落部分」と考えていることがわかりました。

私は個人的に、これを回避するために2つのことを習慣にしています。

の代わりに:

git add .
git commit -m"some msg"

これには2つの欠点があります-

a)すべての新しい/変更されたファイルが追加されます。これには、不要な変更が含まれる場合があります。
b)最初にファイルリストを確認する必要はありません。

だから代わりに私はします:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

このようにすると、追加するファイルについてより慎重になり、メッセージのエディターを使用しながらリストを確認し、もう少し考えることができます。-mオプションではなくフルスクリーンエディターを使用すると、コミットメッセージも改善されます。

[更新-時間の経過とともに、次のように切り替えました:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

また、(そしてあなたの状況にもっと関連しています)、私は避けようとします:

git pull

または

git pull origin master.

プルはマージを意味するため、マージしたくない変更がローカルにある場合、マージされたコードやマージされるべきではないコードのマージ競合が簡単に発生する可能性があります。

代わりに私はやろうとします

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

これも役に立つかもしれません:

gitブランチ、フォーク、フェッチ、マージ、リベース、クローン、違いは何ですか?


ねえ、私はあなたの答えをちょっと理解しました。しかし、私はgithubマージの競合に不慣れなため、何か不足していると思います。何をするとき、あなたのローカルの変更に起こるgit checkout mastergit fetch して git rebase --hard origin/master
Suhaib

私はあなたが何をすべきかについてより多くの詳細を追加する必要があると信じています。私を混乱させる別の例、あなたの答えであなたは述べました:私たちはそうしますgit add .、それは私たちがフォローアップできるようにローカルの変更を保存しgit checkout masterますか?それとも2つの異なるシナリオですか?
Suhaib 2017

@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option hard 'の使用法:git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]または:git rebase [-i] [オプション] [--exec <cmd>] [--onto <newbase>] --root [<branch>]または:git rebase --continue | --abort | --skip | --edit-todo `
likejudo

24

CoolAJ86の答えはほとんどすべてを要約しています。同じコードの両方のブランチに変更がある場合は、手動でマージする必要があります。任意のテキストエディタで競合しているファイルを開くと、次の構造が表示されます。

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

等号と山括弧を削除しながら、新しいコードにしたい方法で、代替案の1つまたは両方の組み合わせを選択します。

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

私にとって常に機能するとは限らず、通常、2つのブランチ間で異なるすべてのコミットが表示されます。これは、を使用--してパスをコマンドから分離する場合にも発生します。

この問題を回避するために私が行うことは、2つのコマンドラインを1回の実行で開くことです

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

そして他の

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

$MERGED_IN_BRANCH私がマージしたブランチ[path]と競合しているファイルで置き換える。このコマンドは、..2つのコミット間の()間のすべてのコミットをパッチ形式でログに記録します。上記のコマンドのように片側を空のままにすると、gitが自動的に使用しますHEAD(この場合、マージするブランチ)。

これにより、2つのブランチが分岐した後に、どのコミットがファイルに入ったかを確認できます。通常は、競合の解決がはるかに簡単になります。


16

使用する patience

patienceマージ再帰戦略を使用して競合を解決することについて他の誰も話していないことに驚いています。大きなマージの競合の場合は、patienceすると良い結果が得られます。アイデアは、個々の行ではなくブロックを照合しようとするというものです。

たとえば、プログラムのインデントを変更すると、デフォルトのGitマージ戦略が{、さまざまな関数に属する単一の波括弧と一致する場合があります。これはpatience

git merge -s recursive -X patience other-branch

ドキュメントから:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

共通祖先との比較

マージの競合があり、他の人がブランチを変更するときに何を考えていたかを確認したい場合は、ブランチ(ブランチではなく)を直接共通の祖先と直接比較する方が簡単な場合があります。そのために使用できますmerge-base

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

通常、特定のファイルの変更のみを確認します。

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

私の場合、これはマージの競合をうまく解決しませんでした。なんらかの理由で、C#プロジェクトのconfig行が重複して保持されていたためです。それは私が以前持っていたFILE IS DIFFERENT全体よりも友好的でしたが
Mathijs Segers

15

2016年12月12日以降、ブランチをマージしてgithub.comで競合解決できます

したがって、古い回答からここに提供されているコマンドラインやサードパーティのツールを使用したくない場合は、GitHubのネイティブツールを使用してください。

このブログ投稿では詳細を説明していますが、基本的には、UIを介して2つのブランチを「マージ」すると、「競合の解決」オプションが表示され、これらのマージの競合に対処できるエディターが表示されます。

ここに画像の説明を入力してください


これはgithubについて尋ねているのではないので、私は非常に貧弱な答えで​​あると私が見ているものに反対票を投じました。
mschuett 2017年

1
@mschuettは正解です。問題は「gitでの競合を解決する方法」ではなく、「gitで競合を解決する方法」です。違いがあり、gitとgithubが同じものであると考える人はすでに多すぎます。そのため、その感情を伝えるものはすべて間違っています。
Patrick Mevzek

15

ブランチ(テスト)からマスターにマージする場合は、次の手順に従います。

ステップ1:ブランチに行く

git checkout test

ステップ2

git pull --rebase origin master

ステップ3:競合がある場合は、これらのファイルに移動して変更します。

ステップ4:これらの変更を追加する

git add #your_changes_files

ステップ5

git rebase --continue

手順6:それでも競合がある場合は、手順3に戻ります。競合がない場合は、以下を実行します。

git push origin +test

ステップ7:テストとマスターの間に競合はありません。直接マージを使用できます。


13

衝突を避けるために、私は常に以下の手順に従います。

  • git checkout master(マスターブランチに来てください)
  • git pull(マスターを更新して最新のコードを取得)
  • git checkout -b mybranch(新しいaブランチをチェックアウトし、そのブランチで作業を開始して、マスターが常にトランクの上部に留まるようにします。)
  • git add。AND git commit AND git push(変更後のローカルブランチ上)
  • git checkout master(マスターに戻ってください。)

これで、同じことを実行して、必要な数のローカルブランチを維持し、必要に応じてブランチにgitチェックアウトを実行するだけで、同時に作業できます。


12

マージの競合は、さまざまな状況で発生する可能性があります。

  • 「git fetch」を実行してから「git merge」を実行する場合
  • 「git fetch」を実行してから「git rebase」を実行する場合
  • 「git pull」を実行するとき(これは実際には上記の条件の1つと同じです)
  • 「git stash pop」を実行すると
  • gitパッチを適用する場合(メールに転送するためにファイルにエクスポートされるコミットなど)

競合を解決するには、Gitと互換性のあるマージツールをインストールする必要があります。個人的にはKDiff3を使用していますが、使いやすく便利です。Windowsバージョンはこちらからダウンロードできます。

https://sourceforge.net/projects/kdiff3/files/

ところで、Git Extensionsをインストールする場合、セットアップウィザードにKdiff3をインストールするオプションがあります。

次にgit configsをセットアップして、Kdiffをmergetoolとして使用します。

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(パスをKdiff exeファイルの実際のパスに置き換えることを忘れないでください。)

次に、マージの競合に遭遇するたびに、次のコマンドを実行する必要があります。

$git mergetool

次に、Kdiff3を開き、最初にマージの競合を自動的に解決しようとします。ほとんどの競合は自然に解決され、残りは手動で修正する必要があります。

Kdiff3は次のようになります。

ここに画像の説明を入力してください

次に、完了したらファイルを保存し、競合のある次のファイルに移動して、すべての競合が解決されるまで同じことを繰り返します。

すべてが正常にマージされているかどうかを確認するには、mergetoolコマンドを再度実行するだけで、次の結果が得られます。

$git mergetool
No files need merging

8

これは、エディター内ですべてを実行することを好む、私のようなVIMユーザー向けの代替手段を追加するための答えです。


TL; DR

ここに画像の説明を入力してください


Tpopeは、VIMのfugitiveと呼ばれるこの素晴らしいプラグインを思い付きました。インストールしたら、実行:Gstatusして競合のあるファイルをチェックし、:Gdiffし、3つの方法でGitを開いてマージします。

3ウェイマージに入ると、fugitiveを使用すると、マージするブランチの変更を次の方法で取得できます。

  • :diffget //2、元の(HEAD)ブランチから変更を取得します。
  • :diffget //3、マージブランチから変更を取得します:

ファイルのマージが完了したら:Gwrite、マージされたバッファーに入力します。Vimcastsは、この手順を詳細に説明する素晴らしいビデオをリリースしました。


6

VSコード用Gitlense

あなたはジトレンセを試すことができます for VS Codeをます。主な機能は次のとおりです。

3.競合を簡単に解決します。

私はすでにこの機能が好きです:

ここに画像の説明を入力してください

2.現在のラインのせい。

ここに画像の説明を入力してください

3.溝のせい

ここに画像の説明を入力してください

4.ステータスバーのせい

ここに画像の説明を入力してください

そして、あなたがそれらをここでチェックできる多くの機能があります


5

git fetch
git checkout ブランチ
git rebaseマスター

このステップでは、優先IDEを使用して競合を修正しようとします

このリンクに従って、ファイルhttps://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/の競合を修正する方法を確認できます

git add
git rebase --continue
git commit --amend
git push origin HEAD:refs / drafts / master(ドラフトのようにプッシュ)

今、すべてがうまくいき、あなたのコミットは間違いなく見つかります

これがこの問題に関するすべての人に役立つことを願っています。


3

まだ編集していない場合は、Visual Studioコードを編集してみてください。マージしようとすると(そしてマージの競合が発生すると)、VSコードがマージの競合を自動的に検出します。

元の変更がどのように変更されたかを示し、受け入れる incomingか、

current change(マージ前の元のものを意味します) '?.

それは私のために役立ちました、それはあなたのためにも働くことができます!

PS:gitをコードとVisual Studio Codeで構成した場合にのみ機能します。



2

Visual Studio(私の場合は2015)を使用している人向け

  1. VSでプロジェクトを閉じます。特に大きなプロジェクトでは、UIを使用してマージすると、VSが異常動作する傾向があります。

  2. コマンドプロンプトでマージを実行します。

    git checkout target_branch

    git merge source_branch

  3. 次に、VSでプロジェクトを開き、チームエクスプローラー->ブランチに移動します。Mergeが保留中であり、競合するファイルがメッセージのすぐ下にリストされているというメッセージが表示されます。

  4. 競合するファイルをクリックすると、マージ、比較、ソースの取得、ターゲットの取得のオプションが表示されます。VSのマージツールは非常に使いやすいです。


非常に大規模なプロジェクトでVS Code 2017を使用しており、プロジェクトを閉じる必要はありません。それはそれをかなりうまく処理します:)
protoEvangelion 2017

2

IDEとしてintelliJを使用している場合は、親をブランチにマージしてみてください。

git checkout <localbranch>
git merge origin/<remotebranch>

このようなすべての競合が表示されます

A_MBPro:test anu $ git merge origin /自動マージsrc / test / java / com /.../ TestClass.java CONFLICT(コンテンツ):src / test / java / com /.../ TestClass.javaでマージの競合

TestClass.javaファイルがintelliJに赤で表示されることに注意してください。また、gitステータスが表示されます

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

ファイルをintelliJで開きます。次のセクションがあります。

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

HEADはローカルブランチでの変更で、origin /はリモートブランチからの変更です。ここで、必要なものを保持し、不要なものを削除します。その後、通常の手順で実行できます。あれは

   git add TestClass.java
   git commit -m "commit message"
   git push

2

Microsoftのビジュアルコードを使用して競合を解決しています。使い方はとても簡単です。ワークスペースでプロジェクトを開いたままにします。競合を検出して強調表示します。さらに、GUIのオプションを使用して、HEADまたは着信から保持したい変更を選択できます。 ここに画像の説明を入力してください

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