Git rebase, отслеживая "local" и 'remote'

При выполнении git rebase мне часто сложно решить, что происходит с "local" и 'remote' при разрешении конфликтов. Иногда у меня создается впечатление, что они меняются местами от одного фиксажа к другому.

Это, вероятно (определенно), потому что я до сих пор не понял.

При перезагрузке, кто является "локальным" и кто 'remote'?

(Я использую P4Merge для разрешения конфликтов)

Ответ 1

TL; DR;

Подводя итоги (Benubird комментарии), когда:

git checkout A
git rebase   B    # rebase A on top of B
  • local - B (rebase на),
  • remote A

и

git checkout A
git merge    B    # merge B into A
  • local - A (слияние в),
  • remote B

Переключатели переадресации ours (текущая ветка до начала перезагрузки) и theirs (ветка, поверх которой вы хотите переустановить).


kutschkem указывает, что в контексте слияния GUI:

  • локальные ссылки частично переустановленные коммиты: "ours" (ветвь вверх по течению)
  • удаленный относится к входящим изменениям: "theirs" - текущая ветвь перед восстановлением.

См. иллюстрации в последней части этого ответа.


Инверсия при rebase

Путаница может быть связана с инверсией ours и theirs во время переустановки.
(соответствующие выдержки)

git rebase справочная страница:

Обратите внимание, что слияние ребаз работает, переигрывая каждую фиксацию из рабочей ветки поверх ветки <upstream>.

Из-за этого, когда происходит конфликт слиянием:

  • Сторона, указанная как "ours" , представляет собой так называемый переустановленный ряд, начиная с <upstream>,
  • и 'theirs' - рабочая ветвь. Другими словами, стороны меняются местами.

Показанная инверсия

При слиянии

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, мы переключаем сторону, потому что первое, что нужно сделать, это проверка ветки upstream! (чтобы воспроизвести текущий ток на вершине)

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

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

Примечание. "восходящее" понятие является ссылочным набором данных (все репо или, как здесь, ветвь, которая может быть локальной ветвью) из какие данные считываются или какие новые данные добавляются/создаются.


'local' и 'remote' vs. 'mine' и 'theirs'

Pandawood добавляет в комментарии:

Для меня все еще остается вопрос, который является "локальным", а кто "remote" (поскольку термины "наш" и "их" не используются при перезагрузке в git, ссылаясь на них, как представляется, ответ более запутанным).

GUI git mergetool

kutschkem добавляет, и правильно:

При разрешении конфликтов git скажет что-то вроде:

local: modified file and remote: modified file. 

Я уверен, что в этом вопросе речь идет о определении локальных и удаленных. В этот момент мне кажется, по моему опыту, что:

  • локальные ссылки частично переустановленные коммиты: "ours" (ветвь вверх по течению)
  • удаленный относится к входящим изменениям: "theirs" - текущая ветвь перед восстановлением.

git mergetool действительно упоминает "локальный" и 'remote':

Merging:
f.txt

Normal merge conflict for 'f.txt':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (kdiff3):

Например, KDiff3 будет отображать разрешение слияния так же:

kdiff3

И meld будет показать его тоже:

Meld diff

То же самое для VimDiff, который отображает:

Вызовите Vimdiff как mergetool с git mergetool -t gvimdiff. Последние версии git вызывают Vimdiff со следующим макетом окна:

+--------------------------------+
| LOCAL  |     BASE     | REMOTE |
+--------------------------------+
|             MERGED             |
+--------------------------------+
  • local:
    Временный файл, содержащий содержимое файла в текущей ветке.
  • BASE:
    Временный файл, содержащий общую базу для слияния.
  • remote:
    Временный файл, содержащий содержимое файла для объединения.
  • MERGED:
    Файл, содержащий маркеры конфликтов.

Git выполнил максимально возможное автоматическое разрешение конфликтов, и состояние этого файла представляет собой комбинацию как local, так и remote с маркерами конфликтов, окружающими все, что git не может решить. mergetool должен записать результат разрешения в этот файл.

Ответ 2

Нижняя строка

git rebase

  • LOCAL = база, которую вы перегружаете на
  • REMOTE = совершает движение вверх.

git merge

  • LOCAL = исходная ветка, которую вы объединяете в
  • REMOTE = другая ветка, чьи записи вы объединяете в

Другими словами, LOCAL всегда является оригиналом, а REMOTE всегда является парнем, чьи коммиты не были там раньше, потому что они сливаются или переустанавливаются наверх

Докажите это!

Конечно. Не верьте мне на слово! Здесь вы можете легко провести эксперимент, чтобы убедиться сами.

Во-первых, убедитесь, что git mergetool настроен правильно. (Если вы этого не сделали, вы, вероятно, все равно не читали бы этот вопрос.) Затем найдите каталог, в котором вы сможете работать.

Настройте свой репозиторий:

md LocalRemoteTest
cd LocalRemoteTest

Создайте начальную фиксацию (с пустым файлом):

git init
notepad file.txt  (use the text editor of your choice)
  (save the file as an empty file)
git add -A
git commit -m "Initial commit."

Создайте фиксацию на ветке, которая не является ведущей:

git checkout -b notmaster
notepad file.txt
  (add the text: notmaster)
  (save and exit)
git commit -a -m "Add notmaster text."

Создайте фиксацию на главной ветке:

git checkout master
notepad file.txt
  (add the text: master)
  (save and exit)
git commit -a -m "Add master text."

gitk --all

В этот момент ваш репозиторий должен выглядеть так:

Repository with a base commit and two one-commit branches

Теперь для теста rebase:

git checkout notmaster
git rebase master
  (you'll get a conflict message)
git mergetool
  LOCAL: master
  REMOTE: notmaster

Теперь тест слияния. Закройте свой mergetool без сохранения каких-либо изменений, а затем отмените rebase:

git rebase --abort

Тогда:

git checkout master
git merge notmaster
git mergetool
  LOCAL: master
  REMOTE: notmaster
git reset --hard  (cancels the merge)

Ваши результаты должны совпадать с результатами, показанными вверху.

Ответ 3

Я точно не понял вашу проблему, но я думаю, что следующая диаграмма устраняет вашу проблему. (Rebase: Удаленный репозиторий --- > Рабочая область)

http://assets.osteele.com/images/2008/git-transport.png

Источник: Мой Git Рабочий процесс