Подтвердить что ты не робот

Git: вытащить ветвь с пересылкой

Позвольте мне описать мою ситуацию:

Г-н Блонд и г-н Орандж работают над ветвью А, которая выходит из ведущей ветки на фиксацию M1. Ветвь А имеет 2 фиксации: A1 и A2.

M1  
   \
    \
     A1 - A2

Между тем, г-н Орандж совершил и сделал еще 2 фиксации на главной ветки, M2 и M3.

M1  - M2 - M3
   \
    \
     A1 - A2

Г-н Блонд вытаскивает из пульта и через некоторое время решает переложить на главную ветку:

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1` - A2`

Теперь A1` и A2` - это перекомпонуемые коммиты, которые существуют локально у мистера Блонда, и A1 и A2 существуют удаленно. Блонд подталкивает свои коммиты, используя -f, чтобы заставить свои изменения и "переписать" историю. Теперь удаленный репозиторий выглядит следующим образом:

M1  - M2 - M3
             \
              \
               A1` - A2`

Но г-н Орандж также работал в филиале A. Его локальный репозиторий по-прежнему выглядит следующим образом:

M1  - M2 - M3
   \
    \
     A1 - A2

Что нужно сделать г-ну Орангу для синхронизации с веткой A в удаленном репозитории?

Нормальное нажатие не будет работать. Будет ли pull -f принудительно изменять изменения с удаленного компьютера? Я знаю, что удаление локальной версии A и ее повторное подключение из удаленного репозитория будет делать трюк, но это, похоже, не является хорошим способом достижения этого.

4b9b3361

Ответ 1

Моя рекомендация (или, "что бы я сделала, если бы была мистер Ориндж" ), начинаем с git fetch. Теперь у меня будет это в моем репо, что и было у мистера Блонда после его перезагрузки и перед тем, как он побежал "git push -f".

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1' - A2'

Единственное важное отличие: у меня будет локальная метка A, указывающая на rev A2, и удаленная метка remotes/origin/A, указывающая на A2 '(г-н Блонд имел это наоборот, локальная метка A указывая на A2 'и remotes/origin/A, указывающие на A2).

Если я работаю над своей копией ветки с именем "А", у меня будет это:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2'

(с моей локальной меткой, указывающей на A3, а не на A2 или A4 или A5 и т.д., в зависимости от того, сколько изменений я применил.) Теперь мне нужно только перезагрузить мой A3 (и, если необходимо, A4) на A2 '. Один очевидный прямой путь:

$ git branch -a
  master
* A
  remotes/origin/master
  remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A

а затем полностью отбрасывать обороты A1 и A2, так как модифицированные находятся в new_A как A1 'и A2'. Или:

$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k

(метод git am -3 -k описан на странице руководства git-format-patch).

Они требуют выяснить, что у меня есть, что мистер Блонд не сделал, прежде чем он сделал свой rebase, то есть идентифицировал A1, A2, A3 и т.д.

Если второй подход успешный, я получаю:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' - A3'

где мое имя ветки new_A указывает на A3 '(моя существующая ветка A все еще указывает на старый A3). Если я использую первый подход, и он преуспеет, я получаю то же самое, просто мое существующее имя ветки A теперь будет указывать на A3 '(и у меня нет имени старой ветки с A1-A2-A3, даже несмотря на то, что он все еще находится в моем репо, поэтому для его поиска требуется просмотр журналов или подобных).

(Если мой A3 нуждается в модификации, чтобы стать A3 ', как интерактивная rebase, так и метод git am), конечно, потребуют меня.)

Конечно, также возможно просто git merge (как в ответе Гэри Фикслера), но это создаст слияние ( "М" без номера ниже) и сохранит обороты A1 и A2, что дает:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' -- M
                 \_______________/

Если вы хотите сохранить оригинальные A1 и A2, это хорошо; если вы хотите избавиться от них, это плохо. Поэтому "что делать" зависит от того, "что вы хотите, чтобы результат был".

Изменить для добавления: мне нравится метод format-patch лучше, поскольку он оставляет мое имя ветки A, пока я уверен, что все хорошо. Предполагая, что все это работает и хорошо, вот последние несколько шагов:

$ git branch -m A old_A
$ git branch -m new_A A

а затем, если old_A можно полностью отбросить:

$ git branch -D old_A

или, что то же самое, начните с удаления ветки, а затем переименуйте new_A в A.

(Редактировать: см. также документацию git rebase --onto, для цели переадресации A3 и т.д.) на ветку new_A.)

Ответ 2

Если г-н Оранж не против потерять свои изменения, он может получить от сервера, затем git checkout A2, чтобы попасть в свою локальную ветвь A2, тогда (предполагая, что пульт называется "origin" ) git reset --hard origin/A2 до reset его A2, где находится удаленный A2.

Если он связан с потерей изменений, он может объединить изменения сервера для их разрешения (из своей ветки A2 и, предположительно, снова, что пульт называется "origin" ) с помощью git merge origin/A2. Это приведет к новому фиксации, который поверх его и удаленных ветвей A2 с изменениями обоих объединений. Затем это можно отбросить обратно на пульте дистанционного управления.