git rebase,跟踪'本地'和'远程'

Ben*_*jol 161 git conflict rebase

在进行git rebase时,我常常难以解决在解决冲突时"本地"和"远程"发生的事情.我有时会产生这样的印象:他们将一方提交交换到另一方提交.

这可能(肯定)因为我还没有正确理解.

变基础时,谁是'本地',谁是'偏远'?

(我使用P4Merge解决冲突)

Von*_*onC 224

TL; DR;

总结(作为Benubird 评论),时间:

git checkout A
git rebase   B    # rebase A on top of B
Run Code Online (Sandbox Code Playgroud)
  • localB(变基),
  • remoteA

和:

git checkout A
git merge    B    # merge B into A
Run Code Online (Sandbox Code Playgroud)
  • localA(合并),
  • remoteB

一个rebase切换ours(在rebase启动之前的当前分支)和theirs(你要在其上重新绑定的分支).


kutschkem指出,在GUI mergetool上下文中:

  • 本地引用部分重新提交的提交:" ours"(上游分支)
  • remote指的是传入的更改:" theirs" - rebase之前的当前分支.

请参阅本答案最后部分的插图.


反转时的反转

混乱可能与反叛反转ours和反转有关theirs.
(相关摘录)

git rebase手册页:

请注意,rebase合并的工作原理是从分支顶部的工作分支重放每个提交<upstream>.

因此,当发生合并冲突时:

  • 报道为' ours'的那一方是迄今为止重新定位的系列,首先是<upstream>,
  • 并且' theirs'是工作分支.换句话说,双方交换.

倒置说明

在合并上

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    \
     \
      \--y--y--y <- other branch to merge
Run Code Online (Sandbox Code Playgroud)

,我们不会更改当前分支'B',所以我们所拥有的仍然是我们正在处理的(并且我们从另一个分支合并)

x--x--x--x--x---------o(*)  MERGE, still on branch B
    \       ^        /
     \     ours     /
      \            /
       --y--y--y--/  
               ^
              their
Run Code Online (Sandbox Code Playgroud)

在一个变种:

但是在一个rebase上,我们会改变方向,因为rebase的第一件事就是检查上游分支!(重播当前提交)

x--x--x--x--x(*) <- current branch B
    \
     \
      \--y--y--y <- upstream branch
Run Code Online (Sandbox Code Playgroud)

A git rebase upstream首先将HEADB 更改为上游分支HEAD(因此,将"我们的"和"他们的"与之前的"当前"工作分支进行切换.)

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
Run Code Online (Sandbox Code Playgroud)

然后,rebase将重播"我们的"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
Run Code Online (Sandbox Code Playgroud)

注意:"上游"概念是参考数据集(一个全部存储库,或者像这里一样,一个分支,可以是一个本地分支),从中读取数据或添加/创建新数据.


' local'和' remote'与' mine'和' theirs''

Pandawood评论中补充道:

对我来说,问题仍然存在,即"本地"和谁是"远程"(因为在git中重新定位时不使用术语"我们的"和"他们的",指的是它们似乎只是让答案更加混乱) .

GUI git mergetool

kutschkem补充说,这是正确的:

在解决冲突时,git会说:

local: modified file and remote: modified file. 
Run Code Online (Sandbox Code Playgroud)

我很确定这个问题的目的是定义本地和远程.那时,根据我的经验,在我看来:

  • 本地引用部分重新提交的提交:" ours"(上游分支)
  • remote指的是传入的更改:" theirs" - rebase之前的当前分支.

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):
Run Code Online (Sandbox Code Playgroud)

例如,KDiff3显示合并分辨率,如下所示:

kdiff3

并且meld也会显示它:

Meld diff

同为vimdiff同时,它显示:

使用git mergetool -t gvimdiff将Vimdiff作为mergetool调用.最新版本的Git使用以下窗口布局调用Vimdiff:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
Run Code Online (Sandbox Code Playgroud)
  • LOCAL:
    包含当前分支上文件内容的临时文件.
  • BASE:
    包含合并公共基础的临时文件.
  • REMOTE:
    包含要合并的文件内容的临时文件.
  • MERGED:
    包含冲突标记的文件.

Git已尽可能多地执行自动冲突解决,并且此文件的状态是两者的组合,LOCAL并且REMOTE包含Git无法自行解决的任何事件的冲突标记.
mergetool应写入解决这一文件的结果.

  • 对我来说,问题仍然存在,即"本地"和谁是"远程"(因为在git中重新定位时不使用术语"我们的"和"他们的",指的是它们似乎只是让答案更加混乱) .问题是"谁是本地人,谁是偏远的" - 所以答案肯定需要提到"本地"和"远程"这两个字 (12认同)
  • 所以,总结一下:当你`git checkout A; git rebase B` local是B,remote是A.我需要知道... (3认同)
  • @VonC 当然;我(咆哮的)观点是,它不应该阅读文档、查看图表以及浏览 StackOverflow。如果指挥部能够给出清晰、明确的反馈就好了。例如,仅显示“{branch A}”和“{branch B}”或类似内容,而不是本地/远程/他们的/我们的/我的/你的。 (2认同)

Rya*_*ndy 43

底线

git rebase

  • LOCAL =你在基础重建的基础
  • REMOTE =承诺你正在向上移动

git merge

  • LOCAL =您要合并的原始分支
  • REMOTE =你正在合并的另一个分支

换句话说,LOCAL始终是原始版本,而REMOTE总是那些之前没有提交过的人,因为它们被合并或重新定位在顶层

证明给我看!

当然.不要相信我的话!这是一个简单的实验,您可以自己查看.

首先,确保正确配置了git mergetool.(如果你没有,你可能无论如何都不会阅读这个问题.)然后找一个可以使用的目录.

设置您的存储库:

md LocalRemoteTest
cd LocalRemoteTest
Run Code Online (Sandbox Code Playgroud)

创建初始提交(使用空文件):

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."
Run Code Online (Sandbox Code Playgroud)

在非master的分支上创建提交:

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

在主分支上创建提交:

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

gitk --all
Run Code Online (Sandbox Code Playgroud)

此时,您的存储库应如下所示:

具有基本提交和两个一次提交分支的存储库

现在进行rebase测试:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster
Run Code Online (Sandbox Code Playgroud)

现在进行合并测试.关闭mergetool而不保存任何更改,然后取消rebase:

git rebase --abort
Run Code Online (Sandbox Code Playgroud)

然后:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)
Run Code Online (Sandbox Code Playgroud)

您的结果应与顶部显示的结果相同.