Git重基,跟踪'本地'和& # 39;远程# 39;

在做git rebase时,在解决冲突时,我经常很难弄清楚“本地”和“远程”发生了什么。我有时有这样的印象,他们从一个承诺到下一个承诺会交换立场。

这可能(肯定)是因为我还没有完全理解。

当改变基础,谁是“本地”和谁是“远程”?

(我使用P4Merge来解决冲突)

44137 次浏览

我没有完全理解你的问题,但我认为下面的图表解决了你的问题。(Rebase: Remote Repository—> Workspace)

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

来源:我的Git工作流

TL,博士;

总结一下(As Benubird 评论),当:

git checkout A
git rebase   B    # rebase A on top of B
  • localB (rebase ),
  • remoteA

和:

git checkout A
git merge    B    # merge B into A
  • localA(合并),
  • remoteB

rebase会切换ours(在rebase开始之前的当前分支)和theirs(你想要在其上进行rebase的分支)。


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

  • 局部引用部分重基提交: "ours"(上游分支)
  • Remote指的是传入的更改: "theirs" -重基前的当前分支。

请参见答案最后一部分的插图。


重构时的反转

混淆可能与在rebase过程中,__ABC0和theirs的反转有关 (相关提取)< / p >

git rebase手册页:

注意,rebase merge的工作原理是在<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做的第一件事是检出上游分支!(在上面重放当前提交)

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

A git rebase upstream将首先将B的HEAD更改为上游分支HEAD(因此与之前的“当前”工作分支相比,切换为“our”和“their”。)

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将在新的'our' B分支上重放'their'提交:

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

注意:“上游”概念是数据的参考集(一个all repo,或者像这里一样,一个分支,可以是当地的分支),从中读取数据或向其中添加/创建新数据。


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

Pandawood的评论中添加:

对我来说,问题仍然存在,谁是“本地的”,谁是“远程的”(因为术语“我们的”和“他们的”在git中换基时不使用,提到它们似乎只是让答案更混乱)。

GUI git合并工具

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

融合也要展示出来:

Meld diff

VimDiff它显示也一样:

使用git mergetool -t gvimdiff调用Vimdiff作为合并工具。最新版本的Git调用Vimdiff的窗口布局如下:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
    <李> LOCAL: < br > 包含当前分支上文件内容的临时文件。李< / > <李> BASE: < br > 包含合并的公共基础的临时文件。李< / > <李> REMOTE: < br > 包含待合并文件内容的临时文件。李< / > <李> MERGED: < br > 包含冲突标记的文件。李< / >
Git已经执行了尽可能多的自动冲突解决,该文件的状态是LOCALREMOTE的组合,冲突标记围绕着Git自己无法解决的任何内容 mergetool应将解析结果写入此文件。< / p >

底线

git变基

  • LOCAL =你要重基的基数
  • REMOTE =你要移动到上面的提交

git合并

  • 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."

在不是master的分支上创建一个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

此时,你的存储库应该是这样的:

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

现在进行rebase测试:

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

现在是合并测试。关闭你的合并工具,不保存任何更改,然后取消rebase:

git rebase --abort

然后:

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

你的结果应该和上面显示的一样。

我也困惑了很长一段时间,经常做出错误的决定,不得不重新开始。

免责声明:我不是git专家,所以如果这里有任何错误,请纠正我!

我想我已经意识到,我的困惑是因为我想象的改基与许多人画的不一样。下面是两张通常用来描述改基的图:

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

然后

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

当然,这是一种画法,但我的感觉是这样的:

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

当然是完全一样的。但从“我们的/他们的”;视角是不同的。在第二种情况下,感觉好像“我们”;仍然“继续”;分支(“6—7—8”),我们想从“大师”中获得变化。所以在这个世界上“我们的”;仍然是“分支”。这就是让我困惑的地方。

但是在第一个“世界观”中,我认为这是Git的观点,我们移动到master(我们想要重基的提交),然后从那里依次选择分支上的每个提交并应用它们。所以“ours"成为“大师”,最初56成功应用后,"our "是6,但实际上6'是"on"主:

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

然后我们继续同样的“7”。

所以在合并中,你“正在进行”;8并将两者合并到一个新的提交中,但在rebase中,你移动到5并尝试在分支上作为新提交应用提交中的差异。

所以“true”;最终结果的图片应该是:

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

而在改基之后,你在8'上。你的分支也一样(我想!)在我的脑海中,这可以想象为:

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