1. ホーム
  2. git

[解決済み] Git の強制上書きを伴うマージ

2022-03-03 23:13:48

質問

というブランチがあります。 demo とマージする必要があります。 master ブランチを作成します。以下のコマンドで目的の結果を得ることができます。

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

唯一の懸念は マージに問題がある場合 と伝えたい。 git での変更を上書きするために master ブランチにマージプロンプトを表示させないようにしました。つまり、基本的には demo ブランチの変更を自動的に上書きする必要があります。 master ブランチを作成します。

複数のオプションがあるようですが、マージのリスクを負いたくありません。

解決方法は?

この回答とはあまり関係ないのですが、私なら git pull を実行するだけです。 git fetch に続いて git merge . マージは3回行うことになるので、フェッチは1回で済むところを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 . として ルート545指摘 は、その -X オプションはマージ戦略に渡され、デフォルトの recursive ストラテジーと、代替の resolve ストラテジーテイク -X ours または -X theirs (どちらか一方のみで、両方は不可)。 しかし、それらが何をするのかを理解するためには、Gitがどのように見つけ、どのように扱うのかを知る必要があります。 マージコンフリクト .

マージの衝突は、いくつかのファイル内で発生する可能性があります 1 を実行したときに ベース の両方と異なるバージョンです。 現在の (ローカル、HEAD、または --ours ) バージョン もう一方は(リモートまたは --theirs ) のバージョンと同じファイルです。 つまり、マージは3つのリビジョン(3つのコミット)を識別しています:基本、我々の、そして彼らの。 base"ベース"バージョンは マージベース コミットグラフにあるように、私たちのコミットと彼らのコミットの間にあります (これについては、他のStackOverflowの投稿を参照してください)。 Gitは、2つの変更点: "私たちが行ったこと" と "彼らが行ったこと" を発見しました。 これらの変更は、(一般的には)一行ごとに見つかります。 純粋にテキスト をベースにしています。 Gitはファイルの内容を全く理解していません。単にテキストの各行を比較しているだけです。

これらの変更は git diff を出力し、いつものように、それらは コンテキスト もあります。 私たちが変更したものと彼らが変更したものが別の行にあり、変更が衝突しないように見えますが、文脈も変わっている可能性があります(たとえば、私たちの変更がファイルの上部または下部に近いため、私たちのバージョンではファイルがなくなりますが、彼らのバージョンでは上部または下部にさらにテキストが追加されているなど)。

に変更があった場合 異なる の行を変更します。 colorcolour を変更し、17行目で fredbarney を71行目に追加すれば、コンフリクトは発生しません。Git は単に 両方とも を変更します。 もし同じ行で起きた変更であっても 同一 を変更すると、Git は コピー1枚 の変更です。 変更が同じ行にありながら異なる変更である場合、あるいはコンテキストが干渉する特殊な場合のみ、変更/修正の衝突が発生します。

-X ours-X theirs オプションは、この衝突をどのように解決するかをGitに伝えます。つまり、私たちの変更と彼らの変更のどちらかを選ぶのです。 あなたがマージすると言ったので demo (彼ら)を master (私たちの) から変更する必要があります。 demo であれば -X theirs .

盲目的に適用する -X しかし、これは危険です。 行単位で見ると衝突していないからと言って、実際に衝突していないとは限りません。 典型的な例としては、変数宣言のある言語が挙げられます。 ベースバージョンは未使用の変数を宣言しているかもしれません。

int i;

私たちのバージョンでは、コンパイラの警告を消すために未使用の変数を削除しています。 その のバージョンでは、数行後にループを追加して i をループカウンタとして使用します。 この2つの変更を組み合わせると、結果のコードはもはやコンパイルできません。 そのため -X オプションは役に立ちません。 異なる行 .

自動化されたテストスイートがある場合、最も重要なことは、マージ後にテストを実行することです。 コミットした後でこれを行い、必要なら後で修正することもできます; あるいは、次のようにすることもできます。 を追加して、コミットします。 --no-commitgit merge コマンドを使用します。 これらすべての詳細については、他の投稿に譲ることにします。


1 また、quot;ファイルワイド"操作に関しても競合が発生することがあります。例えば、ファイル内の単語のスペルを修正し(変更を加えるため)、それらが 削除 ファイル全体が削除されます。 にかかわらず、Gitはこれらの衝突を自分自身で解決することはありません。 -X 引数を使用します。


より少ないマージ、よりスマートなマージ、またはrebaseの使用

この2つのコマンドには、3つのマージがあります。 1つ目は origin/demo をローカルな demo (あなたのは git pull これは、Gitが非常に古い場合、更新に失敗します。 origin/demo しかし、最終的な結果は同じです)。 もうひとつは origin/master の中に master .

を更新しているのは誰なのか、私にはよくわかりません。 demo および master . に自分でコードを書くと demo ブランチを作成します。 他の人はコードを書いて、それを demo ブランチの origin の場合、この最初のステップのマージはコンフリクトが発生したり、本当のマージを生成する可能性があります。 多くの場合、作業を結合するにはマージよりもリベースを使ったほうがよいでしょう (確かに、これは好みや意見の問題です)。 そのような場合は git rebase 代わりに 一方、自分自身のコミットをまったく行わないのであれば demo を使用しないのであれば 必要 a 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 は早送りができないかもしれませんし、rebaseは衝突して失敗するかもしれません(rebaseの動作は、要するに。 チェリーピック これはマージの仕組みを使うので、マージの衝突が起こる可能性があります)。