Коли я повинен використовувати git pull --rebase?


806

Я знаю деяких людей, які використовують git pull --rebaseза замовчуванням, та інших, які наполягають ніколи його не використовувати. Я вважаю, що я розумію різницю між об'єднанням і скасуванням, але намагаюся поставити це в контекст git pull. Це лише про те, щоб не бачити багато повідомлень про злиття, або є інші проблеми?


1
Джерело для людей, які радять проти git pull --rebase? Rebase або git rebase - це окрема діяльність від git pull --rebase!
przemo_li

Відповіді:


584

Ви повинні використовувати git pull --rebaseколи

  • ваші зміни не заслуговують на окрему галузь

Справді - чому б і не тоді? Це зрозуміліше і не нав'язує логічну групування вашим комітетам.


Гаразд, я вважаю, що це потребує певного уточнення. Як ви, мабуть, знаєте, у Git вас заохочують до розгалуження та злиття. Ваша локальна філія, в яку ви втягуєте зміни, і віддалена гілка - це насправді різні гілки, і git pullйдеться про їх об'єднання. Це розумно, оскільки ви натискаєте не дуже часто і зазвичай накопичуєте ряд змін, перш ніж вони є завершеною функцією.

Однак іноді - з будь-якої причини - ви думаєте, що насправді було б краще, якби ці дві - віддалені та локальні - були однією галуззю. Як у SVN. Саме тут git pull --rebaseвступає в гру. Ви більше не зливаєтесь - ви фактично здійснюєте зверху на віддаленій гілці . Саме про це йдеться насправді.

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


17
Я думаю, що це корисно, коли ви працюєте в одній гілці, але ви можете змінити своє робоче місце. Я схильний здійснювати і натискати свої зміни з однієї робочої станції, потім перетягую базу даних в іншу і продовжую працювати над тією ж гілкою.
Пабло Пацос

11
Корисна найкраща практика налаштувати Git для автоматичного відновлення бази даних після витягування git config --global pull.rebase preserve (збереження говорить, крім того, щоб активувати перезавантаження, щоб спробувати зберегти злиття, якщо ви зробили локально).
Колін Д Беннетт

2
Я не погоджуюся з тим, що ви повинні використовувати pull --rebase лише під час роботи над однією гілкою. Ви повинні використовувати його постійно, якщо це неможливо через якусь іншу обставину.
Томаш Фейфар

@ П. Швед ... "Однак іноді - з якоїсь причини - ти вважаєш, що насправді було б краще, якби ці дві - віддалені та локальні - були однією гілкою" ... чи можна це зробити? Моє розуміння: що в місцевому середовищі я можу мати своє відділення та віддалене дзеркало гілки як джерело / господар. Чи можете, будь ласка, надати сюди матеріали?
Мандроїд

736

Я хотів би дати іншу точку зору на те, що насправді означає "git pull --rebase", оскільки він, здається, іноді губиться.

Якщо ви коли-небудь використовували Subversion (або CVS), ви можете звикати до поведінки "svn update". Якщо у вас є зміни, які виконуються, а комісія не вдається, оскільки зміни були внесені вище, ви "svn update". Субверсія триває шляхом злиття змін у верхній частині потоку із вашими, що може призвести до конфліктів.

Щойно зробив Subversion, по суті був "pull --rebase". Акт переформулювання ваших локальних змін у відношенні до новішої версії - це "перезавантажувальна" його частина. Якщо ви зробили "svn diff" до невдалої спроби фіксації та порівняли отриманий розріз з результатом "svn diff" після цього, різниця між двома різними - це те, що зробила операція перезавантаження.

Основна відмінність Git від Subversion в цьому випадку полягає в тому, що в Subversion "ваші" зміни існують лише як незавершені зміни у вашій робочій копії, тоді як у Git ви фактично вчиняєте місцеві дії. Іншими словами, в Git ви розпрощалися з історією; ваша історія та історія вище за течією розійшлися, але у вас є спільний предок.

На мою думку, у звичайному випадку, коли ваша локальна філія просто відображає верхню галузь і постійно розвивається на ній, правильне робити - це завжди "--rebase", тому що це ви семантично насправді робите . Ви та інші викрадаєте передбачувану лінійну історію гілки. Той факт, що хтось інший трапився трохи натиснути перед вашою спробою поштовху, не має значення, і видається контрпродуктивним для кожної такої аварії часу, що призводить до злиття в історії.

Якщо ви насправді відчуваєте потребу в чомусь бути галуззю з будь-якої причини, на мою думку, це вже інше питання. Але якщо у вас немає конкретного і активного бажання представляти свої зміни у вигляді злиття, поведінка за замовчуванням, на мою думку, повинна бути "git pull --rebase".

Зверніть увагу на інших людей, яким потрібно спостерігати та розуміти історію вашого проекту. Ви хочете, щоб історія була всіяна сотнями злиттями всюди, або ви хочете лише декілька виділень, що представляють собою реальні злиття навмисних розбіжних зусиль з розвитку?


18
@MarceloCantos Щоб було зрозуміло, я не кажу, що git (інструмент) повинен за замовчуванням перезавантажуватись. Це було б небезпечно, оскільки база даних суттєво знищує історію. Я кажу, що з точки зору робочого процесу, коли ви не маєте наміру здійснювати свою філію і просто викрадаєте якусь галузь, над якою працюють і інші люди, "поведінка користувача за замовчуванням повинна бути поведінкою за замовчуванням.
scode

1
Ти кажеш, що цього не слід git config --global branch.autosetupmerge always?
Марсело Кантос

9
@MarceloCantos Ні, я не;) Особисто я б залишив автозапуску за замовчуванням true (якщо я зливаюсь назад і четвертий між гілками, відмінними від локальних <-> віддалених, мені подобається, що це буде явним). Я просто кажу, що як людина, я завжди використовую "git pull --rebase" як частину мого нормального робочого процесу "схопитися останній у головній галузі", тому що я ніколи не хочу створювати комісію об'єднання, якщо я не розгалужую явно.
scode

9
+1 @код. Після багатьох болісних годин боротьби з питанням відновлення / злиття, нарешті, ось відповідь, що це нігті.
AgileYogi

10
Ця відповідь є лише спробою адаптувати користувачів нерозподілених систем управління версіями до Git, а не давати їм шанс правильно зрозуміти переваги наявності належних гілок.
Олексій Зімарьов

211

Мабуть, найкращий спосіб пояснити це на прикладі:

  1. Аліса створює галузь теми та працює над нею
  2. Боб створює непов'язану галузь теми та працює над нею
  3. Аліса робить git checkout master && git pull. Майстер уже в курсі.
  4. Боб робить git checkout master && git pull. Майстер уже в курсі.
  5. Аліса робить git merge topic-branch-A
  6. Боб робить git merge topic-branch-B
  7. Боб робить git push origin masterперед Алісою
  8. Аліса це робить git push origin master, що її відкидають, оскільки це не швидке злиття вперед.
  9. Аліса переглядає походження / журнал господаря і бачить, що фіксація не пов'язана з її.
  10. Аліса робить git pull --rebase origin master
  11. Фіксація Аліси злиття розмотається, прихильність Боба витягується, а Аліса призначається після виконання Боб.
  12. Аліса це робить git push origin master, і всі щасливі, що їм не доведеться читати непотрібні злиття, коли вони дивляться на журнали в майбутньому.

Зауважте, що конкретна галузь, в яку об'єднано, не має значення для прикладу. Майстер у цьому прикладі так само легко може бути відділенням випуску чи відділом розробки. Ключовим моментом є те, що Alice & Bob одночасно об’єднують свої локальні відділення у спільну віддалену гілку.


2
Приємно. Я схильний бути явним і git co master && git pull; git checkout topic-branch-A; git rebase master; git checkout master; git merge topic-branch-A; git push origin masterповторюваним, якщо інший поштовх до оволодіння відбувся перед моїм. Хоча я можу побачити стислі переваги у вашому рецепті.
HankCa

Приємне пояснення @Cody Poll
Rajanikanta Pradhan

148

Я думаю, ви повинні використовувати, git pull --rebaseколи співпрацюєте з іншими людьми в одній галузі. Ви перебуваєте у вашій роботі → фіксації → роботі → циклі фіксації, і коли ви вирішите підштовхнути свою роботу, ваш поштовх відхиляється, оскільки в одній гілці була паралельна робота. У цей момент я завжди роблю pull --rebase. Я не використовую сквош (для вирівнювання комітетів), але переробляю основу, щоб уникнути зайвих комірок злиття.

Зі збільшенням ваших знань Git ви переглядаєте історію набагато більше, ніж будь-які інші системи контролю версій, якими я користувався. Якщо у вас є маса невеликих об'єднань, легко втратити фокус на більшій картині, що відбувається у вашій історії.

Це фактично єдиний раз, коли я роблю перезавантаження (*), а решта мого робочого процесу базується на злитті. Але поки це роблять ваші найчастіші довіри, зрештою історія виглядає набагато краще.

(*) Під час викладання курсу Git у мене був затриманий студент з цього приводу, оскільки я також виступав за звільнення гілок функцій за певних обставин. І він прочитав цю відповідь;) Таке звільнення також можливе, але воно завжди має бути за попередньо домовленою / узгодженою системою, і як таке не повинно застосовуватися "завжди". І в той час я зазвичай цього не роблю pull --rebase, про що йдеться;)


2
напевно, можна написати сценарій, щоб приховати
комірки

3
Злиття можуть містити також різниці, а це означає, що це не зовсім тривіально
krosenvold

9
@hasen j Так, але ЗМІСТ цих злиття може мати значення
krosenvold

Ця відповідь розпливчаста і сумнівна у порівнянні з обраною відповіддю: що саме ви маєте на увазі під «тією ж гілкою»? Однак є кілька хороших моментів, які не в обраній відповіді.
iwein

1
Нечіткість навколо "гілки" є цілком навмисною, оскільки існує стільки способів використання реф. "лінія роботи" - це лише один варіант.
krosenvold

49

Я не думаю, що коли-небудь є причину не використовувати pull --rebase- я додав код до Git спеціально, щоб дозволити моїй git pullкоманді завжди перезавантажуватися проти верхніх комітетів.

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


2
"Переглядаючи історію, просто ніколи не цікаво дізнатися, коли хлопець, який працює над цією функцією, перестав синхронізуватися." / але чи це не означає, що ці проміжні комітети, ймовірно, порушені?
eglasius

10
Так, і вони теж не "ціла держава". Ось чому ми їх не хочемо. Я хочу знати, що він хотів, а не як він туди потрапив.
Дастін

4
Якщо pull --rebaseзавжди слід використовувати, чому це не pullробиться за замовчуванням?
страя

2
Боюся, вам доведеться сформувати власну думку. У мене є кілька речей, .gitconfigщоб змусити деякі варіанти зробити правильно. Я думаю, що git rebase робить неправильну справу за замовчуванням, як і тег git тощо. Якщо ви не згодні, вам не потрібно обґрунтовувати свою думку.
Дастін

8
Це здається гарною порадою, якщо ви виходите з "вище" за течією, скажімо master, і якщо галузь, в яку ви втягуєтесь, ще не стала публічною (поки що). Якщо ви витягнете з іншого боку гілку функції в masterце більше схоже на навпаки: ніколи немає причини використовувати --rebase, правда? Це може бути причиною того, що це не за замовчуванням. Я виявив, що Ребази - це те, як зміни повинні проходити від верхівки ієрархії вниз, а злиття - як вони протікають назад вгору. derekgourlay.com/blog/git-when-to-merge-vs-when-to-rebase
jolvi

38

Просто запам'ятай:

  • тягнути = добувати + зливати
  • тягнути --rebase = витяг + відновлення

Отже, виберіть спосіб, яким ви хочете обробляти свою філію.

Ви краще знаєте різницю між злиттям та повторною базою :)


9

Я думаю, що це зводиться до особистих уподобань.

Ви хочете приховати свої дурні помилки, перш ніж натискати на зміни? Якщо так, git pull --rebaseідеально. Це дозволяє пізніше зменшити свої зобов’язання на кілька (або один). Якщо у вашій (незапущеній) історії є злиття, git rebaseпізніше це зробити не так просто .

Я особисто не проти публікації всіх моїх дурних помилок, тому я схильний зливатися замість перезапису.


8
Зауважте, хто переглядає це питання: ця відповідь абсолютно не має значення для запитання "коли я повинен використовувати git pull --rebase?"
therealklanni

3
@therealklanni Я відредагував відповідь, щоб стало зрозуміліше, наскільки це стосується питання (сподіваюся, не руйнуючи наміру).
Paŭlo Ebermann

Ділитися брудним та неструктурованим журналом роботи - це не чесне починання, це лише лінь. Ви витрачаєте час людей, змушуючи їх переслідувати вас через кролячу діру розвитку та налагодження; дайте їм результат, а не рамонти.
krystah

8

git pull --rebaseможе приховати переписування історії від співавтора git push --force. Я рекомендую використовувати git pull --rebase лише в тому випадку, якщо ви знаєте, що забули просунути свої зобов'язання, перш ніж хтось зробить те саме.

Якщо ви нічого не зробили, але ваш робочий простір не чистий, безпосередньо git stashперед тим git pull. Таким чином, ви не мовчите переписувати свою історію (що мовчки може кинути частину вашої роботи).

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