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


174

git rebaseを実行するとき、競合を解決するときに「ローカル」と「リモート」で何が起こっているのかを理解するのが難しいことがよくあります。あるコミットから次のコミットにサイドを入れ替えるような印象を受けることがあります。

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

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

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


これを読むことがあなたを助けることは可能ですか?チュートリアルの残りの部分はある非常に ....だけでなく、便利
ivans

別の優れたgit リソース
不明

stackoverflow.com/questions/2959443/...助けを?(「git svn」部分ではなく、「git rebase」部分のみ)
VonC

@VonC、はい、それだけです。ここに回答の関連部分をコピーしたい場合は、チェックします(今回は本当にそうします、約束します!)
Benjol

大丈夫...私はかむよ;)投稿された関連抽出物。
VonC、2010年

回答:


243

TL; DR;

要約すると(Benubirdの コメントとして)、いつ:

git checkout A
git rebase   B    # rebase A on top of B
  • localされているB(リベース)、
  • remote です A

そして:

git checkout A
git merge    B    # merge B into A
  • localであるA(マージ、)
  • remote です B

rebaseはours(rebaseが開始する前の現在のブランチ)とtheirs(リベースしたいブランチ)を切り替えます。


kutschkem は、GUIのmergetoolコンテキストで次のように指摘しています

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

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


リベース時の反転

混乱は、リベースの反転中oursおよびtheirsリベース中の可能性があります。
(関連抽出物)

git rebasemanページ

リベースマージは、作業ブランチからの各コミットをブランチの上で再生することで機能することに注意してください<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(したがって、以前の「現在の」作業ブランチと比較して、「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

kutschkemが追加しました。

競合を解決するとき、gitは次のように言います。

local: modified file and remote: modified file. 

この時点での質問は、ローカルとリモートの定義を目的としていると確信しています。その時点で、私には私の経験から次のように思われます。

  • ローカルは部分的にリベースされたコミットを参照します: " ours"(上流のブランチ)
  • remoteは受信する変更を参照します: " 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は次のようにマージ解像度表示します

kdiff3

そして、メルドもそれ表示します

溶融差分

以下のための同じはvimdiff表示されます

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

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

Gitは可能な限り多くの自動競合解決を実行しており、このファイルの状態は両方の組み合わせと、Gitがそれ自体で解決できなかったものを囲む競合マーカーLOCALとの組み合わせですREMOTE。このファイルへの解決の結果を記述する必要があります。
mergetool


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

@PandaWood:「local」は「現在のブランチ」(「theirs」になります)、「remote」は「上流のブランチ」(「ours」になります)です。
VonC、2011

3
つまり、要約すると、git checkout A; git rebase BローカルがBの場合、リモートはAです。知っておくべきことはすべて...
Benubird 2013

1
gitはそのようなユーザビリティのclusterfkです。これは意味がありません。git checkout A; git rebase BローカルがBの場合、リモートはAです。私がした場合checkout A、私は午前彼らが存在するとして、現在のファイルを見てA、どのようにどのような方法であることをリモート?(私はBenubirdが間違っていると言っているのではありません。gitには愚かなUXがあると言っています)
Rafa

1
@VonC確かに; 私の(正当化する)ポイントは、ドキュメントを読んだり、図を調べたり、StackOverflowを参照したりする必要はないということです。コマンドだけが明確で明確なフィードバックを提供した場合。たとえば、代わりにローカル/リモート/彼ら/我々 /鉱山/あなたの、ちょうど示し{branch A}および{branch B}または類似。
Rafa

45

肝心なこと

git rebase

  • LOCAL =リベースするベース
  • REMOTE =最上位のコミット

gitマージ

  • 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

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

ベースコミットと2つの1コミットブランチを持つリポジトリ

リベーステストの場合:

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)

結果は、上に表示されているものと同じになります。


1
+1。それは私が上記の私自身の答えで苦労したlocal/ remote側面を明らかにします(とにかくoursvs の逆転についてtheirsです)
VonC

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.