この回答とはあまり関係ありませんがgit pull
、を実行し、git fetch
その後にを実行しgit merge
ます。1つのフェッチで十分な場合、3つのマージを実行して、Gitに3つのフェッチ操作を実行させます。したがって:
git fetch origin # update all our origin/* remote-tracking branches
git checkout demo # if needed -- your example assumes you're on it
git merge origin/demo # if needed -- see below
git checkout master
git merge origin/master
git merge -X theirs demo # but see below
git push origin master # again, see below
最も扱いにくいマージを制御する
ここで最も興味深い部分はgit merge -X theirs
です。以下のようroot545は指摘し、-X
オプションをマージ戦略、およびデフォルトの両方に渡されrecursive
戦略や代替resolve
戦略テイク-X ours
か-X theirs
(どちらか一方、両方ではありません)。ただし、Gitが何を行うかを理解するには、Gitがどのようにして競合を見つけて処理し、マージするかを知る必要があります。
マージ競合は、いくつかのファイル内で発生することができる1際にベースの両方からのバージョンが異なる電流が(ローカル、HEAD、または呼び出された--ours
バージョン)と(また、リモートまたは呼ばれる他の--theirs
その同じファイルの)バージョン。つまり、マージは3つのリビジョン(3つのコミット)、base、ours、およびtheirsを識別しました。「ベース」バージョンは、コミットグラフにあるように、コミットとコミットの間のマージベースからのものです(これの詳細については、他のStackOverflowの投稿を参照してください)。その後、Gitは「私たちがしたこと」と「彼らがしたこと」の2つの変更セットを見つけました。これらの変更は、(一般的に)行ごとに、純粋にテキストで見られます基礎。Gitはファイルの内容を実際に理解していません。テキストの各行を比較するだけです。
これらの変更はgit diff
出力に表示されるものであり、いつものように、それらにもコンテキストがあります。私たちが変更したものは、変更したものとは異なる行にある可能性があります。そのため、変更は衝突しないように見えますが、コンテキストも変更されています(たとえば、変更がファイルの上部または下部に近いため)私たちのバージョンではファイルが不足しますが、彼らのバージョンでは、上部または下部にテキストが追加されています)。
変更がで発生した場合異なるライン-のインスタンス、我々は変更color
にcolour
ライン17上で、彼らは変更fred
にbarney
ライン上の71-その後、競合はありません:Gitは単に取り、両方の変更を。変更が同じ行で発生しても、同一の変更である場合、Gitは変更のコピーを1つ取得します。変更が同じ行にあるが、異なる変更である場合、またはコンテキストが干渉する特殊なケースである場合のみ、変更/変更の競合が発生します。
-X ours
そして-X theirs
私たち、あるいは彼らを:オプションは、ちょうど2つの変更のいずれかを選ぶことによって、この競合を解決する方法をGitリポジトリを教えてください。demo
(自分たちの)をmaster
(私たちの)にマージしていてdemo
、からの変更を望んでいると言ったので、あなたはを望み-X theirs
ます。
-X
ただし、盲目的に適用することは危険です。変更が行ごとに競合しなかったからといって、変更が実際に競合しなかったわけではありません。古典的な例の1つは、変数宣言を持つ言語で発生します。基本バージョンは未使用の変数を宣言するかもしれません:
int i;
このバージョンでは、未使用の変数を削除して、コンパイラの警告を取り除きます。バージョンではi
、ループカウンターとして使用して、数行後にループを追加します。2つの変更を組み合わせると、結果のコードはコンパイルできなくなります。-X
変更が別の行にあるため、このオプションは役に立ちません。
自動テストスイートがある場合、最も重要なことは、マージ後にテストを実行することです。これはコミット後に行うことができ、必要に応じて後で修正できます。または、コマンドに追加することで、コミットする前にそれを行うことができます。このすべての詳細は他の投稿に任せます。--no-commit
git merge
1また、「ファイル全体」の操作に関して競合が発生する可能性もあります。たとえば、ファイル内の単語のスペルを修正し(変更を加えるため)、ファイル全体を削除します(そのため、削除)。Gitは、-X
引数に関係なく、これらの競合を単独で解決することはありません。
より少ないマージを行う、および/またはよりスマートなマージを行う、および/またはリベースを使用する
どちらのコマンドシーケンスにも3つのマージがあります。1つ目はorigin/demo
、ローカルに取り込むことdemo
です(git pull
Gitが非常に古い場合、アップデートは失敗しますorigin/demo
が、同じ最終結果が生成されます)。2つ目は、にorigin/master
取り込むことmaster
です。
誰が更新demo
しているのか、および/または私が明確ではありませんmaster
。あなたがあなた自身のdemo
ブランチであなた自身のコードを書いていて、そして他の人がコードを書いてそれをdemo
ブランチにプッシュしているなら、origin
この最初のステップのマージは衝突するかもしれません、あるいは実際のマージを生成するかもしれません。多くの場合、作業を組み合わせるにはマージではなくリベースを使用する方が良いです(確かに、これは好みと意見の問題です)。その場合は、git rebase
代わりに使用することができます。一方、自分でコミットをdemo
まったく行わない場合は、demo
ブランチも必要ありません。あるいは、これの多くを自動化したいが、あなたと他の両方が行ったコミットがあるときに慎重にチェックできる場合は、git merge --ff-only origin/demo
:これにより、可能な場合demo
は更新されたものと一致するように早送りされorigin/demo
、そうでない場合は完全に失敗します(この時点で、2つの変更セットを検査し、必要に応じて実際のマージまたはリベースを選択できます)。
これと同じロジックがに適用されmaster
ますが、でマージを 実行しているmaster
ため、間違いなくが必要master
です。ただし、早送りの非マージとして実行できない場合にマージを失敗させるのは、より可能性が高いため、おそらくこれもそうgit merge --ff-only origin/master
です。
あなたが自分でコミットをすることは決してないとしましょうdemo
。この場合、名前をdemo
完全に破棄できます。
git fetch origin # update origin/*
git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"
git merge -X theirs origin/demo || die "complex merge conflict"
git push origin master
あなたがいる場合しているあなた自身のやってdemo
分岐コミットを、これは便利ではありません。既存のマージを維持する(ただし--ff-only
、必要な動作に応じて追加する)か、リベースを実行するように切り替えることもできます。マージが競合して失敗することがあり、とのマージは:すべての3つの方法が失敗する可能性があることに注意--ff-only
早送りできないことがあり、そしてリベースは、紛争(リベースは本質的に、ことによって動作し、で失敗することがありさくらんぼ狩りマージを使用してコミット、機械、したがってマージの競合が発生する可能性があります。
git push -f origin master