Как я могу использовать git rebase без принудительного нажатия?

94

Пытаясь достичь git nirvana, я трачу день на изучение того, как использовать rebase для ситуаций, в которых я в настоящее время сливаюсь.

При прохождении того, что я считаю потоком git 101 (который я объясняю ниже), мне приходится это делать, push --forceкогда я отправляю свои изменения обратно в источник.

Я не единственный - я знаю, что это закрытая территория (см. 1 , 2 , 3 , 4 , 5 ), и понимаю технические причины, по которым необходима сила. Моя проблема в том, что есть много (много) записей в блогах, восхваляющих rebase и то, как это изменило их жизнь (см. 1 , 2 , 3 , 4, чтобы перечислить несколько), но ни одна из них не упоминает, что push --forceявляется частью их поток. Однако почти каждый ответ на существующие вопросы о stackoverflow говорит что-то вроде «да, если вы собираетесь перебазировать, вы должны использовать push --force».

Учитывая количество и религиозность сторонников перебазирования, я должен верить, что использование «push --force» не является неотъемлемой частью потока перебазирования, и что если кому-то часто приходится принудительно нажимать их, они делают что-то не так .

push --forceэто плохо .

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

Простой пример

Две ветви:

  • v1.0 - ветка релиза, содержит только патчи
  • master - все для следующего крупного релиза.

У меня есть несколько коммитов патчей и несколько коммитов для следующего выпуска.

предварительное слияние

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

git checkout master
git merge v1.0

Но теперь я пытаюсь

git checkout master
git rebase v1.0

Итак, теперь я здесь:

введите описание изображения здесь

Время:

git push

Никаких кубиков.

Рой Трулав
источник

Ответы:

43

Ребазинг - отличный инструмент, но он работает лучше всего, когда вы используете его для создания слияний с перемоткой вперед для веток темы в мастер. Например, вы можете переустановить ветку add-new-widget на master:

git checkout add-new-widget
git rebase -i master

перед выполнением быстрого слияния ветки с мастером. Например:

git checkout master
git merge --ff-only add-new-widget

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

Это, конечно, не единственный вариант использования rebase или единственный рабочий процесс, но это одно из наиболее разумных применений, которые я видел. YMMV.

Тодд А. Джейкобс
источник
4
Спасибо CG, я думаю, что ключевой момент - «использовать его для создания слияний с перемоткой вперед». Это не относится к моему случаю, приведенному выше, где у меня есть две живые ветки - ветка разработки и ветка выпуска, но, похоже, очень хорошо подходит для временных веток тем, которые необходимы только в течение ограниченного периода времени, а затем могут быть удаляются после объединения. Еще раз спасибо.
Рой Трулав
1
Я понимаю это, но исходный вопрос остается. Я думаю, что фактический ответ - это тот, который дал @Fabien Quatravaux
IsmailS
5
Ну, вам все равно придется принудительно протолкнуть ветку 1.0, не так ли? По крайней мере, у меня всегда так складывается. Метод Фабьенса предотвратил бы это.
Joerx
23

@CodeGnome прав. Вы не должны переустанавливать master на ветке v1.0, а на ветке v1.0 на master, это будет иметь большое значение.

git checkout -b integrate_patches v1.0
git rebase master
git checkout master
git merge integrate_patches

Создайте новую ветку, которая указывает на v1.0, переместите эту новую ветку поверх master, а затем интегрируйте новую версию исправлений V1.0 в основную ветку. Вы получите что-то вроде:

o [master] [integrate_patches] Another patch on v1.0
o A patch on v1.0
o Another change for the next major release
o Working on the next major release
|  o [v1.0] Another path on v1.0
|  o A patch on v1.0
| /
o Time for the release

Этот способ использования rebase рекомендован официальной документацией git .

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

Фабьен Кватраво
источник
Я думаю, что это лучший ответ на конкретную проблему в ОП. Вы создаете временную ветвь слияния и переустанавливаете ее, затем сливаете в мастер и отправляете в источник. Временную ветвь не нужно отправлять в исходную точку. Единственный дополнительный совет, который я хотел бы дать, - это иметь ветку develop или qa, где можно будет квалифицировать объединенный / перебазированный код. После квалификации этот код будет затем объединен в мастер. Это позволяет легко исправлять ошибки, если процесс квалификации занимает слишком много времени. По сути, это процесс «git flow».
Джавид Джамае
Спасибо, Фабьен, отличный ответ. Для тех из нас, кто просто хочет интегрировать изменения masterи не возражает против объединения самой ветки функций, это можно сделать с помощью:git checkout my-branch; git rebase master; git checkout master; git merge my-branch
Сиавас
17

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

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

Это сердце рабочего процесса, в котором вы используете перебазирование, но не слишком сильно подталкиваете: не публикуйте вещи, пока они не будут готовы, не перебазируйте после того, как нажмете.

Дэниел Питтман
источник
Спасибо, Дэн. Не могли бы вы сообщить мне, как этого достичь? Разве это не тот сценарий, в котором применяется перебазирование?
Рой Трулав
2
Если вы изолируете всю свою работу по тематическим веткам, тогда это создаст хороший сценарий для перебазирования. Вы rebaseнедавно внесли изменения в свою ветку темы, но когда вы завершили изменения этой ветки, вы mergeвернетесь обратно в основную ветку разработки.
redhotvengeance
1
Проблема в том, что вы опубликовали ветку, поэтому вам нужно принудительно отправить ее в репозиторий. Вам нужно отказаться от одного из двух: публикации, как вы это делаете, или перебазирования. Сожалею.
Daniel Pittman
Похоже, для этого сценария перебазирование не работает. v1.0 - это не тематическая ветка, это ветвь выпуска, поэтому она никогда не умрет и должна быть опубликована.
Рой Трулав
5

Я думаю, что есть хороший вариант использования этого шаблона «перебазирование, затем принудительное нажатие», которое не является результатом ошибочного нажатия: работа над веткой функции самостоятельно из нескольких мест (компьютеров). Я делаю это часто, поскольку иногда работаю в офисе на своем компьютере, а иногда из дома / у клиента на своем ноутбуке. Мне нужно время от времени перебазировать, чтобы не отставать от основной ветки и / или сделать слияние более чистым, но мне также нужно принудительно нажимать, когда я оставляю одну машину, чтобы работать над другой (где я просто тяну). Работает как шарм, раз уж я один работаю на ветке.

8 сорок
источник
2
У меня такой же рабочий процесс (работа с нескольких компьютеров / мест). Итак, предположим, вы работаете над тематической веткой под названием «mytopic». Пока вы всегда переустанавливаете локальную одноразовую ветку (которая является просто ветвью mytopic) на «master», а затем объединяете ее обратно в mytopic, вам никогда не придется принудительно нажимать. У OP немного другой сценарий, поэтому в таком случае может потребоваться принудительный толчок. Однако я думаю, что OP перебазирует неправильный путь - если бы он сделал это, как я описал, тогда не потребовалось бы принудительного толчка.
bwv549
3

Вот что я использую (при условии, что имя вашей ветки - foobar ):

git checkout master              # switch to master
git rebase   foobar              # rebase with branch
git merge -s ours origin/master  # do a basic merge -- but this should be empty
git push origin master           # aaand this should work
благоухающий
источник
2
Мастер ребазинга выглядит странно.
Эмиль Викстрём
2
gitне
благоухающий
1
git merge -s ours origin/<branch>было то, что исправило это для нас
Макс
0

tl; dr объединить с общими ветками, переустановить с отдельными ветвями. --force-with-leaseявляется более безопасной альтернативой силе и должен помочь вам достичь упомянутой мерзкой нирваны без разрушительного характера силы.

Общее практическое правило, которое я видел в рабочих процессах различных команд, - это использовать mergeдля общих ветвей (то есть, мастер или разработка) и использовать rebaseпри работе над собственной веткой функций. Вот типичный жизненный цикл функциональной ветки

git checkout master
git checkout -b new-feature
git commit -am "commit new work"
git push -u origin new-feature
# have code reviewed, run CI, etc.,
# meanwhile master has new commits
git checkout master
git pull
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

Простая английская версия того, что мы здесь сделали:

  1. Создал новую ветку от мастера
  2. Завершена работа в ветке и перенесена на удаленный
  3. переустановил с мастера
  4. Отправьте работу на удаленный компьютер с помощью force-with-lease
  5. объединить в мастер с очень чистым журналом git, уменьшая беспорядок от нескольких слияний из нашей общей ветки, чтобы наша ветка «догнала» последний мастер (общая ветка)

4-й шаг ДЕЙСТВИТЕЛЬНО важен и является одной из основных причин, по которой я начал отстаивать использование rebase. force-with-leaseпроверяет пульт, чтобы увидеть, были ли добавлены новые коммиты. Если git pushдоказано, что ваша разрушительная сила - это не толкнуть!

Я надеюсь, что это дает кому-то больше уверенности в использовании rebase.

lucasnad27
источник