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 的提交),然后我们从那里挑选每个提交分支依次应用它们。所以“我们的”变成了“主人”,最初是5
。 6
申请成功后,“我们的”是6
,但实际上是“开启”master的6'
:
然后我们继续使用“7”。
所以在合并中你“在”8
并将两者组合成一个新的提交,但在 rebase 中你移动到 5
并尝试将分支上的提交中的差异应用为新的在那里提交。
因此,rebase 最终结果的“真实”图片应该是:
--1--2--3--4--5--6'--7'--8' \ 6--7--8在变基之后,你在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
local
是 B
(rebase onto),
remote
是 A
还有:
git checkout A
git merge B # merge B into A
local
是A
(合并到),
remote
是 B
一个变基切换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 已尽可能多地执行自动冲突解决,并且此文件的状态是
LOCAL
和REMOTE
的组合,其中包含 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 A
和 branch 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
方面(更多的是关于ours
与theirs
的反转)以上是关于git rebase,跟踪“本地”和“远程”的主要内容,如果未能解决你的问题,请参考以下文章
Interactively rebase from here(Idea Git CommitId压缩)
Interactively rebase from here(Idea Git CommitId压缩)
git fetch git pull 与 git pull --rebase