为什么“我们的”和“他们的”的含义用 git-svn 颠倒了
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2959443/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is the meaning of “ours” and “theirs” reversed with git-svn
提问by Marc Liyanage
I use git-svn and I noticed that when I have to fix a merge conflict after performing a git svn rebase
, the meaning of the --ours
and --theirs
options to e.g. git checkout
is reversed. That is, if there's a conflict and I want to keep the version that came from the SVN server and throw away the changes I made locally, I have to use ours
, when I would expect it to be theirs
.
我使用 git-svn 并且我注意到当我必须在执行 a 后修复合并冲突时, eg和选项git svn rebase
的含义是相反的。也就是说,如果存在冲突并且我想保留来自 SVN 服务器的版本并丢弃我在本地所做的更改,我必须使用,而我希望它是.--ours
--theirs
git checkout
ours
theirs
Why is that?
这是为什么?
Example:
例子:
mkdir test
cd test
svnadmin create svnrepo
svn co file://$PWD/svnrepo svnwc
cd svnwc
echo foo > test.txt
svn add test.txt
svn ci -m 'svn commit 1'
cd ..
git svn clone file://$PWD/svnrepo gitwc
cd svnwc
echo bar > test.txt
svn ci -m 'svn commit 2'
cd ..
cd gitwc
echo baz > test.txt
git commit -a -m 'git commit 1'
git svn rebase
git checkout --ours test.txt
cat test.txt
# shows "bar" but I expect "baz"
git checkout --theirs test.txt
cat test.txt
# shows "baz" but I expect "bar"
回答by VonC
That seems consistent with what a rebase does.
这似乎与 rebase 的作用一致。
git svn rebase
will fetches revisions from the SVN parent of the current HEAD and rebases the current (uncommitted to SVN) work against it.git rebase
does mention:
Note that a rebase merge works by replaying each commit from the working branch on top of the<upstream>
branch.
Because of this, when a merge conflict happens:- the side reported as ours is the so-far rebased series, starting with
<upstream>
, - and theirs is the working branch.
In other words, the sides are swapped.
- the side reported as ours is the so-far rebased series, starting with
git svn rebase
将从当前 HEAD 的 SVN 父级获取修订,并将当前(未提交给 SVN)的工作重新绑定到它。git rebase
确实提到:
请注意,rebase 合并通过重放分支顶部的工作分支的每个提交来工作<upstream>
。
因此,当发生合并冲突时:- 报道为我们的一方是迄今为止重新调整的系列,从
<upstream>
, - 他们是工作分支。
换句话说,双方互换。
- 报道为我们的一方是迄今为止重新调整的系列,从
git rebase replays each commit from the working branch on top of the
<upstream>
branch.
git rebase 重放来自分支顶部的工作分支的每个提交
<upstream>
。
If you reconcile both definitions:
如果您调和两个定义:
- the commits coming from SVN are the ones on top of which local Git commits are replayed. They are part of the "so-far rebased series", and are referenced as "our" (in your case, the
test.txt
file withbar
content) - the working branch (containing Git commits unknown to SVN, in your case, the
test.txt
file withbaz
content) is "their", and each of those local Git commits are being replayed.
- 来自 SVN 的提交是在其上重放本地 Git 提交的提交。它们是“迄今为止重新定位的系列”的一部分,并被称为“我们的”(在您的情况下,是
test.txt
包含bar
内容的文件) - 工作分支(包含 SVN 未知的 Git 提交,在您的情况下,是
test.txt
包含baz
内容的文件)是“他们的”,并且正在重播每个本地 Git 提交。
In other words, SVN or not:
换句话说,SVN 与否:
- the "
<upstream>
" branch (on top of which anything is replayed, and which is part of the so far rebased commits") is "ours". - what is being replayed (the working branch) is "theirs".
- “
<upstream>
”分支(在其上重放任何内容,并且是迄今为止重新提交的一部分”)是“我们的”。 - 正在重播的(工作分支)是“他们的”。
Good mnemonic tipby CommaToast:
好记忆提示通过CommaToast:
whatever HEAD's pointing to is "ours"
HEAD 所指的都是“我们的”
(and the first thing a git rebase upstream
does it to checkout the upstream
branch on top of which you want to rebase: HEAD refers to upstream
-- ours
now.)
(并且 agit rebase upstream
做的第一件事是检出upstream
要在其上变基的分支:HEAD 指的是upstream
--ours
现在。)
The confusion is likely coming from the role of the working branch in a classic git merge
.
When you are merging:
混淆可能来自经典中工作分支的角色git merge
。
合并时:
- the "working branch" is the one containing what is "so far merged", and is considered as "our",
- while the other commit represent what is being -- not replayed but -- merge on top of the working branch, and considered as "their".
- “工作分支”是包含“到目前为止已合并”的分支,并被视为“我们的”,
- 而另一个提交代表正在发生的事情——不是重播而是——合并在工作分支的顶部,并被视为“他们的”。
As the git rebase
man page mentions, a merge during a rebase means the side are swapped.
正如git rebase
手册页所提到的,在变基期间进行合并意味着交换了一侧。
Another way to say the same thing is to consider that:
说同样的事情的另一种方式是考虑:
- what we haveon the checked out branch is 'ours',
- what we had(and is being merged or replayed) is 'theirs'.
- 我们在签出的分支上拥有的是“我们的”,
- 我们拥有的(正在合并或重播)是“他们的”。
On a merge:
在合并上:
x--x--x--x--x(*) <- current branch B ('*'=HEAD)
\
\
\--y--y--y <- other branch to 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)
,我们不改变当前分支'B',所以我们所拥有的仍然是我们正在处理的(并且我们从另一个分支合并)
x--x--x--x--x---------o(*) MERGE, still on branch B
\ ^ /
\ ours /
\ /
--y--y--y--/
^
their
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)
但是在 rebase 上,我们换边了,因为 rebase 做的第一件事就是检出上游分支!(在其上重放当前提交)
x--x--x--x--x(*) <- current branch B
\
\
\--y--y--y <- upstream branch
A git rebase upstream
will first change HEAD
of B to the upstream branch HEAD
(hence the switch of 'ours' and 'theirs' compared to the previous "current" working branch.)
Agit rebase upstream
将首先将HEAD
B更改为上游分支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
, and then the rebase will replay 'their' commits on the new 'our' B branch:
,然后 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
The only extra step with git svn rebase
is that a svn "fetch" is performed first on the Git remote branch representing SVN commits.
You have initially:
唯一的额外步骤git svn rebase
是首先在代表 SVN 提交的 Git 远程分支上执行 svn “fetch”。
您最初拥有:
x--x--x--x--x(*) <- current branch B, "ours" for now.
\
\
\--y--y--y <- SVN tracking branch, "theirs for now"
, you first update the SVN tracking branch with new commits coming from SVN
,您首先使用来自 SVN 的新提交更新 SVN 跟踪分支
x--x--x--x--x(*) <- current branch B, still "ours", not for long
\
\
\--y--y--y--y'--y' <- SVN tracking branch updated
, then you switch the current branch to the SVN side (which becomes "ours")
,然后将当前分支切换到 SVN 端(变成“我们的”)
x--x--x--x--x <- for "B", now "their" during the rebase
\
\
\--y--y--y--y'--y'(*) <- SVN tracking branch updated, and branch B:
now "ours" (this is "what we now have")
, before replaying the commits you were working on (but which are now "theirs" during that rebase)
, 在重放您正在处理的提交之前(但在该变基期间现在是“他们的”)
x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
\
\
\--y--y--y--y'--y'--x'--x'--x'(*) <- branch B with HEAD updated ("ours")
^
|
upstream SVN tracking branch