Почему имеет значение “наш”, и “их” инвертировал с мерзавцем-svn

Я использую мерзавца-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"
89
задан Marc Liyanage 2 June 2010 в 16:38
поделиться

1 ответ

Это кажется соответствующим тому, что делает rebase.

  • git svn rebase получит ревизии из SVN-родителя текущего HEAD и пересоздаст текущую (нефиксированную в SVN) работу в соответствии с ними.

  • git rebase упоминает:
    . Обратите внимание, что слияние rebase работает путём воспроизведения каждого коммита из рабочей ветки поверх ветки .
    Из-за этого, когда происходит конфликт слияния:

    • сторона, о которой сообщается как о нашей, - это пока что rebased-ветвь, начиная с ,
    • а их - рабочая ветвь.
      Другими словами, стороны поменялись местами.

git rebase воспроизводит каждый коммит из рабочей ветви поверх ветви.

Если согласовать оба определения:

  • коммиты, приходящие из SVN, являются теми, поверх которых воспроизводятся локальные коммиты Git. Они являются частью "so-far rebased series" и упоминаются как "наша" (в вашем случае test.txt файл с bar содержимым)
  • рабочая ветвь (содержащая коммиты Git, неизвестные SVN, в вашем случае test. txt файл с baz содержимым) является "своей", и каждый из этих локальных Git-коммитов воспроизводится.

Другими словами, SVN или нет:

  • ветка "" (поверх которой воспроизводится всё, что угодно, и которая является частью пока что ребазированных коммитов") является "нашей".
  • то, что воспроизводится (рабочая ветка) - "их".

Хорошая мнемоническая подсказка от CommaToast:

на что бы ни указывал HEAD, это "наше"

(и первое, что делает git rebase upstream, это проверяет upstream ветку, поверх которой вы хотите сделать rebase: HEAD относится к upstream -- ours now.)


Путаница, вероятно, происходит из-за роли рабочей ветки в классическом git merge.
При слиянии:

  • рабочая ветка - это та, которая содержит то, что "пока слито", и считается "нашей",
  • в то время как другие коммиты представляют то, что - не воспроизводится, а - сливается поверх рабочей ветки, и считается "их".

Как упоминается на странице руководства git rebase, слияние во время 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

Но при ребазе, мы меняем сторону, потому что первое, что делает ребаз, это проверяет восходящую ветку! (чтобы воспроизвести текущие коммиты поверх неё)

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

A git rebase upstream сначала изменит HEAD ветки B на ветку upstream 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

, а затем 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

Единственный дополнительный шаг при git svn rebase - это то, что сначала выполняется svn "fetch" на удалённой ветке 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
225
ответ дан 24 November 2019 в 07:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: