web-dev-qa-db-ja.com

git rebase、「ローカル」と「リモート」を追跡

Git rebaseを実行するとき、競合を解決するときに「ローカル」と「リモート」で何が起こっているのかを理解するのが難しいことがよくあります。私は時々、あるコミットから次のコミットにサイドを交換するという印象を持っています。

私はまだ適切に理解していないため、これはおそらく(間違いなく)です。

リベースする場合、誰が「ローカル」で誰が「リモート」ですか?

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

158
Benjol

TL; DR;

要約すると(As Benubirdcomments )、次の場合:

git checkout A
git rebase   B    # rebase A on top of B
  • localB(rebaseonto)、
  • remoteAです

そして:

git checkout A
git merge    B    # merge B into A
  • localA(mergeinto)、
  • remoteBです

リベースは、ours(リベースを開始する前の現在のブランチ)とtheirs(リベースする最上位のブランチ)を切り替えます。


kutschkem が指摘しているのは、GUI mergetoolコンテキストで:

  • ローカルは部分的にリベースされたコミットを参照します: "ours"(上流ブランチ)
  • リモートは受信した変更を参照します: "theirs"-リベース前の現在のブランチ。

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


リベース時の反転

混乱は リベース中のourstheirsの反転 に関連している可能性があります。
(関連抽出)

git rebase manページ

リベースマージは、<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 will first change HEAD of B to the upstream branch HEAD (hence the switch of 'ours' and 'theirs' compared to the previous "current" working branch.)

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

注: "upstream"の概念 は、データの参照セット(すべてのレポまたはここのようなブランチlocalブランチ)読み取るか、新しいデータが追加/作成されます。


local」と「remote」対「mine」と「theirs

Pandawood が追加されます コメント

私にとっては、「ローカル」で誰が「リモート」であるかという疑問が残っています(gitでリベースするときに「私たち」と「彼ら」という用語は使用されないため、それらを参照すると答えが混乱するようです) 。

GUI git mergetool

kutschkem が追加されます。

競合を解決するとき、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):

たとえば、 KDiffマージ解像度をそのように表示します

kdiff3

そして meld表示も になります:

Meld diff

VimDiff表示される でも同じです:

Git mergetool -t gvimdiffでVimdiffをmergetoolとして呼び出します。 Gitの最新バージョンは、次のウィンドウレイアウトでVimdiffを呼び出します。

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • LOCAL
    現在のブランチ上のファイルの内容を含む一時ファイル。
  • BASE
    マージの共通ベースを含む一時ファイル。
  • REMOTE
    マージするファイルの内容を含む一時ファイル。
  • MERGED
    競合マーカーを含むファイル。

Gitはできるだけ多くの自動競合解決を実行しました。このファイルの状態は、LOCALREMOTEの両方の組み合わせで、Git自身が解決できなかったものを囲む競合マーカーがあります。
mergetoolは、解決の結果をこのファイルに書き込む必要があります。

216
VonC

一番下の行

git rebase

  • LOCAL =リベースするベースonto
  • REMOTE =上に移動するコミット

git merge

  • LOCAL =マージする元のブランチ
  • REMOTE =コミットをマージする他のブランチ

つまり、[〜#〜] local [〜#〜]は常にオリジナルであり、[〜#〜] remote [〜#〜]は常にガイですコミットがトップにマージまたはリベースされているため、以前にコミットがなかった

証明してください!

確かに。私の言葉を信じないでください!以下は、自分で確認できる簡単な実験です。

まず、git mergetoolが適切に構成されていることを確認してください。 (そうしなければ、おそらくこの質問を読んでいないでしょう。)次に、作業するディレクトリを見つけます。

リポジトリをセットアップします。

md LocalRemoteTest
cd LocalRemoteTest

最初のコミットを作成します(空のファイルを使用):

git init
notepad file.txt  (use the text editor of your choice)
  (save the file as an empty file)
git add -A
git commit -m "Initial commit."

マスターではないブランチでコミットを作成します。

git checkout -b notmaster
notepad file.txt
  (add the text: notmaster)
  (save and exit)
git commit -a -m "Add notmaster text."

Masterブランチでコミットを作成します。

git checkout master
notepad file.txt
  (add the text: master)
  (save and exit)
git commit -a -m "Add master text."

gitk --all

この時点で、リポジトリは次のようになります。

Repository with a base commit and two one-commit branches

リベーステストの場合:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster

マージテスト。変更を保存せずにmergetoolを閉じてから、リベースをキャンセルします。

git rebase --abort

次に:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)

結果は、上部に表示されるものと同じである必要があります。

41
Ryan Lundy

私はあなたの問題を正確に把握できませんでしたが、次の図はあなたの問題を解決すると思います。 (リベース:リモートリポジトリ--->ワークスペース)

http://assets.osteele.com/images/2008/git-transport.png

ソース: マイGitワークフロー