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

时间:2010-06-16 07:43:04

标签: git conflict rebase

在进行git rebase时,我常常难以解决在解决冲突时“本地”和“远程”发生的事情。我有时会觉得他们将一方提交交换到另一方提交。

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

当变基,谁是'本地'而谁是'偏远'?

(我使用P4Merge解决冲突)

4 个答案:

答案 0 :(得分:211)

TL; DR;

总结(作为Benubird comments),何时:

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

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


kutschkem指出,GUI合并工具上下文中的

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

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


反转时的反转

混淆可能与inversion of ours and theirs during a rebase有关 (相关摘录)

git rebase man page

  

请注意,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

关于rebase:

在rebase 上,我们切换侧面,因为rebase的第一件事就是结帐上游分支! (重播当前提交的内容)

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

git rebase upstream 首先会将B的HEAD更改为上游分支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

,然后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

注意:"upstream" notion是数据的引用数据集(一个全部存储库,或者像这里一样,一个分支,可以是本地分支),从中读取数据或者添加/创建了哪些新数据。


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

Pandawood添加了the comments

  

对我来说,问题仍然存在,那就是“本地”,谁是“偏远的”(因为在git中重新定位时不使用“我们的”和“他们的”这些术语,指的是它们似乎只是回答更令人困惑的)。

GUI git mergetool

kutschkem补充说,这是正确的:

  

在解决冲突时,git会说:

local: modified file and remote: modified file. 
  

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

  • 本地引用部分重新提交的提交:“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):

例如,KDiff3display the merge resolution like so

kdiff3

melddisplay it too

Meld diff

VimDiffwhich displays

相同
  

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

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  
      
  • LOCAL
      包含当前分支上文件内容的临时文件。
  •   
  • BASE
      包含合并公共基础的临时文件。
  •   
  • REMOTE
      包含要合并的文件内容的临时文件。
  •   
  • MERGED
      包含冲突标记的文件。
  •   
     

Git已尽可能多地执行自动冲突解决,此文件的状态是LOCALREMOTE的组合,其中包含Git无法自行解决的任何问题的冲突标记。
  mergetool应将解析结果写入此文件。

答案 1 :(得分:40)

底线

git rebase

  • LOCAL =您将重新定位到
  • 的基础
  • 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."

在主分支上创建提交:

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

现在进行rebase测试:

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

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

git rebase --abort

然后:

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

您的搜索结果应与最常显示的内容相同。

答案 2 :(得分:3)

我没有完全解决您的问题,但我认为下图解决了您的问题。 (Rebase:Remote Repository ---&gt; Workspace)

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

来源:My Git Workflow

答案 3 :(得分:0)

我也很困惑很长时间,常常会做出错误的决定,必须重新开始。

免责声明:我不是git专家,所以如果这里有什么问题,请纠正我!

我想我已经意识到我的困惑是因为我对重新基准的描绘与许多绘制它的方式不同。这是两个通常用来描述变基的图:

  --1--2--3--4--5
     \
      6--7--8

然后

  --1--2--3--4--5--6--7--8

当然,这是绘制它的一种方法,但是我对rebase发生的事情的感觉是:

  --1--2--3--4--5
                 \
                  6--7--8

当然是完全一样的。但是从“我们/他们”的角度来看,情况有所不同。在第二种情况下,感觉“我们”仍在分支上(“ 6--7--8”),我们想从“主”那里接取更改。因此,在这个世界上,“我们的”仍然是“分支”。这就是让我感到困惑的地方。

但是在第一个“世界视图”(我想是Git的视图)中,我们移至主控(我们希望将作为基础的提交),然后从中选择每个提交依次分支并应用它们。因此,“我们的”最初是5成为“主人”。成功应用6之后,“我们的”是6,但实际上是“在”母版上的6'

  --1--2--3--4--5--6'
     \
      6--7--8

然后我们继续使用“ 7”。

因此,在合并中,您“在” 8上,并将两者合并到一个新的提交中,但是在重新设置基准时,您移至5并尝试将差异应用于分支作为新的提交在那里。

因此,变基最终结果的“真实”图景应该确实是:

  --1--2--3--4--5--6'--7'--8'
     \
      6--7--8

在重新设置基准之后,您将进入8'。您的分支机构也是如此(我想!)。可以(在我看来)可视化为:

  --1--2--3--4--5
     \           \
      6--7--8     6'--7'--8'