IT-Storm

Отладка в два раза сложнее, чем написание кода. Следовательно, если вы пишете код настолько умно, насколько это возможно, вы по определению недостаточно умны, чтобы его отладить

Menu

Git: Команда "git pull --rebase" простыми словами

Git: Команда

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

Теперь вы хотите забрать обновления с сервера через git pull, но Git ругается и говорит: «Что-то тут не так, история у нас разная, я не знаю, как их объединить».

В этом посте я простыми словами объясню, что именно произошло, что значит эта ошибка и зачем в таких случаях использовать git pull --rebase.

Что вообще случилось?
Когда ваш коллега переписал историю коммитов и сделал git push --force

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

это как будто он выкинул старую цепочку событий (которая была на сервере) и заменил её на новую (ту, тоторая сейчас у него локально). Git это заметил. А у вас на компьютере осталась старая история, и теперь Git видит две разные линии событий: одна у вас, другая - на сервере.

Вы пытаетесь сделать git pull, чтобы обновить свою ветку. Но Git не знает, как правильно склеить вашу старую историю с новой. Поэтому он и выдаёт такое сообщение, например:
User
 + 538d044...84e43d3 feature_0981     -> origin/feature_0981  (forced update)
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge (the default strategy)
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint: 
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
Говоря простым языком: «У вас с сервером разная история. Скажите мне, что делать: сливать, пересобирать или вообще не трогать?»

Какие есть варианты?
Git предлагает вам три пути:

1. Слияние (merge)
Это поведение по умолчанию. Git просто добавит коммит слияния поверх всего, чтобы объединить две разные истории.
Как включить:
git config pull.rebase false

2. Переписать историю (rebase)
Git возьмёт ваши локальные коммиты и как бы «переустановит» их поверх новых коммитов с сервера, как будто вы сделали их позже.
Как включить:
git config pull.rebase true

3. Только fast-forward
Работает только если ваша история полностью устарела, и можно просто «перемотать» её вперёд без конфликтов.
Как включить:
git config pull.ff only

Так что же делать в нашей ситуации?
Если коллега переписал историю и сделал git push --force, вы не сможете просто сделать git pull без указания стратегии. Самый безопасный способ в этом случае - использовать --rebase.

Выглядит это так:
git pull --rebase origin feature_0981
где feature_0981 - имя ветки

Что делает эта команда?
1. Git сначала подтянет свежую историю с сервера.
2. Потом временно «открепит» ваши локальные коммиты.
3. Потом применит их заново, как будто вы их сделали позже, чем коллега.
4. Вуаля - теперь у вас красивая линейная история, без лишних коммитов слияния и конфликтов (если всё прошло гладко, если нет - то придётся исправить конфликты).

Почему не стоит навсегда включать pull.rebase?
Можно было бы просто прописать (тем самым создать постоянную запись в настройках вашего Git):
git config --global pull.rebase true
...и забыть об этом. Но я не советую этого делать.

Почему?

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

Поэтому лучше каждый раз осознанно выбирать нужную стратегию, добавляя флаг вручную: --rebase, --no-rebase или --ff-only.

Вывод
Если вы получили странное сообщение при git pull после того, как кто-то сделал git push --force, не паникуйте. Это обычная ситуация при плохой командной работе с Git. (в нормальных компаниях git push --force считается своего рода "злом" и применяется в исключительных случаях)

Запомните простое правило:

git pull --rebase - когда хотите «подстроить» свою историю под чужую (например ту, которая образовалась на сервере после того как кто-то сделал git push --force), не создавая лишних слияний.

Надеюсь, теперь команда git pull --rebase стала для вас понятной и больше не вызывает страха smiley

Если что - смело спрашивайте в комментариях!



 

Git