Git rebase и git push: non-fast forward, зачем использовать?

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

К сожалению, каждый раз, когда я делаю "git rebase", а затем пытаюсь нажать, это приводит к сообщению "non-fast forward" и аборту нажатия. Единственный способ нажать здесь - использовать -force. Означает ли это, что я должен использовать 'git merge' вместо перезагрузки, если моя ветка стала общедоступной, а другие работают над ней?

Ответ 1

Несколько заметок о том, как работает git (не технический):

Когда вы переустанавливаете, git берет соответствующие коммиты и "подтверждает" их поверх чистой истории. Это делается для предотвращения отображения истории:

Description: tree -> mywork -> merge -> mywork -> merge -> mywork -> merge
Commit SHA1: aaaa -> bbbb   -> cccc  -> dddd   -> eeee  -> ffff   -> gggg

После переустановки он может выглядеть так (или аналогичный):

Description: tree -> rebase
Commit SHA1: aaaa -> hhhh

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

Теперь вы знаете, что та же самая информация находится в коммитах, но git несет ответственность, не просто перезаписывая эти коммиты (bbbb-gggg в примере выше).


Модель общего репо

Если вы используете общий репозиторий, тогда подобные вещи могут стать весьма запутанными. Позвольте мне объяснить, почему. Скажем, еще один разработчик вытащил ветку, и они зафиксировали aaaa → gggg в своей ветке. Затем они совершают фиксацию iiii

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

Description: tree -> rebase
Commit SHA1: aaaa -> hhhh

Когда другой разработчик пытается нажать, он получает сообщение "non-fast forward". Когда он делает слияние, то обе истории RELINKED вместе, и вы получаете mess

Что-то вроде этого (грязное):

Description: tree -> rebase -> mywork -> merge -> mywork -> merge -> mywork -> merge -> devwork -> merge 
Commit SHA1: aaaa -> hhhh   -> bbbb   -> cccc  -> dddd   -> eeee  -> ffff   -> gggg -> iiii    -> jjjj

Иными словами, если другие тянут И толкают, вам лучше придерживаться слияния git или AVOID PUSHING, пока после rebase (и не переустановите вашу работу).


Публично видимая модель репозитория

Возможно, вы используете другую (более gittish) модель, где вы просто хотите, чтобы люди могли вытащить ваш репо. В этом случае git push -force не так уж плохо, потому что тогда они могут справиться с этим. Они могут переустанавливать свои изменения, чтобы быть на вершине ваших изменений, прежде чем давать свои патчи вам. Это не позволяет вашему репо полностью запутаться.

Однако для вас может быть лучший способ. git push --mirror

От http://www.kernel.org/pub/software/scm/git/docs/git-push.html

Вместо того, чтобы называть каждый ref для push, указывает, что все ссылки в $GIT_DIR/refs/(который включает, но не ограничиваясь refs/heads/, refs/remotes/, и refs/tags/) be зеркалируется в удаленном репозитории. Новые локальные ссылки будут отодвигается к удаленному концу, локально обновленные ссылки будут обновлены удаленный конец и удаленные ссылки будут удаляться с удаленного конца. Эта по умолчанию, если конфигурация опция дистанционный..mirror установлен.


Одна из замечательных особенностей git заключается в том, что она очень гибкая и позволяет использовать много разных рабочих процессов. Но реальная сила заключается в том, что это распределенная модель, поэтому я считаю, что большинство ROI можно использовать, используя ее таким образом.

Ответ 2

Нет, rebase совершенно легальна с публичными репозиториями и даже может быть желательным для того, чтобы держать историю в курсе. Просто имейте в виду, что вы не должны использовать rebase для перезаписи истории удаленных опубликованных коммитов. То есть, rebase может применяться только к вашим собственным, локальным, обязывает, что вы никогда не публиковали. Вы используете rebase, чтобы поместить свои коммиты поверх них при извлечении, а затем, возможно, отрегулируйте их там. Другая причина, по которой вы можете получить такое сообщение, - это то, что ветка, которую вы нажимаете, была обновлена, и вам нужно синхронизировать - выборку и переупорядочение ваших коммитов поверх того, что вы выбрали.