git rebase,跟踪“本地”和“远程”
在进行 git rebase 时,我经常很难在解决冲突时弄清楚“本地”和“远程”发生了什么。我有时有一种印象,他们从一个承诺到下一个承诺都会交换立场。
这可能(肯定)是因为我仍然没有正确理解这个范式。
变基时,谁是“本地”,谁是“远程”?
(我使用 P4Merge 来解决冲突。)
When doing a git rebase
, I often have difficulty working out what is happening with the 'local' and 'remote' when resolving conflicts. I sometimes have the impression that they swap sides from one commit to the next.
This is probably (definitely) because I still don't properly understand the paradigm.
When rebasing, who is 'local' and who is 'remote'?
(I use P4Merge for resolving conflicts.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
TL;博士;
总结一下(如 Benubird 评论),当:
local
是B
(变基< strong>onto),远程
是A
并且:
本地
是A
(合并 into),remote
是B
A rebase 切换
ours
(rebase 开始前的当前分支)和他们的
(要在其上变基的分支)。kutschkem 指出,在 GUI mergetool 上下文中:
ours
”(上游分支)theirs
” - 之前的当前分支变基。请参阅本答案最后部分的插图。
变基时反转
混乱可能与 在变基期间
我们的
和他们的
反转。(相关摘录)
git rebase
手册页:因此,当发生合并冲突时:
ours
”的一侧是迄今为止重新调整基数的系列,从
开始,>theirs
' 是工作分支。换句话说,双方交换了。
反转说明
在合并上
,我们不会更改当前分支“B”,因此我们所拥有的仍然是我们正在处理的内容(并且我们从另一个分支合并)
在变基上:
但是在变基上,我们切换一边,因为变基所做的第一件事就是签出上游分支! (重放其上的当前提交)
git rebase upper
将首先将 B 的HEAD
更改为上游分支HEAD
(因此与之前的“当前”工作分支相比,“我们的”和“他们的”进行了切换。),然后 rebase 将在新的“我们的”B 分支上重播“他们的”提交:
注意: “上游”概念是参考数据集(所有存储库或者像这里一样,一个分支,可以是本地分支),从中读取数据或添加/创建新数据。
“
本地
”和“远程
”与“我的
”和“他们的
”Pandawood 添加了 评论:
GUI git mergetool
kutschkem 添加,正确的是:
ours
”(上游分支)theirs
” - 变基之前的当前分支。git mergetool
确实提到了“本地”和“远程”:例如,KDiff3 将像这样显示合并分辨率 :
和 meld 也会显示它:
与 VimDiff,显示:
TL;DR;
To summarize (As Benubird comments), when:
local
isB
(rebase onto),remote
isA
And:
local
isA
(merge into),remote
isB
A rebase switches
ours
(current branch before rebase starts) andtheirs
(the branch on top of which you want to rebase).kutschkem points out that, in a GUI mergetool context:
ours
" (the upstream branch)theirs
" - the current branch before the rebase.See illustrations in the last part of this answer.
Inversion when rebase
The confusion might be related to the inversion of
ours
andtheirs
during a rebase.(relevant extracts)
git rebase
man page:Because of this, when a merge conflict happens:
ours
' is the so-far rebased series, starting with<upstream>
,theirs
' is the working branch.In other words, the sides are swapped.
Inversion illustrated
On a merge
, we don't change the current branch 'B', so what we have is still what we were working on (and we merge from another branch)
On a rebase:
But on a rebase, we switch side because the first thing a rebase does is to checkout the upstream branch! (to replay the current commits on top of it)
A
git rebase upstream
will first changeHEAD
of B to the upstream branchHEAD
(hence the switch of 'ours' and 'theirs' compared to the previous "current" working branch.), and then the rebase will replay 'their' commits on the new 'our' B branch:
Note: the "upstream" notion is the referential set of data (a all repo or, like here, a branch, which can be a local branch) from which data are read or to which new data are added/created.
'
local
' and 'remote
' vs. 'mine
' and 'theirs
'Pandawood adds in the comments:
GUI git mergetool
kutschkem adds, and rightly so:
ours
" (the upstream branch)theirs
" - the current branch before the rebase.git mergetool
does indeed mention 'local' and 'remote':For instance, KDiff3 would display the merge resolution like so:
And meld would display it too:
Same for VimDiff, which displays:
底线
git rebase
git 上移动的提交merge
换句话说,LOCAL 始终是原始分支,REMOTE< /strong> 总是那些以前没有提交过的人,因为它们正在被合并或重新基于顶部
证明它!
当然。别相信我的话!这是一个简单的实验,您可以亲自看看。
首先,确保 git mergetool 配置正确。 (如果没有,您可能无论如何都不会阅读这个问题。)然后找到一个要工作的目录。
设置您的存储库:
创建一个初始提交(使用空文件):
在一个分支上创建一个提交不是 master:
在 master 分支上创建提交:
此时您的存储库应如下所示:
现在进行变基测试:
现在进行合并测试。关闭合并工具而不保存任何更改,然后取消变基:
然后:
您的结果应该与顶部显示的结果相同。
The bottom line
git rebase
git merge
In other words, LOCAL is always the original, and REMOTE is always the guy whose commits weren't there before, because they're being merged in or rebased on top
Prove it!
Certainly. Don't take my word for it! Here's an easy experiment you can do to see for yourself.
First, make sure you have git mergetool configured properly. (If you didn't, you probably wouldn't be reading this question anyway.) Then find a directory to work in.
Set up your repository:
Create an initial commit (with an empty file):
Create a commit on a branch that isn't master:
Create a commit on the master branch:
At this point your repository should look like this:
Now for the rebase test:
Now the merge test. Close your mergetool without saving any changes, and then cancel the rebase:
Then:
Your results should be the same as what's shown up top.
我也曾经迷茫过很长一段时间,经常做出错误的决定,不得不重新开始。
我想我已经意识到我的困惑是因为我对变基的想象与许多人所描绘的不同。这里有两张通常用来描述变基的图:
然后
当然这是绘制它的一种方法,但是我对变基发生的情况的感觉是这样的:
这当然是完全一样。但从“我们/他们”的角度来看,情况有所不同。在第二种情况下,感觉好像“我们”仍然“在”分支上(“6--7--8”),并且我们想要从“master”那里获取更改。所以在这个世界上“我们的”仍然是“枝条”。这就是让我困惑的地方。
但在第一个“世界观”中,我认为这是 Git 的视图,我们移动到 master(我们想要变基到的提交),然后从那里我们选择分支上的每个提交转动并应用它们。所以“我们的”变成了“主人”,最初是
5
。成功应用6
后,“我们的”是6
,但实际上是“在”master 上的6'
:然后我们继续对“7”进行同样的处理。
因此,在合并中,您“位于”
8
并将两者组合成一个新的提交,但在变基中,您移动到 5
并尝试应用差异分支上的提交作为那里的新提交。因此,rebase 最终结果的“真实”图片应该是:
在 rebase 之后,您位于
8'
。你的分支也是如此(我想!)。这可以想象为(在我看来):I too, was confused for a long time, often making the wrong decision and had to start over.
I think I have come to the realization that my confusion was because I pictured a rebase differently than what many draw it. Here are two drawings that commonly are used to describe a rebase:
and then
And of course that is one way to draw it, but my feeling of what is happening with a rebase is this:
Which of course is exactly the same. But from an "ours/theirs" perspective it is different. In the second case it feels as if "we" are still "on" the branch ("6--7--8") and we want to pick up the changes from the "master". So in this world "ours" is still the "branch". And this is what confused me.
But in the first "world view", which I suppose is Git's view, we move to the master (the commit we want to rebase onto) and from there we pick each of the commits on the branch in turn and apply them. So "ours" becomes the "master", initially
5
. After6
has been applied successfully, "ours" is the6
, but actually the6'
that is "on" the master:And then we go on for the same with the "7".
So in a merge you "are on" the
8
and combine the two into a new commit, but in a rebase you move to the5
and try to apply the diffs in the commits on the branch as new commits there.So the "true" picture of the end result of a rebase should really be:
And after the rebase you are on
8'
. And so is you branch (I think!). And this could be visualized (in my mind) as:让我看到这个页面的是需要了解 git 树中的哪个 SHA 是我们的 / 基础 / 他们的(或 LOCAL / BASE / REMOTE )。
接受的答案,7年来的累积工作是惊人的,并且非常有帮助。
然而,我发现它缺少我正在寻找的有利位置。
当合并冲突变得严重时(尤其是由 Visual Studio 管理的 XML 文件,尤其是
.dtsx
文件),我希望能够轻松比较普通版本。阅读答案后,我对所看到的内容有了更好的理解,但是如何识别我正在比较的提交/分支?我想要合并之前文件(或分支)的 SHA,位于我所在的变基位置。
首先,我了解了 ls-files --stage 以及每个状态如何具有一个直接 SHA (有关更多信息,请参阅我提供的这个答案)
但这并不能帮助我理解涉及哪些提交- 尤其是当 rebase 超过了几个深度的承诺时。
然后我了解了 .git/rebase_merge 目录及其内容。
使用以下 git 别名,您可以获得 rebase 的每个 BASE、LOCAL 或 REMOTE 提交的 SHA:
这允许我执行诸如 * 之类的操作:
* 虽然,这不是最方便的方法(请参阅此相关答案 - 与上面提到的相同 - 有关更多选项),这个将即使在
git add
或之后也能工作
What got me to this page is the need to understand which SHA in the git tree is ours / base / theirs ( or LOCAL / BASE / REMOTE ).
The accepted answer, a cumulative work across 7 years is amazing, and is very helpful.
However, I found it was missing the vantage point I was looking for.
When a merge conflict goes bad (happens to me a lot with XML files managed by Visual Studio -
.dtsx
files in particular), I would like to be able to compare vanilla versions easily.After reading the answer, I have a better understanding of what I'm seeing, but how do I identify the commit/branch I'm comparing with? I wanted the SHA of the files (or the branches) before the merge, in the position of the rebase I'm in.
First I learned about
ls-files --stage
and how each state has a direct SHA (for more on this, see this answer I provided)But this didn't help me understand which commits are involved - especially when a rebase is more than a couple commits deep.
Then I learned about
.git/rebase_merge
directory and it's content.With the following git aliases, you can get the SHA of each of the BASE, LOCAL or REMOTE commits of a rebase:
This allows me to do things like*:
* although, it's not the most convenient method (see this related answer - same as mentioned above - for more options), this one will work even after a
git add
or
我没有完全理解您的问题,但我认为下图可以解决您的问题。 (Rebase : 远程存储库 ---> 工作区)
来源:我的 Git 工作流程
I didn't get your problem exactly but I think the following diagram resolves your issue. (Rebase : Remote Repository ---> Workspace)
Source: My Git Workflow