git rebase,跟踪“本地”和“远程”

Posted

技术标签:

【中文标题】git rebase,跟踪“本地”和“远程”【英文标题】:git rebase, keeping track of 'local' and 'remote' 【发布时间】:2011-03-04 08:20:59 【问题描述】:

在执行 git rebase 时,我经常难以弄清楚在解决冲突时“本地”和“远程”发生了什么。我有时觉得他们从一个提交到下一个提交交换了双方。

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

rebase 时,谁是“本地”,谁是“远程”?

(我使用 P4Merge 解决冲突)

【问题讨论】:

阅读this 是否可能对您有所帮助?本教程的其余部分也非常很有帮助.... ***.com/questions/2959443/… 有帮助吗? (不适用于“git svn”部分,仅用于“git rebase”部分) @VonC,是的,就是这样。如果你想在这里复制你的答案的相关部分,我会打勾(这次我真的会,我保证!) 好吧...我会咬人的;)发布相关摘录。 我遇到了完全相同的问题和相同的感受(当变基时,谁是“本地”,谁是“远程”?)。即使我使用 P4Merge :-D 【参考方案1】:

我也是,迷茫了很久,经常做出错误的决定,不得不重新开始。

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

我想我已经意识到我的困惑是因为我对 rebase 的描绘与许多人绘制的不同。这里有两张通常用来描述变基的图:

--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(我们想要重新设置 onto 的提交),然后我们从那里挑选每个提交分支依次应用它们。所以“我们的”变成了“主人”,最初是56申请成功后,“我们的”是6,但实际上是“开启”master的6'

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

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

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

因此,rebase 最终结果的“真实”图片应该是:

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

在变基之后,你在8'。你的分支也是如此(我想!)。这可以(在我看来)可视化为:

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

【讨论】:

简单的规则是“我们的”或“本地”是 HEAD 所在的位置。在 rebase 期间,HEAD 位于 6',然后是 7',然后是 8'。 “因为在这种情况下,6 只获得了一个新的父节点,我们不需要新的提交?”:7 也获得了一个新的父节点:6'。因此 7 变为 7',因为它的父级发生了变化。 8 也是一样。 @VonC 你的意思是在快进的情况下我们仍然得到 6'、7' 和 8'?或者你的意思是,正如我上一张图片试图展示的那样,如果我们不能快进整个序列会生成新的提交? 如果您的答案是关于变基,则没有“快进”:变基总是会触发新的提交,因为它们的父级正在更改。 是的,你是对的。我将删除该评论。我在想用 rebase 拉动,这不是一回事吗?或者这可能是在 cmets 中的讨论/教程;-)【参考方案2】:

TL;DR;

总结一下(如Benubirdcomments),当:

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

还有:

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

一个变基切换ours(变基开始之前的当前分支)和theirs(你想要变基的分支)。


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

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

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


变基时反转

混淆可能与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

在变基上:

但是在变基上,我们切换到一边,因为变基所做的第一件事就是检查上游分支! (在其之上重播当前提交)

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

A 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 是数据的参考集(一个所有 repo 或像这里一样,一个分支,它可以是一个 local 分支)从中读取数据或新的数据添加/创建数据。


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

Pandawood 加入the comments:

对我来说,问题仍然存在,即“本地”和“远程”谁(因为在 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 将是 display the merge resolution like so:

而meld 将是display it too:

VimDiff、which displays 相同:

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

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

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

【讨论】:

对我来说,问题仍然存在,即“本地”和“远程”谁是“远程”(因为在 git 中变基时不使用术语“我们的”和“他们的”,仅指称它们似乎使答案更加混乱)。问题是“谁是本地的,谁是远程的”——所以答案肯定需要提及“本地”和“远程”这两个词 @PandaWood:“本地”是“当前分支”(变成“他们的”),“远程”是“上游分支”(变成“我们的”)。 所以,总结一下:当你 git checkout A; git rebase B 本地是 B 时,远程是 A。我只需要知道... git 就是这样一个可用性集群。这是没有意义的:当你 git checkout A; git rebase B 本地是 B 时,远程是 A。如果我checkout A,那么我 am 目前正在查看存在于A 上的文件,那么 remote 是怎么回事? (我不是说 Benubird 错了;我是说 git 有一个愚蠢的用户体验) @VonC 当然;我的(咆哮)观点是它不应该阅读文档、查看图表和浏览 ***。要是命令能给出清晰明确的反馈就好了。例如,不要显示 local/remote/theirs/ours/mine/yours,而是显示 branch Abranch B 或类似名称。【参考方案3】:

我没有完全理解您的问题,但我认为下图可以解决您的问题。 (变基:远程存储库 ---> 工作区)

来源:My Git Workflow

【讨论】:

【参考方案4】:

底线

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

在主分支上创建提交:

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

gitk --all

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

现在进行变基测试:

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)

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

【讨论】:

+1。这阐明了我在上面自己的答案中遇到的local/remote 方面(更多的是关于ourstheirs 的反转)

以上是关于git rebase,跟踪“本地”和“远程”的主要内容,如果未能解决你的问题,请参考以下文章

Interactively rebase from here(Idea Git CommitId压缩)

Interactively rebase from here(Idea Git CommitId压缩)

git fetch git pull 与 git pull --rebase

git远程分支回退

git的提交突出--git rebase之abortcontinueskip

git rebase 不使用分支