не может нажать на ветку после перебазирования

131

Мы используем git, и у нас есть основная ветка и ветки для разработчиков. Мне нужно добавить новую функцию, а затем переустановить коммиты на master, а затем отправить master на сервер CI.

Проблема в том, что если у меня возникают конфликты во время перебазирования, я не могу нажать на свою удаленную ветку разработчика (на Github) после завершения перебазирования, пока я не извлечу свою удаленную ветку. Это вызывает повторяющиеся коммиты. Когда нет конфликтов, работает как положено.

вопрос: после перебазирования и разрешения конфликтов, как мне синхронизировать локальную и удаленную ветки разработчика без создания дублирующих коммитов

Настроить:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

РЕДАКТИРОВАТЬ

Похоже, это нарушит рабочий процесс:

developer1, работающий над myNewFeature, разработчик2, работающий над hisNewFeature, оба используют master в качестве основной ветви

developer2 объединяет myNewFeature со своимNewFeature

developer1 выполняет перезагрузку, разрешает конфликты, затем принудительно отправляет в удаленную ветку для myNewFeature

пару дней спустя developer2 снова сливает myNewFeature со своимNewFeature

Заставит ли это других разработчиков ненавидеть developer1?

Matt
источник
не решение, а просто мысль. кто we? вы в команде больше, чем вы? theyскажите (люди, которые знают больше, чем я), что если вы поделитесь своим кодом, вы не должны его использовать rebase. Почему ты просто не делаешь git pullи git merge?
AdamT
извините, Мы = команда разработчиков
Мэтт
1
так что да, вероятно, не следует делать перестановку, когда вы делитесь кодом. это может привести к тому, что вам придется делать что-то вроде того, что указано ниже ( forceтолчок)
AdamT
о, извините, когда они говорят rewriting history, что этоrebase
AdamT
По его словам, это его собственная ветвь разработки, так что это не должно быть проблемой, если только не ожидается, что кто-то объединит это.
Learath2

Ответы:

93

Во-первых, вы и те, с кем работаете, должны согласовать, предназначена ли ветвь topic / devel для совместной разработки или только для вашей собственной. Другие разработчики знают, что нельзя объединяться в мои ветки разработки, потому что они будут обновлены в любое время. Обычно рабочий процесс выглядит следующим образом:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

Затем, чтобы быть в курсе последних событий, я сделаю следующее:

 git fetch origin
 git checkout master
 git merge --ff origin/master

Я делаю это по двум причинам. Во-первых, потому что он позволяет мне видеть, есть ли удаленные изменения, без необходимости переключаться с моей ветки разработки. Во-вторых, это механизм безопасности, чтобы я не перезаписывал какие-либо несохраненные / зафиксированные изменения. Кроме того, если я не могу выполнить быстрое слияние с основной веткой, это означает, что либо кто-то перебазировал удаленный мастер (за что их нужно жестко выпороть), либо я случайно назначил мастеру и должен очистить свой конец.

Затем, когда в пульте есть изменения, и я быстро перехожу к последнему, я перебазирую:

git checkout devel0
git rebase master
git push -f origin devel0

Затем другие разработчики знают, что им нужно будет перенастроить свои ветки разработки с моей последней версии:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

В результате история становится намного чище:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

Не объединяйте коммиты туда-сюда по вашей прихоти. Он не только создает дублирующиеся коммиты и делает невозможным отслеживание истории, но и практически невозможно найти регрессии от конкретного изменения (именно поэтому вы в первую очередь используете контроль версий, верно?). Проблема, с которой вы столкнулись, является результатом именно этого.

Также похоже, что другие разработчики могут делать коммиты в ваши ветки разработки. Вы можете это подтвердить?

Единственный момент для слияния - это когда ваша тематическая ветка готова к принятию master.

На стороне примечания. Если несколько разработчиков используют один и тот же репозиторий, вам следует подумать о наличии именованных ветвей, чтобы различать ветки разработки разработчиков. Например:

git branch 'my-name/devel-branch'

Таким образом, все тематические ветки разработчиков находятся в собственном вложенном наборе.

Тревор Норрис
источник
1
«Также похоже, что другие разработчики могут коммитить ваши ветки разработки. Вы можете подтвердить это?» ДА, они ...
Мэтт
Вы также обратили мое внимание на другую проблему. Работа между офисом и домом. Я делаю слияние в обоих местах и ​​в конце дня нажимаю, чтобы продолжить с того места, где остановился. Затем, когда пришло время перебазировать, все эти коммиты создают путаницу. Мне нужно рассматривать мои ветки как одну ветку и перебазировать
Мэтт
@Matt Да, эти две проблемы действительно испортят ваш рабочий процесс. Во-первых, я бы сообщил другим разработчикам, что только владелец может зафиксировать именованный разветвленный объект (например, «matt / devel»). ИМХО, в любом случае два разработчика не должны использовать одну и ту же ветку. Просто создает путаницу. Что касается более поздних версий, перебазирование и принудительное нажатие должны поддерживать актуальность двух местоположений.
Тревор Норрис,
Отличный ответ. У меня побочный вопрос, почему вы используете --forceфлаг, когда делаете это git push -f origin devel0?
Нобита
2
@Nobita Когда git pushневозможно перемотать вперед (т.е. история sha не совпадает), вы должны принудительно нажать, чтобы перезаписать предыдущую историю новой историей, созданной из git rebase.
Тревор Норрис
50

Вам нужно принудительно подтолкнуть, когда вы переместили коммиты дальше по строке, git ожидает, что вы добавите коммиты в верхушку ветки. git push -f origin myNewFeatureисправит вашу проблему.

Совет: Выше показано законное применение силового толчка. Никогда не переписывайте историю в общедоступном репозитории, иначе многие люди будут вас ненавидеть.

Learath2
источник
1
Я считаю, что это самый оптимальный способ поддерживать рабочий процесс.
Сайед Приом
1
Спасибо друг. Я использовал эту команду, чтобы заставить мою перебазированную локальную ветвь перейти в ту же удаленную ветку.
wei
11
использование git push --force-with-leaseнамного безопаснее, чем использованиеgit push --force
git push --force-with-lease origin HEAD- при условии, что ваша целевая ветка уже
проверена
31

Главное, что нужно помнить, это то, что pull и rebase делают за кулисами.

Вытягивание в основном выполняет две функции: выборку и объединение. Когда вы включаете --rebase, вместо слияния выполняется перебазирование.

Перебазирование в значительной степени похоже на сохранение всех ваших локальных изменений с момента разветвления, ускоренную пересылку вашей ветки до последней фиксации на целевом объекте и распаковку ваших изменений по порядку сверху.

(Это объясняет, почему вы можете получить несколько запросов на разрешение конфликтов при выполнении перебазирования по сравнению с одним разрешением конфликта, которое вы можете получить при слиянии. У вас есть возможность разрешить конфликт в КАЖДОМ коммите, который перебазируется, чтобы в противном случае сохранить ваши коммиты. )

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

Это потребует от вас время от времени нажимать измененные изменения либо с помощью силы:

git push -f origin newfeature

Или в некоторых случаях ваш администратор мог удалить возможность принудительного использования, поэтому вы должны удалить и воссоздать:

git push origin :newfeature
git push origin newfeature

В любом случае вы должны быть абсолютно уверены, что знаете, что делаете, если кто-то еще сотрудничает с вами в вашей удаленной ветке. Это может означать, что вы сначала работаете вместе с слияниями и переустанавливаете их в более управляемый формат фиксации непосредственно перед тем, как перейти к мастеру и удалению вашей рабочей ветки.

Помните, что вы почти всегда можете отказаться от git GC, воспользовавшись следующими преимуществами:

git reflog

Это ОГРОМНАЯ спасатель жизни, так как вы можете вернуться к более стабильному состоянию, если потеряетесь во всех своих перебазах / управлении конфликтами.

Мэтью Сандерс
источник
Опция удаления и воссоздания, приведенная выше, мне понравилась. Принуждение к моему репо запрещено!
Саймон Холмс
2

Вам нужно выполнить форсированный толчок, т.е. git push -f origin myNewFeature

О, и вам лучше убедиться, что люди ничего не основывают на вашей ветке разработки - обычно вы не должны публиковать ветки, в которых вы вообще переписываете историю (или, скорее, не переписываете историю после публикации). Одним из способов было бы использовать имя ветки, например, wip/myNewFeatureа затем упомянуть, что wipветки будут время от времени переустанавливаться на master.

ThiefMaster
источник
использование git push --force-with-leaseнамного безопаснее, чем использованиеgit push --force
@MrCholo Люди не начнут использовать это, пока git не добавит для него короткую опцию, как -fдля обычного принудительного толчка :)
ThiefMaster
ха, да, я использовал его в автоматическом скрипте, хотя
2

Общий ответ, который уже был дан, - использовать git push -f origin myNewFeatureпри внесении изменений с измененной базой - является хорошей отправной точкой. Я пишу этот ответ, чтобы рассмотреть поправку о том, не нарушит ли это ваш рабочий процесс.

Если мы предполагаем, что вы собираетесь использовать git pull --rebase ...(или какой-либо вариант этого), за которым следует принудительное нажатие на удаленную ветку, то в вашем примере рабочий процесс нарушается, когда developer2 сливается myNewFeatureс hisNewFeature. Имеет смысл иметь возможность перебазировать свою собственную ветку функций, пока никто не работает над этой веткой, поэтому вам нужны правила для разграничения территории ветки.

Вы можете обойти это, а) установив правило, из которого вы только когда-либо сливаетесь master, или б) создавая коллективную developветвь, на которой вы основываете свою собственную myNewFeatureветку, и устанавливаете правило, из которого вы только когда-либо сливаетесь develop. masterзатем будет зарезервирован только для этапов или выпусков (или, как бы то ни было, вы хотите это настроить), и developбудет там, где вы продвигаете каждую функцию, когда она будет готова к интеграции в другие ветки функций.

Я считаю, что это можно считать упрощенной версией рабочего процесса Gitflow.

cosmicFluke
источник