Skip to content
This page has been auto-translated and may contain errors.View in English

ブランチのマージとコンフリクト解決

docs.scrimba.com

フィーチャーブランチが完成しました。トグルが機能し、変更をコミットしたので、あとはそれをmainに置いて、チームの残りのコードが住んでいるところに統合したいと考えています。ほとんどの場合、それを取り込むのは迅速で静かです。Gitは2つのブランチを比較し、重複するものを見つけず、余分な手順なしで作業を折り込みます。しかし、別のブランチで同じ行をあなたと同じチームメイトが変更したことがあり、Gitはどのバージョンを保持したいのかを推測できません。その状況は、複数の人がコミットしているほぼすべてのプロジェクトに現れます。これはブランチの通常の日常的な部分であり、Gitが同じ行について2つの考えを見つけ、どちらが勝つかについてあなたの判断を求めていることを意味します。

git mergeでブランチを戻す

add-fahrenheit-toggleという独自のブランチでFahrenheitトグルを構築し、mainが分岐してから移動していないとします。mainに切り替えて、持ってきたいブランチの名前でgit mergeを実行します。

bash
$ git switch main
$ git merge add-fahrenheit-toggle
Updating 4f2a891..8c3d1a0
Fast-forward
 src/index.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

git merge <branch>は常に、現在立っているブランチ内に名前付きブランチをマージします。そのため、最初にmainに切り替えることが重要です。立っているブランチは、マージを受け取るものです。これが実行された後、mainadd-fahrenheit-toggleからすべてのコミットを持っています。フィーチャーブランチ自体は変更されません。その作業がmainにも存在するようになったため、その上で作業を続けるか、今削除できます。

出力のFast-forward行は注意深く読む価値があります。それはmainがあなたが分岐してから新しいコミットを得ていなかったことを意味し、Gitは何かを組み合わせる必要はありませんでした。mainラベルをadd-fahrenheit-toggleが既に指していたのと同じコミットを指し示すように前に移動しました。**ファストフォワードマージ**はGitがラベルを既にそこにいる必要があった場所に追いつけることで、それ以上ではありません。

mainがあなたが作業している間に他のコミットを拾った場合、たとえばチームメイトがその間にバグ修正をマージした場合、Gitはもうラベルを前に移動することができません。なぜなら、mainとあなたのブランチは分岐以来異なる方向に進んだからです。代わりに、両方の履歴を結びつける新しいコミットを作成します。これはマージコミットと呼ばれます。

bash
$ git switch main
$ git merge add-fahrenheit-toggle
Merge made by the 'ort' strategy.
 src/index.js | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

このようなマージの後のgit log --graph --onelineは分岐と結合を示します。履歴の2行が横に並んで実行され、マージコミットで再び出会います。どちらの結果も、あなたに何か余分なものを求めません。Gitはブランチが分岐したかどうかに基づいてどちらが適用されるかを決定し、いずれの方法でもあなたのフィーチャーは今mainの一部です。

上記の両方の結果は同じ考えに基づいています。**3方向マージ**です。2つのブランチを組み合わせるために、Gitは2つのチップ以上を比較します。まず、両方のブランチが共有する共通の開始点であるマージベースを見つけ、次に3つのスナップショットを見ます。ベースと各ブランチのチップです。共有ベースに対してそれぞれのチップを比較することで、Gitは各側が変更した行を正確に知ることができます。これにより、2つの編集セットを自動的に組み合わせることができます。毎回あなたに尋ねる代わりに。

ファストフォワードは、3つのスナップショットの1つが冗長であることが判明した場合です。ベースと1つのチップが同じコミットであるため、その側には組み合わせるものはなく、Gitは新しいものを作成しないでラベルを移動します。マージコミットは一般的なケースです。ここで両側は基本以来何かを変更し、Gitは新しいスナップショットを記録し、2つの親を持ちます。1つは各ブランチの履歴に戻っています。次のセクションで遇うすべてのマージコンフリクトは、同じ3方向比較から来ます。両側が同じ行に触れたことを見つけ、それらを独自に組み合わせる方法がありません。

Junogit mergeでブランチを戻すgit merge branch-nameはそのブランチのコミットを、現在立っているブランチに持ってくるため、まずmainに切り替えます。ほとんどのマージは背景で静かに起こり、あなたは日々を進めます。フィーチャーブランチ自体については何も変わりません。mainが作業を得た後で使い続けるか削除できます。
Junogit mergeでブランチを戻す ファストフォワードはmainが移動していなかったことを意味するため、Gitはラベルを前に滑らせただけです。mainがその間に他のコミットを拾ったら、マージは代わりに2つの親を持つ実際のマージコミットを作成します。コマンドは同じgit merge branch-nameです。Gitはどの種類のマージが適切であるかを決定します。
Junogit mergeでブランチを戻す 3方向マージは、各ブランチのチップに対して共有ベースコミットを比較して、各側で何が変更されたかを理解します。これにより、2つのブランチを組み合わせることはほとんどの場合自動的です。ファストフォワードは、ベースと1つのチップが既に一致する特殊なケースです。私はまだ、散らかったグラフでどのコミットがベースとしてカウントされるかを知り尽くすのに一時停止を見つけます。不確定な場合はそれを描き出してください。

マージコンフリクトはどのように見えるか

コンフリクトは、マージの両側で同じ行が変更され、Gitがどのバージョンを求めているかを知る方法がない場合に発生します。チームメイトがsrc/index.jsの関数を変更したローディングスピナーをmainにマージし、あなたのadd-fahrenheit-toggleブランチが同じ関数を変更してトグルを追加したとします。今マージは途中で止まり、完了しません。

bash
$ git switch main
$ git merge add-fahrenheit-toggle
Auto-merging src/index.js
CONFLICT (content): Merge conflict in src/index.js
Automatic merge failed; fix conflicts and then commit the result.

これは**マージコンフリクト**です。ファイルを開くと、Gitが2つのバージョンが正確に同意しない場所を表示しています。

<<<<<<< HEAD
  showLoadingSpinner(true);
=======
  const tempF = celsiusToFahrenheit(tempC);
>>>>>>> add-fahrenheit-toggle

<<<<<<< HEADは現在のブランチ上にあるもの(この場合はmain)の開始をマークします。=======は2つのバージョンを分割します。>>>>>>> add-fahrenheit-toggleは受け入れるブランチのバージョンの終わりをマークします。マーカー間のすべてが同じ行の一握りで、2つの異なる方法で書かれています。

コンフリクトはGitがあなたの判断を必要とすることを意味します。何も壊れていません。Gitは同じ行への2つの変更を見つけ、どれを求めているかを推測する方法がありません。そのため、それは一時停止し、どちらが勝つかを決めるようあなたに求めます。ファイルを編集して、いずれかのバージョン、両方、またはそれらを組み合わせた新しいものを保持するまで、希望どおりに読まれるようにしてから、マーカー行自体を削除します。

  showLoadingSpinner(true);
  const tempF = celsiusToFahrenheit(tempC);

ファイルが正しく見えたら、他の変更と同じようにそれをステージしてコミットします。

bash
$ git add src/index.js
$ git commit

メッセージなしでgit commitを実行すると、エディタが開き、Gitが既に用意したメッセージが表示されます。マージについて説明します。保存して閉じると、マージが完了します。

コンフリクトが開いている間、git statusは最初に値する確認です。「Unmerged paths」の下で注意が必要なすべてのファイルをリストします。そのため、複数の競合するファイルに触れる大きなマージでは、修正する必要があるファイルの数が正確にわかります。

bash
$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   src/index.js

git addはGitにファイルのコンフリクトが解決されたことを伝えます。実際にマーカーを削除したかどうかは確認しません。そのため、ステージング前にファイルを読み直してください。マージが予想より乱雑に見える場合、または間違ったブランチを選んだ場合、git merge --abortは完全にバックアウトし、git mergeを実行する前の様子に作業ディレクトリを返します。半分完成したものは何も残しません。

コンフリクトはgit mergeに限定されません。**Rebase**は、1つの履歴をもう1つで最新に保つもう1つの方法であり、同じ種類のクラッシュに当たります。解決されたら異なる結果になります。マージは2つの親を持つマージコミットで2つの履歴を結びつけ、ブランチが存在したという事実と、それがいつ再参加したかを正確に保持します。代わりに、リベースはあなたのブランチのコミットを再実行し、別のブランチのチップで1つずつ再実行し、マージコミットがなく、2つが分岐したという痕跡がない歴史の直線を生成します。

bash
$ git switch add-fahrenheit-toggle
$ git rebase main

トレードオフは実数です。リベースからの線形履歴はgit logで読みやすく読まれます。1つのコミット、別のコミット。一部のチームは整頓された物語のために好みます。マージは、フィーチャーブランチがmainに正確に再参加したポイントを含む、起こったことの真の形を保持します。一部のチームは精度のために好みます。どちらの選択も間違っていません。チームごとに1つの規約を選択し、一貫性を保ちます。

1つのルールは、どの規約を選択するかに関係なく保持します。他の人が既にプルしたか、その上に作業を構築したブランチを再ベースしないでください。リベースは新しいIDで新しいコミットにコミットを書き直します。共有ブランチの履歴がコラボレータの下で変更される場合、彼らのローカルコピーと書き直されたリモートはもう同意しません。彼らの終わりの手動修正を強制します。誰か他の人がそれをプルする前に、独自のブランチでリベース自由に。一度共有されたら、マージしてください。

Junoマージコンフリクトはどのように見えるか マージコンフリクトは2つのブランチが同じ行を変更し、Gitがあなたに結果を選ぶように求める必要があることを意味します。ファイルを開き、<<<<<<<=======>>>>>>>を探し、希望どおりに読むまで編集してから、そのマーカー行を削除します。git addgit commitで終わります。私の最初のコンフリクトは緊急のように感じました。それはGitが私にかなり通常の質問を求めていたことが判明しました。
Junoマージコンフリクトはどのように見えるかgit statusはマージされていないパスの下のすべての未解決ファイルをリストします。コンフリクトが複数の1つに触れる瞬間に便利です。git addはあなたの仕事をチェックせずにファイルを解決済みとしてマークするため、ステージングする前にそれを読んでください。マージが側に行く場合、git merge --abortは何も半分完成した状態で、クリーンな状態に戻ります。
Junoマージコンフリクトはどのように見えるか リベースはマージと同じクラッシュに遭遇します。代わりに新しいベースにコミットを再実行します。保存されたブランチ形状を直線に交換します。その取引をあなたが使用しているブランチのみに保ちます。ブランチが共有されるにつれて、リベースで提出を書き直すことは、既にそれをプルしたすべての人にとって人生を困難にするため、代わりにマージに手を伸ばします。

それを一緒に戻す

マージはブランチを行う価値を生じさせます。独自の履歴のラインで安全に実験します。Branchesで説明しています。その後、コンフリクトを含めて、準備ができたら作業をmainに折り込みます。GitHubでは、同じ操作は通常、マシンでローカルgit mergeの代わりにプルリクエストを通じて行われます。pull request flowの章は、共有プロジェクトの変更を提案、レビュー、およびマージすることをカバーしています。マージが既にコミットした後に意図していない場所に着陸した場合、undoing thingsはどのように安全にバックアウトするかについて説明しています。