Gitリポジトリでのマージの競合を解決したいと考えています。
どうやってやるの?
Gitリポジトリでのマージの競合を解決したいと考えています。
どうやってやるの?
試す:git mergetool
各競合をステップスルーするGUIが開き、マージ方法を選択できます。後で少し手作業で編集する必要がある場合もありますが、通常はそれだけで十分です。確かにすべてを手作業で行うよりもはるかに優れています。
Josh Gloverのコメントによると:
コマンド
GUIをインストールしない限り、必ずしもGUIを開くとは限りません。私のために走っ
git mergetool
た結果、vimdiff
使用されました。次のツールのいずれかをインストールして、代わりmeld
に使用opendiff
でき ます:、、、、、、、、、、、、、、、、 。kdiff3
tkdiff
xxdiff
tortoisemerge
gvimdiff
diffuse
ecmerge
p4merge
araxis
vimdiff
emerge
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つのビューは
ローカル–これは現在のブランチのファイルです
BASE –共通の祖先、両方の変更前のファイルの外観
REMOTE –ブランチにマージするファイル
MERGED –マージ結果、これがリポジトリに保存されるものです
ctrl+を使用して、これらのビュー間を移動できますw。ctrl+wの後に。を使用すると、MERGEDビューに直接アクセスできますj。
vimdiffナビゲーションの詳細については、こちらとこちらをご覧ください。
ステップ4。MERGEDビューは次のように編集できます
REMOTEから変更を取得したい場合
:diffg RE
BASEから変更を取得したい場合
:diffg BA
ローカルから変更を取得したい場合
:diffg LO
ステップ5。保存、終了、コミット、クリーンアップ
:wqa
保存してviを終了します
git commit -m "message"
git clean
diffツールによって作成された余分なファイル(* .origなど)を削除します。
上から考えられるユースケースは次のとおりです。
いくつかの変更をプルするつもりですが、おっと、あなたは最新ではありません:
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.
タダ!
マージ ツールが競合や解決策を理解するのに役立つことはめったにありません。私は通常、テキスト エディターでコンフリクト マーカーを確認し、補足として git log を使用する方がうまくいきます。
いくつかのヒントを次に示します。
私が見つけた最良の方法は、「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"、"irs" などの 3 つの個別のファイルにカット アンド ペーストします。
次に、次のコマンドを実行して、競合の原因となった 2 つの diff ハンクを確認できます。
diff common mine
diff common theirs
これは、マージ ツールを使用する場合と同じではありません。マージ ツールには競合しないすべての差分ハンクも含まれるためです。それは気を散らすものだと思います。
誰かがすでにこれについて言及しましたが、各 diff ハンクの背後にある意図を理解することは、通常、競合がどこから発生し、どのように処理するかを理解するのに非常に役立ちます。
git log --merge -p <name of file>
これは、共通の祖先とマージしている 2 つのヘッドの間でそのファイルに触れたすべてのコミットを示しています。(したがって、マージ前に両方のブランチに既に存在するコミットは含まれません。) これにより、現在の競合の要因ではないことが明らかな diff ハンクを無視することができます。
自動ツールで変更を確認します。
自動化されたテストがある場合は、それらを実行します。lintがある場合は、それを実行します。ビルド可能なプロジェクトの場合は、コミットする前にビルドします。どのような場合でも、変更によって何も壊れていないことを確認するために少しテストを行う必要があります。(まあ、競合のないマージでも、作業中のコードが壊れる可能性があります。)
事前に計画してください。同僚と通信します。
事前に計画を立て、他の人が取り組んでいることを認識しておくと、マージの競合を防ぎ、早期に解決するのに役立ちます (詳細はまだ覚えていません)。
たとえば、あなたと他の人が両方とも同じファイル セットに影響を与えるさまざまなリファクタリングに取り組んでいることがわかっている場合は、事前にお互いに話し合って、それぞれがどのような種類の変更を行っているかをよりよく理解する必要があります。作る。計画された変更を並行して行うのではなく順次行うと、時間と労力を大幅に節約できます。
大量のコードにまたがる大規模なリファクタリングの場合は、連続して作業することを強く検討する必要があります。1 人が完全なリファクタリングを実行している間、全員がコードのその領域での作業を停止します。
連続して作業できない場合 (おそらく時間的なプレッシャーが原因で)、予想されるマージの競合について連絡することで、少なくとも問題をより早く解決するのに役立ちますが、詳細はまだ覚えています。たとえば、同僚が 1 週間にわたって破壊的な一連のコミットを行っている場合、その同僚のブランチをその週に 1 日 1 回または 2 回マージ/リベースすることを選択できます。そうすれば、マージ/リベースの競合が見つかった場合でも、すべてを 1 つの大きな塊にマージするのに数週間待つ場合よりも迅速に解決できます。
マージに確信が持てない場合は、強制しないでください。
競合するファイルが多数あり、競合マーカーが何百行にも及ぶ場合は特に、マージが圧倒されることがあります。多くの場合、ソフトウェア プロジェクトを見積もる際、危険なマージの処理などのオーバーヘッド項目に十分な時間を含めていません。
長期的には、前もって計画を立て、他の人が取り組んでいることを認識することが、マージの競合を予測し、短時間で正しく解決できるように準備するための最良のツールです。
競合しているファイルを特定します (Git はこれを教えてくれるはずです)。
各ファイルを開き、差分を調べます。Git はそれらを区別します。各ブロックのどのバージョンを保持するかが明確になることを願っています。コードをコミットした仲間の開発者と話し合う必要があるかもしれません。
ファイル内の競合を解決したら、git add the_file
.
すべての競合を解決git rebase --continue
したら、完了時に Git が指示したコマンドを実行します。
ファイルに同時に変更が加えられると、マージの競合が発生します。これを解決する方法は次のとおりです。
git
CLI競合状態になった場合の簡単な手順は次のとおりです。
git status
(Unmerged paths
セクションの下)。次のいずれかの方法で、各ファイルの競合を個別に解決します。
GUI を使用して競合を解決します: git mergetool
(最も簡単な方法)。
リモート/他のバージョンを受け入れるには、次を使用しますgit checkout --theirs path/file
。これにより、そのファイルに対して行ったローカルの変更がすべて拒否されます。
ローカル/私たちのバージョンを受け入れるには、次を使用します。git checkout --ours path/file
ただし、何らかの理由で競合するリモート変更が行われたため、注意が必要です。
<<<<<
競合するファイルを手動で編集し、 /の間のコード ブロックを探して、>>>>>
上または下からバージョンを選択します=====
。参照:競合の表示方法.
git add
パスとファイル名の競合は/で解決できますgit rm
。
最後に、次を使用してコミットの準備ができているファイルを確認しますgit status
。
の下にまだファイルがUnmerged paths
あり、競合を手動で解決した場合は、次の方法で解決したことを Git に知らせてくださいgit add path/file
。
すべての競合が正常に解決された場合は、次の方法で変更をコミットし、git commit -a
通常どおりリモートにプッシュします。
関連項目: GitHubのコマンド ラインからマージの競合を解決する
実用的なチュートリアルについては、以下を確認してください: Scenario 5 - Fixing Merge Conflicts by Katacoda。
Windows、macOS、および Linux/Unix でファイルを視覚的に比較およびマージできるDiffMergeの使用に成功しました。
3 つのファイル間の変更をグラフィカルに表示でき、自動マージ (安全な場合) と、結果のファイルの編集を完全に制御できます。
画像ソース: DiffMerge (Linux スクリーンショット)
ダウンロードしてリポジトリで実行するだけです:
git mergetool -t diffmerge .
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 "$@"
次に、次のキーボード ショートカットを使用できます。
別の方法として、2 つのファイルまたはディレクトリをマージして 3 つ目のファイルまたはディレクトリを作成できるopendiff (Xcode ツールの一部) を使用することもできます。
Stack Overflow question Aborting a merge in 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
小さなコミットを頻繁に行っている場合は、コミット コメントを で確認することから始めます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
、インデックスが更新され、差分には表示されなくなります。すべての競合が処理され、それらのファイルがgit add
-edgit commit
されると、マージが完了します。
自分のバージョンまたはそのバージョンの完全なバージョンが必要か、個々の変更を確認してそれぞれについて決定したいかのどちらかです。
私または彼らのバージョンを完全に受け入れる:
私のバージョンを受け入れます (ローカル、私たちのもの):
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
すべての変更を確認し、個別に受け入れます
git mergetool
git add <filename>
git commit -m "merged bla bla"
デフォルトmergetool
はコマンドラインで動作します。コマンドラインmergetoolの使い方は別の問題です。
このためのビジュアル ツールをインストールmeld
して実行することもできます。
git mergetool -t meld
ローカル バージョン (私たちのもの)、「ベース」または「マージされた」バージョン (マージの現在の結果)、およびリモート バージョン (彼らのもの) を開きます。完了したらマージされたバージョンを保存し、git mergetool -t meld
「マージする必要のあるファイルはありません」と表示されるまで再度実行してから、手順 3. と 4. に進みます。
How Conflicts Are Presentedを参照するか、Git のgit merge
ドキュメントを参照して、マージ競合マーカーとは何かを理解してください。
また、「競合を解決する方法」セクションでは、競合を解決する方法について説明しています。
競合を確認したら、次の 2 つのことを行うことができます。
合体しないと決める。必要な唯一のクリーンアップは、インデックス ファイルを
HEAD
コミットしてリバース 2. にリセットすることと、2. および 3. によって行われた作業ツリーの変更をクリーンアップすることです。git merge --abort
これに使用できます。競合を解決します。Git は作業ツリーで競合をマークします。ファイルを形に編集し、
git add
それらをインデックスに編集します。git commit
取引を封印するために使用します。いくつかのツールを使用して競合を処理できます。
マージツールを使用します。
git mergetool
マージを行うグラフィカルなマージツールを起動します。差分を見てください。とバージョン
git diff
の両方からの変更を強調表示して、3 方向の差分を表示します。HEAD
MERGE_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ブック セクションBasic Merge Conflictsで、マージ競合マーカーとその解決方法についても読むことができます。
マージの競合を半手動で解決したい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、および出力バッファー) が開きます。「n」(次のリージョン)、「p」(プレビュー リージョン) を押してナビゲートします。'a' と 'b' を押して、鉱山またはその地域をそれぞれ出力バッファーにコピーします。および/または出力バッファを直接編集します。
終了したら:「q」を押します。Emacs は、このバッファーを保存するかどうかを尋ねます: はい。バッファを終了した後、ターミナルから実行して解決済みとしてマークします。
git add FILENAME
すべてのバッファタイプが終了したら
git commit
マージを終了します。
前の回答のプル/フェッチ/マージについて言えば、興味深い生産的なトリックを共有したいと思います。
git pull --rebase
この上記のコマンドは、私の Git ライフの中で最も便利なコマンドであり、多くの時間を節約できました。
新しくコミットした変更をリモート サーバーにプッシュする前に、手動でgit pull --rebase
試してみてください。これにより、最新のリモート サーバーの変更が (フェッチ + マージで) 自動的に同期され、ローカルの最新のコミットが Git ログの一番上に配置されます。手動のプル/マージについて心配する必要はありません。git pull
merge
競合が発生した場合は、使用してください
git mergetool
git add conflict_file
git rebase --continue
詳細については、「git pull –rebase」は何をしますか?
Git でのマージの競合を修正するには、次の手順に従ってください。
Git のステータスを確認します: git status
パッチセットを取得します: git fetch (Git コミットから適切なパッチをチェックアウトします)
ローカル ブランチをチェックアウトします (ここの例では temp1): git checkout -b temp1
マスターから最近のコンテンツをプル: git pull --rebase origin master
mergetool を起動し、競合を確認して修正します...そして、現在のブランチでリモート ブランチの変更を確認します: git mergetool
ステータスをもう一度確認してください: git status
mergetool によってローカルに作成された不要なファイルを削除します。通常、mergetool は *.orig 拡張子を持つ余分なファイルを作成します。そのファイルは重複しているだけなので削除し、変更をローカルで修正して、正しいバージョンのファイルを追加してください。 git add #your_changed_correct_files
ステータスをもう一度確認してください: git status
変更を同じコミット ID にコミットします (これにより、新しい個別のパッチ セットが回避されます): git commit --amend
master ブランチへのプッシュ: git push (Git リポジトリへ)
次の 3 つの手順があります。
コマンドで競合を引き起こしているファイルを見つける
git status
ファイルを確認すると、次のようにマークされた競合が見つかります
<<<<<<<<head
blablabla
必要な方法に変更してから、コマンドでコミットします
git add solved_conflicts_files
git commit -m 'merge msg'
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
ブランチtest
からにマージするmaster
場合は、次の手順に従います。
ステップ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 : そして、test と master の間に競合はありません。マージを直接使用できます。
2016 年 12 月 12 日以降、github.com でブランチをマージして競合を解決できます。
したがって、ここで古い回答から提供されているコマンドラインまたはサードパーティ ツールを使用したくない場合は、GitHub のネイティブ ツールを使用してください。
このブログ投稿で詳しく説明していますが、基本は、UI を介して 2 つのブランチを「マージ」すると、これらのマージの競合に対処できるエディターに移動する「競合の解決」オプションが表示されるということです。
マージの競合は、さまざまな状況で発生する可能性があります。
git fetch
とその後git merge
git fetch
とその後git rebase
git pull
(実際には上記の条件のいずれかに等しい)git stash pop
競合を解決するには、Git と互換性のあるマージ ツールをインストールする必要があります。私は個人的にKDiff3を使用していますが、便利で便利です。Windows 版は次の場所からダウンロードできます。
https://sourceforge.net/projects/kdiff3/files/
ところで、Git 拡張機能をインストールすると、セットアップ ウィザードに Kdiff3 をインストールするオプションがあります。
次に、KDiff3 をマージツールとして使用するように Git 構成をセットアップします。
$ 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
(パスを KDiff3 EXE ファイルの実際のパスに置き換えることを忘れないでください。)
次に、マージの競合に遭遇するたびに、次のコマンドを実行するだけです。
$ git mergetool
次に、Kdiff3 を開き、最初にマージの競合を自動的に解決しようとします。ほとんどの競合は自然に解決され、残りは手動で修正する必要があります。
Kdiff3 は次のようになります。
完了したら、ファイルを保存すると、競合のある次のファイルに移動し、すべての競合が解決されるまで同じことを繰り返します。
すべてが正常にマージされたかどうかを確認するには、mergetool コマンドを再度実行します。次の結果が得られるはずです。
$ git mergetool
No files need merging
競合を避けるために、私は常に以下の手順に従います。
git checkout master
(マスターブランチに来てください)git pull
(マスターを更新して最新のコードを入手してください)git checkout -b mybranch
(新しい a ブランチをチェックアウトし、そのブランチで作業を開始して、マスターが常にトランクのトップに留まるようにします。)git add .
および git push (変更後のローカルブランチでgit commit
) git checkout master
(ご主人様の元へ)git checkout
これで、同じことを実行して、必要な数のローカル ブランチを維持し、必要に応じてブランチに対してa を実行するだけで同時に作業できます。
この答えは、エディター内ですべてを行うことを好む私のような Vim ユーザーのための代替手段を追加することです。
Tpopeはfugitiveと呼ばれる Vim 用の素晴らしいプラグインを思い付きました。インストールしたら、実行:Gstatus
して競合のあるファイルをチェックし、:Gdiff
Git を 3 方向マージで開くことができます。
3 者間マージが完了すると、fugitiveを使用すると、マージするブランチの変更を次の方法で取得できます。
:diffget //2
、元の ( HEAD ) ブランチから変更を取得します。:diffget //3
、マージ ブランチから変更を取得します。ファイルのマージが完了したら、マージ:Gwrite
されたバッファを入力します。
Vimcasts は、これらの手順を詳細に説明する素晴らしいビデオをリリースしました。
IntelliJ IDEAを IDE として使用している場合は、次の方法で親をブランチにマージしてみてください。
git checkout <localbranch>
git merge origin/<remotebranch>
次のようなすべての競合が表示されます。
A_MBPro:test anu$ git merge origin/ Auto-merging src/test/java/com/.../TestClass.java CONFLICT (コンテンツ): src/test/java/com/.../TestClass.java でのマージの競合
ここで、ファイル TestClass.java が IntelliJ IDEA で赤で表示されていることに注意してください。
またgit status
、表示されます:
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/test/java/com/.../TestClass.java
IntelliJ IDEA でファイルを開きます。次のセクションがあります。
<<<<<<< HEAD
public void testMethod() {
}
=======
public void testMethod() { ...
}
>>>>>>> origin/<remotebranch>
ここで、HEAD はローカル ブランチでの変更、origin/<remotebranch> はリモート ブランチからの変更です。ここでは、必要なものを保持し、不要なものを削除します。その後は、通常の手順で行う必要があります。あれは
git add TestClass.java
git commit -m "commit message"
git push
私は、完全なディレクトリ ツリー全体の比較/マージと、完全なディレクトリ ツリー比較の個々のファイルの比較/マージの両方を行うWinMerge (無料ツール) を使用するのが好きです。
Git マージの競合は、プル リクエストが同僚の変更を元に戻す/失う/上書きすることを示しています。これは通常、コンテンツのコピーが十分に最近のものではないためです。
解決する手順は次のとおりです。
つまり、各ユーザーが同じソース ファイルに対して何を行ったかを手動で確認する以外に、Git マージの競合を解決する魔法の方法はありません。
それが私が考えていることです。
注: WinMerge は .bak ファイルを作成し、それらをソース管理の AzOps、TFS などにコピーしたくないので、編集を正しく行ったことが確実な場合は、.bak ファイルを削除します。