Git push отклонен после переадресации функции

Хорошо, я думал, что это был простой сценарий мерзавца, что я пропускаю?

У меня есть master ветвь и ветвь feature. Я делаю некоторую работу над master, некоторые - над feature, а затем еще немного над master. Я получаю что-то вроде этого (лексикографический порядок подразумевает порядок коммитов):

A--B--C------F--G  (master)
       \    
        D--E  (feature)

У меня нет проблем ни с git push origin master чтобы поддерживать удаленный master обновленным, ни с git push origin feature (когда она feature), чтобы поддерживать удаленное резервное копирование для работы моей feature. До сих пор у нас все хорошо.

Но теперь я хочу, чтобы перебазировать feature на вершине F--G совершающий на мастере, так что я git checkout feature и git rebase master. Все еще хорош. Теперь у нас есть:

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

Проблема: в момент, когда я хочу сделать резервную копию новой перебазированной feature разветвленной с git push origin feature, push отклоняется, так как дерево изменилось из-за перебазировки. Эту проблему можно решить только с git push --force origin feature.

Я ненавижу использовать --force не будучи уверенным, что мне это нужно. Так мне это нужно? Обязательно ли перебазировка подразумевает, что следующий push должен быть --force?

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

Ответ 1

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

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

Когда вы выполняете git rebase, коммиты D и E применяются к новой базе, и создаются новые коммиты. Это означает, что после rebase у вас есть что-то вроде этого:

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

В этой ситуации удаленная ветка не может быть быстро перенаправлена ​​на локальную. Хотя, теоретически, локальная ветвь может быть объединена в удаленный (очевидно, в этом случае она вам не нужна), но поскольку git push выполняет только перемотку вперед, он выдает и ошибки.

А какая опция --force - это просто игнорирование состояния удаленной ветки и установка ее на фиксацию, которую вы в нее вставляете. Итак, git push --force origin feature-branch просто переопределяет origin/feature-branch с помощью локального feature-branch.

На мой взгляд, переполнение ветвей функций на master и принудительное отталкивание их обратно в удаленный репозиторий в порядке, пока вы единственный, кто работает на этой ветке.

Ответ 2

Вместо использования -f или -force разработчики должны использовать

--force-with-lease

Почему? Потому что он проверяет удаленную ветку для изменений, что является абсолютно хорошей идеей. Представьте себе, что Джеймс и Лиза работают над одной и той же ветвью функций, и Лиза нажала на фиксацию. Джеймс теперь сворачивает свою местную ветку и отклоняется при попытке толчка. Конечно, Джеймс считает, что это связано с переустановкой и использованием --force и будет переписывать все изменения Лизы. Если бы Джеймс использовал -force-with-lease, он бы получил предупреждение о совершении кем-то другим. Я не понимаю, почему кто-то использовал бы -force вместо -force-with-lease при нажатии после rebase.

Ответ 3

Я бы использовал вместо "checkout -b", и это легче понять.

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

когда вы удаляете, вы не можете нажать в выходящую ветку, содержащую разные идентификаторы SHA. В этом случае я удаляю только удаленную ветвь.

Ответ 4

Одно из решений заключается в том, чтобы сделать то, что msysGit сбрасывание слияния script делает - после перезагрузки слияние в старой главе feature с помощью -s ours. Вы получите граф фиксации:

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

... и ваш push feature будет быстрой перемоткой вперед.

Другими словами, вы можете сделать:

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(Не проверено, но я думаю, что правильно...)

Ответ 5

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

Как таковой, я предложил бы использовать следующую последовательность:

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

Да, новая ветка, это должно решить это без использования --force, что, по моему мнению, является главным недостатком git.

Ответ 6

Другие ответили на ваш вопрос. Если вы пересобираете ветку, вам нужно будет принудительно нажать эту ветку.

Rebase и общий репозиторий обычно не ладят. Это история переписывания. Если другие используют эту ветвь или разветвляются из этой ветки, тогда перестановка будет довольно неприятной.

В целом, rebase хорошо работает для управления локальными веткими. Управление удаленным филиалом работает лучше всего с явным слиянием (-no-ff).

Мы также избегаем объединения мастера в ветвь функции. Вместо этого мы переустанавливаем мастер, но с новым именем ветки (например, добавляем суффикс версии). Это позволяет избежать проблемы с перезагрузкой в ​​общем хранилище.

Ответ 7

Мой способ избежать принудительного нажатия - создать новую ветку и продолжить работу над этой новой веткой и после некоторой стабильности удалить прежнюю ветвь, которая была переустановлена:

  • Восстановление локально проверенной ветки
  • Ветвление с переустановленной ветки на новую ветку
  • Нажатие этой ветки как новая ветвь на удаленный. и удаление старой ветки на пульте дистанционного управления.

Ответ 8

Что случилось с git merge master в ветке feature? Это сохранит работу, которую вы имели, оставив ее отдельно от основной ветки.

A--B--C------F--G
       \         \
        D--E------H

Изменить: Ах, извините, не прочитал ваш запрос проблемы. При выполнении rebase вам понадобится сила. Все команды, которые изменяют историю, нуждаются в аргументе --force. Это отказоустойчиво, чтобы вы не потеряли работу (старые D и E будут потеряны).

Итак, вы выполнили git rebase, который сделал дерево похожим (хотя частично скрытый как D и E больше не находится в названной ветке):

A--B--C------F--G
       \         \
        D--E      D'--E'

Итак, при попытке нажать новую ветвь featureD' и E' в ней) вы потеряете D и E.

Ответ 9

Для меня работает следующее:

git push -f origin branch_name

и он не удаляет мой код.

Но, если вы хотите этого избежать, вы можете сделать следующее:

git checkout master
git pull --rebase
git checkout -b new_branch_name

то вы можете вишневым выбрать все свои фиксации в новую ветку. git cherry-pick COMMIT ID а затем нажмите новую ветку.

Ответ 10

Для меня работает следующие простые шаги:

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

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

git push origin --delete myFeature

Ответ 11

Поскольку ОП понимает проблему, просто ищет более приятное решение...

Как насчет практики?

  • Имейте в реальной ветке разработки функций (где вы никогда не переустанавливаете и не нажимаете, поэтому ваши разработчики разработчиков не ненавидят вас). Здесь регулярно извлекайте эти изменения из основного с помощью слияния. История Мессье, да, но жизнь проста, и никто не ввязывается в его работу.

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

Возможно, уже существует имя шаблона для этого метода.