1. ホーム
  2. git

[解決済み] git rebase、'local' と 'remote' を追跡する

2022-04-13 07:21:42

質問

gitのリベースを行う際、コンフリクトを解決する際に「ローカル」と「リモート」で何が起こっているのかがわからないことがよくあります。あるコミットから次のコミットまで、両者が入れ替わっているような印象を受けることがあります。

これはおそらく(間違いなく)、私がまだきちんと理解していないからだと思います。

リベースするとき、誰が「ローカル」で誰が「リモート」なのか?

(競合の解決にP4Mergeを使用しています)

解決方法は?

TL;DR。

要約すると(As ベニューバード コメント )のとき。

git checkout A
git rebase   B    # rebase A on top of B

  • localB (リベース ),
  • remoteA

そして

git checkout A
git merge    B    # merge B into A

  • localA (マージ ),
  • remoteB

リベーススイッチ ours (リベース開始前の現在のブランチ) と theirs (リベースの対象となるブランチ) を指定します。


クチュケム が指摘する。 GUI の Mergetool のコンテキストで :

  • 部分的にリベースされたコミットをローカルに参照する : " ours " (上流ブランチ)
  • リモートとは、入ってくる変更のことです : "です。 theirs " - リベース前の現在のブランチです。

この回答の最後の部分にある図解を参照してください。


リベース時の反転

この混乱は の逆バージョンです。 ourstheirs リベース時 .

(該当箇所抜粋)

git rebase マンページ :

リベースマージは、作業ブランチからの各コミットを <upstream> ブランチを作成します。

このため、マージの競合が発生すると

  • として報告された側は、' ours から始まる、これまでのリベースシリーズです。 <upstream> ,
  • と' theirs は作業用ブランチです。 つまり、左右が入れ替わっているのです。

反転の図解

マージについて

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    \
     \
      \--y--y--y <- other branch to merge

この場合、現在のブランチ 'B' は変更しないので、現在あるものはまだ作業中のものです (そして別のブランチからマージします)。

x--x--x--x--x---------o(*)  MERGE, still on branch B
    \       ^        /
     \     ours     /
      \            /
       --y--y--y--/  
               ^
              their


リベースで

しかし リベース時 なぜなら、リベースが最初に行うのは、上流ブランチをチェックアウトすることだからです! (現在のコミットをその上で再生するため)

x--x--x--x--x(*) <- current branch B
    \
     \
      \--y--y--y <- upstream branch

A git rebase upstream は、まず HEAD のBを上流ブランチの HEAD (そのため、以前の "current" 作業ブランチに比べて 'ours' と 'theirs' が切り替わっています)。

x--x--x--x--x <- former "current" branch, new "theirs"
    \
     \
      \--y--y--y(*) <- upstream branch with B reset on it,  
                       new "ours", to replay x's on it

そして、リベースは「彼らの」コミットを新しい「我々の」Bブランチで再生します。

x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
    \
     \
      \--y--y--y--x'--x'--x'(*) <-  branch B with HEAD updated ("ours")
               ^
               |
        upstream branch


上流の考え方 は、データの参照集合(全レポや、ここのようにブランチ。 ローカル ブランチ) からデータを読み込んだり、新しいデータを追加/作成したりします。


' local ' と ' remote ' 対 ' mine ' と ' theirs '

パンダウッド で追加されます。 コメント :

私にとっては、どちらがローカルでどちらがリモートなのかという疑問が残ります(git でリベースする際に "ours" と "theirs" という言葉は使われないので、それを参照すると回答がより混乱するように思えます)。

GUI git mergetool

クチュケム が追加され、当然ながら

コンフリクトを解決するとき、gitは次のようなことを言うでしょう。

local: modified file and remote: modified file. 

質問の狙いは、この時点でのローカルとリモートの定義にあることは間違いないでしょう。その時点で、私の経験上、次のように思います。

  • ローカルは部分的にリベースされたコミットを参照する : " ours " (上流ブランチ)
  • リモートとは、入ってくる変更のことです : "です。 theirs " - リベース前の現在のブランチです。

git mergetool は、確かに「ローカル」と「リモート」に言及しています。 :

Merging:
f.txt

Normal merge conflict for 'f.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

例えば KDiff3 なら はマージ解像度を次のように表示します。 :

そして メルド も表示されます。 :

以下同じ ヴィムディフ , を表示します。 :

git mergetool -t gvimdiffでVimdiffをmergetoolとして呼び出す。最近のGitのバージョンでは、以下のようなウィンドウレイアウトでVimdiffを起動します。

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+

<ブロッククオート
  • LOCAL :

    現在のブランチにあるファイルの内容を含む一時的なファイルです。
  • BASE :

    マージのための共通基盤を含む一時ファイル。
  • REMOTE :

    マージされるファイルの内容を含む一時的なファイルです。
  • MERGED :

    コンフリクトマーカーを含むファイル。

Gitは可能な限り自動的な競合の解決を行い、このファイルの状態は両者の LOCALREMOTE で、Git が自己解決できなかったものをコンフリクトマーカーで囲みます。

mergetool は、このファイルに解決結果を書き込む必要があります。