バイナリファイルとのGit競合の解決


464

Windows(msysgit)でGitを使用して、これまでに行った設計作業の変更を追跡しています。

今日、私は(リモートリポジトリを備えたbrian)別のPCで作業しており、今日行った編集をラップトップ上の通常のローカルバージョンにマージしようとしています。

私のラップトップでは、私はgit pull brian master自分のローカルバージョンに変更をプルするために使用しました。メインのInDesignドキュメント以外はすべて問題ありませんでした。これは競合として示されます。

PCのバージョン(brian)は保持したい最新バージョンですが、どのコマンドがこのバージョンを使用するようにリポジトリに指示しているのかわかりません。

ラップトップに直接ファイルをコピーしようとしましたが、これによりマージプロセス全体が中断されるようです。

誰かが私を正しい方向に向けることができますか?

回答:


854

git checkoutこのような場合には、--oursまたは--theirsオプションを受け入れます。したがって、マージの競合があり、マージするブランチからのファイルだけが必要であることがわかっている場合は、次のようにすることができます。

$ git checkout --theirs -- path/to/conflicted-file.txt

そのバージョンのファイルを使用する。同様に、(マージされるバージョンではなく)バージョンが必要であることがわかっている場合は、

$ git checkout --ours -- path/to/conflicted-file.txt

47
--oursを使用する前に、ファイルに対して 'git reset HEAD path / to / conflicted-file.txt'を実行する必要がありました。それ以外の場合は効果がないようです。
Zitrax 2011年

6
@Zitrax実行後にファイルを比較しましたgit checkout --oursか?manページは、チェックアウト--ours /-theirsが「両方変更、マージが必要」のリストから変更を削除し、それをインデックスに追加することを(IMHO)に示唆しています(それは正しくないと思います)。git addチェックアウト後に実行する必要があると思います。
Tim Keating

15
注:「git add conflicted-file.txt」と「git commit」を実行する必要があります。手作業で試したところ、コミットメッセージには競合に関するメモが事前に入力されていました。
エドワードフォーク14

2
「マージしているブランチ」の言い回しは「マージしているブランチ」に危険なほど近いので、前置詞を削除するだけの方が良いと思います。「マージしているブランチ」は、gitコマンドも反映します。 (つまりgit merge branch_name)。
andrybak 2016年

13
このトピックの説明では常に欠けている重要なポイントがいくつかあります。、の意味を代わりにマージのリベースを行うとき--their--ours交換され、すなわち--their ==は、現在のブランチを、チェックアウトし、あなたが現在にマージしようとしているSPEC --oursは、分岐、通常リモートブランチ、またはパスでありますブランチ。この[space]--[space]オプションにより、ブランチ名とパス指定の間のパス指定が明確になり、両方とも同じ名前で存在します(たとえば、既存のブランチ名は「abc」で、ディレクトリは「abc」と呼ばれます)。
BoiseBaked 2016

147

このように手動で競合を解決し(ファイルをコピーして)、次にファイルをコミットする必要があります(コピーしたか、ローカルバージョンを使用したかに関係なく)。

git commit -a -m "Fix merge conflict in test.foo"

通常、Gitはマージ後に自動コミットしますが、それ自体では解決できない競合を検出すると、計算したすべてのパッチを適用し、残りは手動で解決してコミットするために残します。GitのマージマニュアルページGitは、SVNのクラッシュコースまたはこのブログのエントリは、それが動作するようになっています方法についていくつかの光を当てることがあります。

編集:以下の投稿を参照してください。実際にファイルを自分でコピーする必要はありませんが、使用できます

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

必要なファイルのバージョンを選択します。ファイルのコピー/編集は、両方のバージョンを混在させたい場合にのみ必要です。

ミパディスの答えを正しいものとしてマークしてください。


1
それをありがとう。ファイルを「正しい」ファイルとしてマークするための何らかの組み込み方法があるかどうかはわかりませんでした。存在しないコマンドが見つからなかった理由を説明しています!
Kevin Wilson、

ええ、それは少し直感的ではありません
-git

120

この問題を克服することもできます

git mergetool

これによりgit、競合するバイナリのローカルコピーが作成され、デフォルトのエディターが起動されます。

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

もちろん、バイナリファイルをテキストエディタで効果的に編集することはできません。代わりに、エディターを閉じずに新しい{conflicted}.REMOTEファイルをコピーします{conflicted}。次に、エディターgitを閉じると、装飾されていない作業用コピーが変更され、マージの競合が通常の方法で解決されます。


8
ファイルが大きい場合、またはテキストエディターでバイナリを開く危険を冒したくない場合は、mergetoolプロンプト( " Hit return to start merge resolution tool")でctrl + cを押すと、余分なファイルがそのまま残ります。次に、それらを変更するか、外部ツール(LibreOffice / OpenOffice / MSWordなどのバイナリドキュメント形式に便利)にマージして、結果を元のファイル名に保存します。gitに競合が解決されたことを通知するにはgit add、元のファイル名を使用して、マージコミットを終了します。
Felix

18

現在のブランチのバージョンを保持して解決するには(マージするブランチのバージョンを無視します)、ファイルを追加してコミットします。

git commit -a

現在のブランチのバージョンを、マージするブランチのバージョンで上書きして解決するには、まずそのバージョンを作業ディレクトリに取得してから、追加/コミットする必要があります。

git checkout otherbranch theconflictedfile
git commit -a

より詳しく説明


1
受け入れられた回答よりもこのバリアントを選択します。特に、リベースの場合に「--ours」と「--theirs」の意味が入れ替わることを考えると、直感的です。
アントニーハッチキンス

11

ミパディの答えは私にとってはうまくいきませんでした、私はこれをする必要がありました:

git checkout --ours path / to / file.bin

または、バージョンのマージを維持するには:

git checkout-それらのパス/to/file.bin

その後

git add path / to / file.bin

そして、再び「git mergetool」を実行して、次の競合に進むことができました。


6

ドキュメントからgit checkout

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
インデックスからパスをチェックアウトするときは、ステージ#2(ours)または#3(theirs、マージされていないパスの)をます。

以前にマージが失敗したため、インデックスにはマージされていないエントリが含まれている可能性があります。デフォルトでは、インデックスからそのようなエントリをチェックアウトしようとすると、チェックアウト操作は失敗し、何もチェックアウトされません。を使用-fすると、これらのマージされていないエントリは無視されます。マージの特定の側のコンテンツは、--oursまたはを使用してインデックスからチェックアウトできます--theirs。を使用-mすると、作業ツリーファイルに加えた変更を破棄して、元の競合したマージ結果を再作成できます。


4

私は同様の問題に遭遇しました(マージ時に競合を引き起こすいくつかのバイナリファイルを含むコミットをプルしたい)が、gitを使用して完全に実行できる別のソリューションに遭遇しました(つまり、手動でファイルをコピーする必要がない)。ここに含めると思ったので、少なくとも次に必要になったときに覚えておくことができます。:)手順は次のようになります。

% git fetch

これにより、リモートリポジトリから最新のコミットがフェッチされます(設定によっては、リモートブランチ名を指定する必要がある場合があります)が、それらのマージは試行されません。コミットをFETCH_HEADに記録します

% git checkout FETCH_HEAD stuff/to/update

これにより、必要なバイナリファイルのコピーが取得され、作業ツリーの内容がリモートブランチからフェッチされたバージョンで上書きされます。gitはマージを行わないため、リモートブランチからのバイナリファイルの正確なコピーが作成されるだけです。それが完了したら、通常どおりに新しいコピーを追加/コミットできます。


4

この手順は、Githubにプルリクエストを送信した後にバイナリファイルの競合を解決するためのものです。

  1. Githubで、プルリクエストがバイナリファイルと競合していることがわかりました。
  2. 次に、ローカルコンピューターの同じgitブランチに戻ります。
  3. (a)このバイナリファイルを再作成/再構築し、(b)結果のバイナリファイルをこの同じgitブランチにコミットします。
  4. 次に、この同じgitブランチをGithubに再度プッシュします。

Githubでは、プルリクエストで競合が解消されます。


これはまさに私が必要とする手順です
Huifang Feng

2

バイナリがdll以外のもの、または直接編集できるものの場合イメージのように、またはブレンドファイルの場合(そして、ファイルをゴミ箱に入れる/選択する必要がない場合)、実際のマージは次のようになります。

私はあなたがバイナリファイルであるものに向けられたdiffツールを検索することをお勧めします、例えば、例えば画像ファイルのためのいくつかの無料のものがあります

それらを比較します。

ファイルを比較するための差分ツールがない場合、binファイルの元のジェネレーターがある(つまり、blender 3dなどのエディターが存在する)場合は、それらのファイルを手動で検査することもできます。ログを見て、何を含めるべきかを他の人に尋ねます)そしてhttps://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remergeでファイルの出力を行います

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend


1

WindowsでGitを使用してバイナリファイルの差分/マージを管理するための2つの戦略に遭遇しました。

  1. Tortoise gitでは、ファイル拡張子に基づいて、さまざまなファイルタイプのdiff / mergeツールを構成できます。2.35.4.3を参照してください。差分/マージの詳細設定http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html。もちろん、この戦略は、利用可能な適切なdiff / mergeツールに依存しています。

  2. git属性を使用すると、バイナリファイルをテキストに変換するツール/コマンドを指定して、デフォルトのdiff / mergeツールにそれを実行させることができます。http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributesを参照してください。この記事では、メタデータを使用して画像を比較する例も示しています。

ソフトウェアモデルのバイナリファイルで作業するための両方の戦略を取得しましたが、設定が簡単だったので、亀のgitを使いました。


0

私はGit Workflow for Excel- https://www.xltrail.com/blog/git-workflow-for-excelアプリケーションを使用して、マージの問題に関連するほとんどのバイナリファイルを解決しています。このオープンソースアプリを使用すると、時間をかけずに問題を生産的に解決でき、混乱することなく適切なバージョンのファイルを簡単に選択できます。


0

私のケースはバグのようです... git 2.21.0を使用

私は引っ張った...それはバイナリファイルについて不平を言った:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

そして、ここでの答えのいずれも、意味のある出力をもたらしませんでした。

私が今持っているファイルを見ると...それは私が編集したファイルです。私がどちらかを行う場合:

git checkout --theirs -- <path>
git checkout --ours -- <path>

私は出力を得ます:

Updated 0 paths from the index

私のファイルのバージョンはまだ残っています。rmしてからチェックアウトすると、代わりに1と表示されますが、それでも私のバージョンのファイルは得られます。

git mergetool言う

No files need merging

とgitステータスは言う

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

1つのオプションは、コミット元に戻すことですです...しかしが悪かったため、多くのコミットがありましたが、この悪いものが最初でした。それを繰り返す時間を無駄にしたくありません。

この狂気を解決するには:

私はただ走った

git commit

これはリモートバージョンを失い、おそらく余分なバイナリファイルを格納するためのスペースを浪費します...

git checkout <commit where the remote version exists> <path>

リモートバージョンを返す

その後、ファイルを再度編集し、コミットしてプッシュします。これは、おそらくバイナリファイルの別のコピーでスペースを浪費することを意味します。


私の場合、git checkout --ours <path>受信しようとした後Updated 0 paths from the index git add <path>同じことを行うコマンドで修正しました。
Andriy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.