「私たち」と「彼ら」の意味がgit-svnで逆になっているのはなぜですか


90

私はgit-svnを使用していますが、を実行した後にマージの競合を修正する必要がある場合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

回答:


230

これはリベースが行うことと一致しているようです。

  • git svn rebase 現在のHEADのSVN親からリビジョンをフェッチし、現在の(SVNにコミットされていない)作業をリベースします。

  • git rebase言及:
    リベースマージは、<upstream>ブランチの上にある作業中のブランチから各コミットを再生することで機能することに注意してください。
    このため、マージの競合が発生すると、次のようになります。

    • 我々として報告側が始まる、それまでリベースシリーズです<upstream>
    • そして、彼らは作業ブランチです。
      つまり、側面が入れ替わります。

git rebaseは、作業ブランチからの各コミットをブランチの上にリプレイします<upstream>

両方の定義を調整する場合:

  • SVNからのコミットは、ローカルGitコミットがリプレイされるものです。それらは「これまでリベースされたシリーズ」の一部であり、「私たち」として参照されます(あなたの場合、コンテンツtest.txtbar含むファイル)
  • 作業ブランチ(SVN にとって未知のGitコミットを含み、あなたの場合、コンテンツtest.txtbaz含むファイル)は「それら」であり、それらのローカルGitコミットのそれぞれが再生されています。

つまり、SVNかどうか。

  • " <upstream>"ブランチ(何も再生されず、これまでにリベースされたコミットの一部である)は " 私たちのブランチ"です。
  • 再生されているもの(作業ブランチ)は「彼らのもの」です。

グッドニーモニック先端によってCommaToast

HEADが指しているものは何でも「私たち」

(そして、リベースしたいブランチgit rebase upstreamをチェックアウトするためにa が最初に行うことupstream:HEADが参照するupstream- ours今。)


混乱は、クラシックにおける作業ブランチの役割に起因する可能性がありgit mergeます。
マージするとき:

  • 「ワーキングブランチ」は「これまでにマージされた」ものを含むものであり、「私たち」と見なされます、
  • 他のコミットは何が行われているのかを表します-再生ではありません-作業ブランチの上にマージし、「彼ら」と見なされます。

git rebasemanページが言及、リベース時のマージは、サイドが交換されることを意味します。


同じことを言うもう1つの方法は、それを考慮することです。

  • 私たちが持ってチェックアウトしたブランチにすること「である私たち
  • 私たちが持っていたもの(そしてマージまたは再生されているもの)は「彼らのもの」です。

マージ時:

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はまずHEADBを上流のブランチに変更しますHEAD(したがって、以前の「現在の」作業ブランチと比較して、「ours」と「theirs」が入れ替わります。)

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 "fetch"が実行されることです。
最初は次のとおりです。

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側に切り替えます(これは「ours」になります)。

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 rebasemanページのその発言を完全に逃したに違いありません...
Marc Liyanage

@epologee:どういたしまして。gitのみを使用している場合にも、リベースとマージで何が行われているのかを理解するのにも役立ちます。そして、それは上流の定義に追加します。stackoverflow.com/questions/2739376/...
VonC

5
我が神よ!!!トーバルズはどんな種類の薬を服用していましたか?これは複雑すぎます。Gitは非常に危険なツールです。外部の知識や直感を使用しようとすると、すべての作業を簡単に破棄できます。ソフトウェア開発がワームホールを掘り下げました!
ATL_DEV 2014年

@ user148298この機能に問題はありません。gitの専門家でない限り、このようなことをすべて知っている必要はありません。また、高度な機能が必要な場合は、まずそれを学ぶ必要があります。
Earth Engine
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.