2013-05-27 6 views
32

Позвольте мне описать мою ситуацию:Git: Натяжение нормированной ветви

г-н и г-н Blond Оранжевый работают на ветви А, разветвляется мастер филиала на совершение M1. Филиал А имеет 2 фиксации: A1 и A2.

M1 
    \ 
    \ 
    A1 - A2 

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

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

Mr Blond тянет с пульта дистанционного управления, и через некоторое время решает перебазироваться на мастер-отрасли:

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

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

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

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

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

Что мистер Оранжевый нужно сделать для того, чтобы быть синхронизированы с филиалом в удаленном хранилище?

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

ответ

21

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

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

Одно важное различие, я буду иметь мой местный лейбл A указывая преподобному A2, и удаленный ярлык remotes/origin/A указывая на A2' (Mr Blond было это наоборот, местные этикетки, указывающие на A A2 'и remotes/origin/A, указывающие на A2).

Если я работал на моей копии филиала под названием «A» Я буду вместо этого:

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

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

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

, а затем падение оборотов А1 и А2 полностью, так как модифицированные из них находится в new_A как А1' и 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, то есть, идентифицируя А1, А2, А3 и т.д.

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

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

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

(Если мои потребности A3 модификации стать A3' , как интерактивный перебазироваться и метод „мерзавец утра“ потребует работы со мной, конечно.)

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

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

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

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

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

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

$ git branch -D old_A 

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

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

30

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

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

+1

Примечание: нет пробелов между '-' и 'hard' - мне потребовалось некоторое время, так как ответ был завернут на моем экране именно между этими двумя :) – qbolec

Смежные вопросы