Git: Команда "git pull --rebase" простыми словами
Представьте, что вы и ваш коллега работаете над одной и той же веткой в Git. Коллега решил немного «прибраться» в истории коммитов, сделал это у себя локально и потом отправил изменения на сервер с помощью git push --force. Вы же в это время продолжали работать со старой версией этой ветки.
Теперь вы хотите забрать обновления с сервера через git pull, но Git ругается и говорит: «Что-то тут не так, история у нас разная, я не знаю, как их объединить».
В этом посте я простыми словами объясню, что именно произошло, что значит эта ошибка и зачем в таких случаях использовать git pull --rebase.
Что вообще случилось?
Когда ваш коллега переписал историю коммитов и сделал git push --force
это как будто он выкинул старую цепочку событий (которая была на сервере) и заменил её на новую (ту, тоторая сейчас у него локально). Git это заметил. А у вас на компьютере осталась старая история, и теперь Git видит две разные линии событий: одна у вас, другая - на сервере.к слову у нас в компании техлид запретил использовать
push --forceбез согласования лично с ним, и это на мой взгляд правильное решение, чтобы избежать бардака. Но такие правила не везде...
Вы пытаетесь сделать
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 false2. Переписать историю (
rebase)Git возьмёт ваши локальные коммиты и как бы «переустановит» их поверх новых коммитов с сервера, как будто вы сделали их позже.
Как включить:
git config pull.rebase true3. Только 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 pull --rebase - когда хотите «подстроить» свою историю под чужую (например ту, которая образовалась на сервере после того как кто-то сделал git push --force), не создавая лишних слияний.Надеюсь, теперь команда
git pull --rebase стала для вас понятной и больше не вызывает страха 
Если что - смело спрашивайте в комментариях!