为什么"我们的"和"他们的"的含义与git-svn相反

Mar*_*age 89 git git-svn

我使用git-svn并且我注意到当我必须在执行a之后修复合并冲突时,例如和的选项git svn rebase的含义是相反的.也就是说,如果存在冲突并且我想保留来自SVN服务器的版本并丢弃我在本地进行的更改,我必须使用,当我期望它.--ours--theirsgit checkoutourstheirs

这是为什么?

例:

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"
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 225

这似乎与rebase的作用一致.

  • git svn rebase 将从当前HEAD的SVN父级获取修订,并将当前(未提交到SVN)的工作重新绑定.

  • git rebase确实提到:
    请注意,rebase合并的工作原理是从分支顶部的工作分支重放每个提交<upstream>.
    因此,当发生合并冲突时:

    • 报道为我们的那一方是迄今为止重新定位的系列,从以下开始<upstream>,
    • 他们是工作部门.
      换句话说,双方交换.

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

如果你调和两个定义:

  • 来自SVN的提交是重放本地Git提交的提交.它们是"迄今为止重新定义的系列"的一部分,并被引用为"我们的"(在您的情况下,test.txt带有bar内容的文件)
  • 工作分支(包含Git未知的SVN,在您的情况下,test.txt带有baz内容的文件)是"他们的",并且正在重播每个本地Git提交.

换句话说,SVN与否:

  • " <upstream>"分支(在其上面重放任何内容,并且是迄今为止重新提交的内容的一部分")是" 我们的 ".
  • 被重播的内容(工作分支)是" 他们的 ".

记忆提示通过CommaToast:

无论HEAD指出的是"我们的"

(并且首先git rebase upstream要检查upstream你想要重新定位的分支:HEAD指的是upstream- ours现在.)


混乱可能来自工作分支在经典中的作用git merge.
当你合并时:

  • "工作分支"是包含"到目前为止合并"的内容,被视为"我们的",
  • 而另一个提交代表什么是 - 没有重播但是 - 合并在工作分支之上,并被视为"他们的".

正如git rebase手册页提到的那样,在rebase期间合并意味着交换了一方.


说同样事情的另一种方式是考虑:

  • 我们在签出的分支上的内容是' 我们的 ',
  • 我们所拥有的(并且正在合并或重播)是' 他们 '.

在合并上:

x--x--x--x--x(*) <- current branch B ('*'=HEAD)
    \
     \
      \--y--y--y <- other branch to merge
Run Code Online (Sandbox Code Playgroud)

,我们不会更改当前分支'B',所以我们所拥有的仍然是我们正在处理的(并且我们从另一个分支合并)

x--x--x--x--x---------o(*)  MERGE, still on branch B
    \       ^        /
     \     ours     /
      \            /
       --y--y--y--/  
               ^
              their
Run Code Online (Sandbox Code Playgroud)

但是在一个rebase上,我们会改变方向,因为rebase的第一件事就是检查上游分支!(重播当前提交)

x--x--x--x--x(*) <- current branch B
    \
     \
      \--y--y--y <- upstream branch
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

然后,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
Run Code Online (Sandbox Code Playgroud)

唯一的额外步骤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"
Run Code Online (Sandbox Code Playgroud)

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

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

,然后你将当前分支切换到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")
Run Code Online (Sandbox Code Playgroud)

,在重播您正在进行的提交之前(但现在在该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
Run Code Online (Sandbox Code Playgroud)

  • 哇,多好的回答,谢谢!我必须完全错过了`git rebase`手册页中的那句话...... (9认同)
  • 天哪!!!Torvalds服用什么药?这太复杂了!Git是一个非常危险的工具.如果您尝试使用外部知识或直觉,您可以轻松地销毁所有工作.软件开发已经走下了虫洞! (4认同)