Як я можу використовувати git rebase, не вимагаючи примусового натискання?


92

Намагаючись досягти git nirvana, я витрачаю день, навчаючись, як використовувати перебазування для ситуацій, коли я в даний час зливаюся.

Пробігаючись через те, що я вважаю потоком 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 - гілка випуску, містить лише латки
  • майстер - все для наступного великого випуску.

У мене є кілька фіксованих виправлень і кілька комітів для наступного випуску.

занурити

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

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 оскільки ви не обробляєте історію на головній гілці.

Це, звичайно, не єдиний варіант використання для перебазування чи єдиний робочий процес, але це одне з найбільш розумних застосувань для нього, яке я бачив. YMMV.


4
Завдяки CG, я вважаю, що ключовим фактором є "використовувати його для швидкого злиття". Це не стосується мого викладеного вище випадку, коли у мене є дві реальні гілки - гілка розробки та гілка випуску, але, схоже, це дуже добре застосовується для тимчасових гілок тем, які необхідні лише для обмеженого часу пероїдів, а потім можуть бути видаляються після об’єднання. Знову дякую.
Рой Truelove

1
Я це розумію, але вихідне питання залишається. Я думаю, що фактичною відповіддю є відповідь @Fabien Quatravaux
IsmailS

4
Ну, вам все одно доведеться примусово натискати гілку 1.0, ні? Принаймні, так у мене постійно все обертається. Метод Фаб'єна запобігає цьому.
joerx

23

@CodeGnome має рацію. Вам не слід перебазувати майстер на гілці 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 до master гілки. Ви отримаєте щось на зразок:

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: використовувати це слід лише в тому випадку, якщо ви помилились і штовхнули те, чого не хотіли.


Я думаю, що це найкраща відповідь на конкретну проблему в ОП. Ви створюєте тимчасову гілку злиття і перебазуєте на ній, а потім об'єднуєте для мастерингу та надсилання до початку. Тимчасова гілка не повинна бути переміщена до початкової точки. Єдиною додатковою порадою, яку я дав би, було б мати розробку або гілку qa, де злитий / перебазований код можна кваліфікувати. Після кваліфікації цей код буде об'єднаний лише у ff у master. Це дозволяє легко виправити помилки, якщо ваш процес кваліфікації триває занадто довго. В основному це процес "git flow".
Джавід Джамае

Дякую, Фаб'єн, чудова відповідь. Для тих з нас, хто просто хоче інтегрувати зміни masterі не проти об’єднати саму гілку git checkout my-branch; git rebase master; git checkout master; git merge my-branch
об’єктів

17

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

Я використовую перебазування цілої групи, але я публікую чимось приватним, де силове натискання не має значення (наприклад: мій власний клон на GitHub, як частина запиту на витягування), або перебазую перед тим, як натиснути вперше.

Це суть робочого процесу, коли ви використовуєте перебазування, але не змушуйте сильно натискати: не публікуйте речі, поки вони не будуть готові, не перебазуйте після натискання.


Дякую Ден. Не могли б ви повідомити, як тоді слід досягти вищезазначеного? Це просто не сценарій, коли застосовується перебазування?
Рой Truelove

2
Якщо ви ізолюєте всю свою роботу за гілками тем, це створює хороший сценарій для перебазування. Ви rebaseнещодавно внесли зміни у свою гілку теми, але після завершення змін mergeу цій гілці ви повернетесь у основну гілку розробки.
redhotvengeance

1
Проблема в тому, що ви опублікували гілку - тому вам потрібно примусово натиснути на сховище. Вам потрібно відмовитись від одного з двох: публікувати так, як ви робите, або перебазувати. Вибачте.
Даніель Піттман,

Здається, перебазування не працює для цього сценарію. v1.0 - це не гілка теми, це гілка релізу, тому вона ніколи не помре і її потрібно опублікувати.
Roy Truelove

5

Я думаю, що для цього шаблону перебазування-тоді-сили-натискання є хороший варіант використання, який не є результатом помилкового натискання: робота над гілкою об’єктів самостійно з кількох місць (комп’ютерів). Я роблю це часто, оскільки іноді працюю в офісі за робочим столом, а іноді вдома / на сайті замовника на ноутбуці. Мені потрібно періодично перебазувати, щоб не відставати від основної гілки та / або робити злиття чистішими, але мені також потрібно натискати з силою, коли залишаю одну машину, щоб перейти працювати на іншу (де я просто тягну). Працює як шарм, поки я єдиний, хто працює на філії.


2
У мене такий самий робочий процес (працює з кількох комп’ютерів / локацій). Отже, припустимо, ви працюєте над галуззю тем, яка називається „mytopic“. Поки ви завжди перебазуєте локальну викидну гілку (яка є просто гілкою mytopic) на "master", а потім зливаєте її назад у mytopic, тоді вам ніколи не доведеться змушувати натискати. 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
Переоцінка майстра виглядає дивно.
Emil Vikström

2
gitне позбавлений особистості
повторний

1
git merge -s ours origin/<branch>було те, що виправили для нас
Макс

0

tl; dr злиття із спільними гілками, перебазування з окремими гілками. --force-with-leaseє більш безпечною альтернативою силі і повинна допомогти вам досягти згаданої git нірвани без руйнівного характеру сили.

Загальне емпіричне правило, яке я бачив як працює для робочих процесів різних команд, - це використовувати 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. злиття в master з дуже чистим журналом git, зменшуючи безлад від кількох злиттів з нашої спільної гілки, щоб наша гілка "наздогнала" останню master (спільну гілку)

Четвертий крок ДІЙСНО важливий і одна з основних причин, я почав виступати за використання rebase. force-with-leaseперевіряє пульт дистанційного керування, чи не додано нових комітів. Якщо git pushбуло доведено, що це руйнівне, воно не підштовхне!

Я сподіваюся, це надає комусь більше впевненості у використанні rebase.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.