为什么用git-svn颠倒了“我们的”和“他们的”的含义


90

我使用git-svn,我注意到执行a之后必须修复合并冲突git svn rebase时,--ours--theirs选项的含义git checkout相反。也就是说,如果发生冲突,并且我想保留来自SVN服务器的版本并丢弃在本地进行的更改,则必须使用ours,如果我希望这样做的话theirs

这是为什么?

例:

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"

Jut用许多图表更新了我的答案,以更好地说明“我们的”和“他们的”方面。
VonC 2010年

Answers:


230

这似乎与rebase的工作一致。

  • git svn rebase 将从当前HEAD的SVN父级获取修订,并根据当前HEAD(不提交给SVN)对其进行基准调整。

  • git rebase确实提到:
    请注意,rebase合并是通过在分支顶部的工作分支中重放每个提交来进行工作的<upstream>
    因此,当发生合并冲突时:

    • 报道为我们方的是到目前为止已改版的系列,以开头<upstream>
    • 他们的是工作部门
      换句话说,双方互换

git rebase从分支顶部的工作分支重放每个提交<upstream>

如果您使两个定义一致:

  • 来自SVN的提交是重播本地Git提交的提交。它们是“到目前为止的基础系列”的一部分,被称为“我们的”(在您的情况下,是test.txt包含bar内容的文件)
  • 工作分支(包含SVN未知的Git提交,在您的情况下,test.txt包含baz内容的文件)为“其”,并且正在重播每个本地Git提交。

换句话说,SVN与否:

  • <upstream>”分支(在此分支上会重播所有内容,并且这是迄今为止基于重定位的提交的一部分)是“ 我们的 ”。
  • 正在重放的(工作分支)是“ 他们的 ”。

记忆提示通过CommaToast

HEAD指的是“我们的”

(首先要做的git rebase upstream是检出要在其上进行基础调整的upstream分支:HEAD是指upstream- ours现在。)


混乱可能来自经典中工作分支的角色git merge
合并时:

  • “工作分支”是包含“到目前为止已合并”的分支,被认为是“我们的”,
  • 而另一次提交则代表正在发生的事情-不是重播而是-在工作分支的顶部合并,并被视为“他们的”。

就像git rebase手册页中提到的那样,在变基过程中合并意味着交换了该边。


说同一件事的另一种方法是考虑:

  • 我们在结帐的分支上拥有的是“ 我们的 ”,
  • 我们拥有的(并且正在被合并或重放)是“ 他们的 ”。

在合并中

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上,我们切换了一方,因为rebase要做的第一件事就是检出上游分支!(重播当前提交)

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

A git rebase upstream将首先将HEADB 更改为上游分支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

,然后重新部署将在新的“我们的” 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

唯一的额外步骤git svn rebase是,首先在代表SVN提交的Git远程分支上执行svn“获取”。
您最初有:

x--x--x--x--x(*) <- current branch B, "ours" for now.
    \                                   
     \
      \--y--y--y <- SVN tracking branch, "theirs for now"

,您首先要使用来自SVN的新提交更新SVN跟踪分支

x--x--x--x--x(*) <- current branch B, still "ours", not for long
    \                                   
     \
      \--y--y--y--y'--y' <- SVN tracking branch updated

,然后将当前分支切换到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")

,在重播您正在处理的提交之前(但在重新设置期间现在是“它们的”)

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

9
哇,真是个好答案,谢谢!我肯定完全错过了git rebase手册页中的这一言论...
Marc Liyanage 2010年

@epologee:不客气。当您仅使用git时,它也很有用,以了解在进行基础调整和合并期间发生了什么。并将其添加到上游的定义:stackoverflow.com/questions/2739376/...
VonC

5
天哪!!!Torvalds服用哪种药物?这太复杂了!Git是一个非常危险的工具。如果您尝试使用外部知识或直觉,就很容易破坏所有工作。Sofware的开发已陷入虫洞!
ATL_DEV 2014年

@ user148298此功能没有错。除非您是git专家,否则您不必了解所有这些内容。如果您确实需要高级功能,则必须先学习它。
地球引擎
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.