Введение в Git Merge и Git Rebase: зачем и когда их использовать
Часто у разработчиков возникает выбор между Merge (слияние) и Rebase (перемещение). В Гугле вы увидите разное мнение, многие советуют не использовать Rebase, так как это может вызвать серьезные проблемы. В статье я объясню, что такое слияние и перемещение, почему вы должны (или не должны) использовать их и как это сделать.

Git Merge и Git Rebase преследуют одну и ту же цель. Они предназначены для интеграции изменений из одной ветки в другую. Хотя конечная цель одинаковая, принципы работы разные.
Некоторые считают, что вы всегда должны использовать Rebase, другие предпочитают Merge. В этом есть свои плюсы и минусы.
Git Merge

Слияние — обычная практика для разработчиков, использующих системы контроля версий. Независимо от того, созданы ли ветки для тестирования, исправления ошибок или по другим причинам, слияние фиксирует изменения в другом месте. Слияние принимает содержимое ветки источника и объединяет их с целевой веткой. В этом процессе изменяется только целевая ветка. История исходных веток остается неизменной.
Плюсы:
- простота;
- сохраняет полную историю и хронологический порядок;
- поддерживает контекст ветки.
- история коммитов может быть заполнена (загрязнена) множеством коммитов;
- отладка с использованием git bisect может стать сложнее.
Слейте ветку master в ветку feature, используя команды checkout и merge.
$ git checkout feature $ git merge master (or) $ git merge master feature
Это создаст новый «Merge commit» в ветке feature, который содержит историю обеих веток.
Git Rebase
Rebase — еще один способ перенести изменения из одной ветки в другую. Rebase сжимает все изменения в один «патч». Затем он интегрирует патч в целевую ветку.
В отличие от слияния, перемещение перезаписывает историю, потому что она передает завершенную работу из одной ветки в другую. В процессе устраняется нежелательная история.

- Упрощает потенциально сложную историю
- Упрощение манипуляций с единственным коммитом
- Избежание слияния коммитов в занятых репозиториях и ветках
- Очищает промежуточные коммиты, делая их одним коммитом, что полезно для DevOps команд
- Сжатие фич до нескольких коммитов может скрыть контекст
- Перемещение публичных репозиториев может быть опасным при работе в команде
- Появляется больше работы
- Для восстановления с удаленными ветками требуется принудительный пуш. Это приводит к обновлению всех веток, имеющих одно и то же имя, как локально, так и удаленно, и это ужасно.
Как это сделать
Переместите ветку feature на главной ветке, используя следующие команды.
$ git checkout feature $ git rebase master
Это перемещает всю ветку функции в главную ветку. История проекта изменяется, создаются новые коммиты для каждого коммита в основной ветке.
Интерактивное перемещение
Это позволяет изменять коммиты при их перемещении в новую ветку. Это лучше, чем автоматическое перемещение, поскольку обеспечивает полный контроль над историей коммитов. Как правило, используется для очистки истории до слияния ветки feature в master.
$ git checkout feature $ git rebase -i master
Это откроет редактор, перечислив все коммиты, которые будут перемещены.
pick 22d6d7c Commit message#1 pick 44e8a9b Commit message#2 pick 79f1d2h Commit message#3
Это точно определяет, как будет выглядеть ветка после выполнения перемещения. Упорядочивая объекты, вы можете сделать историю такой, как захотите. Вы можете использовать команды fixup, squash, edit, и так далее.
Какой из них использовать?
Так что же лучше? Что рекомендуют эксперты?
Трудно принять единственно правильное решение о том, что лучше использовать, поскольку все команды разные. Всё зависит от потребностей и традиций внутри команды.
Принимайте решения на основании компетенции команды в Git. Для вас важна простота или перезаписывание истории, а может быть что-то другое?
Что рекомендую я?
По мере роста команды становится сложно управлять или отслеживать изменения в разработке, применяя слияние. Чтобы иметь чистую и понятную историю коммитов, разумно использовать Rebase.
Преимущества Rebase:
- Вы разрабатываете локально: если вы не делились своей работой с кем-либо еще. На данный момент вы должны предпочесть перемещение слиянию, чтобы сохранить свою историю в порядке. Если у вас есть личная вилка репозитория, которая не используется совместно с другими разработчиками, вы можете делать rebase даже после того, как переместились в свою ветку.
- Ваш код готов к ревью: вы создали пулл реквест. Другие анализируют вашу работу и потенциально стягивают ее к своей вилке для локального ревью. На данный момент вы не должны перемещать свою работу. Вы должны создать коммит «переделать» и обновить ветку. Это помогает отслеживать запросы на пулл реквест и предотвращает случайную поломку истории.
- Ревью сделано и готово к интеграции в целевую ветку. Поздравляем! Вы собираетесь удалить свою ветку feature. Учитывая, что с этого момента другие разработчики не будут fetch-merging эти изменения, это ваш шанс изменить вашу историю. На этом этапе вы можете переписать историю и сбросить оригинальные коммиты, и эти надоедливые «переделки» и «слияние» сливаются в небольшой набор целенаправленных коммитов. Создание явного слияния для этих коммитов является необязательным, но имеет значение. Он записывает, когда функция достигла master.
Не забывайте:
code = coffee + developer
Git rebase — перебазирование коммитов и веток
Знакомим с git rebase: рассказываем о преимуществах команды и показываем, в каких случаях ее стоит использовать и почему.
Эта инструкция — часть курса «Введение в Git».
Смотреть весь курс
Введение
Rebase (перебазирование) — один из способов в git, позволяющий объединить изменения двух веток. У этого способа есть преимущество перед merge (слияние) — он позволяет переписать историю ветки, придав тот истории тот вид, который нам нужен.
В этой инструкции мы познакомим вас поближе с командой git rebase, расскажем о преимуществах и тонкостях работы с ней, покажем, в каких случаях ее стоит использовать и почему.
Git rebase — что это
Из документации — это наложение коммитов поверх другого базового коммита. Под базовым понимается тот коммит, к которому применяются коммиты выбранной ветки.
git rebase [ []]
Первый аргумент обязательный (upstream) — это базовый коммит, к которому применятся коммиты выбранной ветки. Второй аргумент можно не задавать, если HEAD указывает на ветку, которая будет нами перебазирована.
Как работает git rebase
Чтобы понимать процесс работы перебазирования, обратимся к рисунку 1.
У нас есть две ветки — master и my_branch. Мы находимся на ветке my_branch (HEAD указывает на ветку my_branch). Выполняем команду:
git rebase master
После этого git удалит и последовательно переместит коммиты C, D, F из ветки my_branch в ветку master — сначала C, затем D и F. Новые коммиты C’, D’, F’ полностью идентичны удаленным, меняется только хеш.
Сначала для ветки my_branch базовым коммитом был B, но после стал коммит E. Это и есть процесс под названием перебазирование.
Как использовать git rebase
Перебазирование в git используется для придания линейности истории ветки, чтобы удобно отслеживать изменения, или для обновления ветки разработки последними изменениями из основной ветки. Также есть и другие варианты использования — с помощью интерактивного режима и параметра —onto.
Линейная история — реинтеграция тематической ветки после выполнения git rebase master
После того как мы использовали команду git rebase, можно перемотать ветку master командой git merge:
git checkout master git merge my_branch
К команде слияния можно добавить флаг либо —ff (fast-forward merge), чтобы не создавать коммит слияния, или добавить —no-ff — для его создания. Создание коммита слияния помогает определить, когда ветки объединились, и какие коммиты тематической ветки были сделаны.
Когда работа с тематической веткой закончена, удаляем ее:
git branch -d my_branch
Это приведет к законченному виду истории, когда мы внедрили изменения из тематической ветки в основную часть проекта.
Конфликты
Так как git rebase последовательно переприменяет коммиты, то могут возникнуть конфликты слияния (merge conflicts). Первая причина появления конфликта — объединение коммитов, содержащих изменения в одних и тех же файлах. Вторая причина — несколько человек изменяют одинаковый файл на одной расшаренной ветке. Чтобы узнать, в каких файлах есть конфликтующие изменения, проверим статус.
git status
Нам будет предложено решить конфликтные коммиты, затем пометить их решенными:
git add/rm
Дальше нужно продолжить перебазирование:
git rebase --continue
Или еще откатить изменения — вернуться в состояние до использования команды rebase.
git rebase --abort
Есть и третий вариант с перезапуском шага и перезагрузкой процесса перебазирования:
git rebase --skip
Но будьте аккуратны, skip пропустит (удалит) конфликтный коммит.
Git rebase interactive
Интерактивный режим rebase используется для перезаписи истории посредством изменения самих коммитов, а также информации в них. Переход в интерактивный режим перебазирования делается при помощи флага -i или —interactive.
git rebase [-i | --interactive]
Выполнение этой команды создаст список коммитов в хронологическом порядке добавления, чтобы пользователь мог по своему желанию отредактировать их перед последующим перебазированием. Дальше мы рассмотрим подробнее, как это происходит.
Как пользоваться интерактивным режимом
Например, вот созданная ветка master с пятью коммитами:
2hqsibn selected new method in script.js (HEAD -> master) 4kq5jn2 changes to the script.j qk01ru3 resolved conflict fmjgyu6 added new files z2zgn0c initial commit (origin/master)
Поставлено две задачи:
- Поменять местами коммиты qk01ru3 и 4kq5jn2;
- исправить ошибку в комментарии четвертого коммита (4kq5jn2).
Для этого мы включаем интерактивный режим rebase. В нем можно указать определенное количество коммитов для изменения. Чтобы это сделать, необходимо передать в аргумент коммит, предшествующий тому, который мы будем изменять (в данном случае это fmjgyu6), либо задать “HEAD~[x]”, где вместо [x] — нужное нам число коммитов.
git rebase -i HEAD~3
Откроется текстовый редактор по умолчанию, где также будет приведено описание команд, используемых в интерактивном режиме rebase:
pick qk01ru3 resolved conflict pick 4kq5jn2 changes to the sсript.j pick 2hqsibn selected new method in script.js # Rebase fmjgyu6..2hqsibn onto fmjgyu6 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop = remove commit
Обратите еще раз внимание, что коммиты в интерактивном режиме расположены в другом порядке, от более старого к новому. Приступим к решению задач.
- Для того чтобы поменять коммиты местами, мы просто меняем местами их строчки.
- Чтобы исправить ошибку в комментарии, мы меняем команду “pick” в 4kq5jn2 на “reword” и в следующем окне переписываем комментарий на “changes to the script.js”.
В итоге имеем следующий порядок коммитов:
reword 4kq5jn2 changes to the sсript.js pick qk01ru3 resolved conflict pick 2hqsibn selected new method in script.js
Не забываем сохранять изменения, как вы обычно делаете при сохранении в вашем текстовом редакторе. Выходим из интерактивного режима закрытием текстового редактора.
Теперь наша ветка имеет вид:
vh9xwf3 selected new method in script.js (HEAD -> master) s70zmpx resolved conflict b0jemdh changes to the script.js fmjgyu6 added new files z2zgn0c initial commit (origin/master)
Имейте в виду, что хеши коммитов, с которыми работал rebase, станут иными.
Какой режим выбрать: стандартный или интерактивный
Интерактивный rebase — продвинутая версия обычного rebase, которая дает возможность большего взаимодействия с коммитами. Если нужно разделить, объединить, удалить коммиты, изменить их описание и порядок, интерактивный режим справится на отлично. Если же такой потребности нет, быстрее будет использовать стандартный режим rebase, в котором от пользователя не требуются лишние действия до возникновения конфликтов.
Git rebase —onto
Onto относится к возможностям, раскрывающих rebase во всей красе.
git rebase --onto [ []]
Эта опция позволяет указать коммит, с которого будут перебазироваться коммиты (первый аргумент), иначе это называется новая база. Третий аргумент (branch) можно не указывать, если HEAD указывает на ветку, которая будет нами перебазирована.
Пример
У нас есть три ветки: master, feature-1, develop.
Нам нужно интегрировать изменения из ветки develop в master. Воспользуемся обычным rebase:
git checkout develop
git rebase master
Тогда получим вот такой результат с двумя одинаковыми коммитами D:
Это произошло потому, что перебазирование переприменило коммиты D, G, H, I, так как по отношению к ветке master коммиты ветки develop начинаются с коммита D как связывающего коммита. Теперь решим задачу с интеграцией изменений из develop немного по-другому. Чтобы избежать таких случаев как с коммитом D, воспользуемся новой командой:
git rebase --onto master feature-1 develop
Результат проиллюстрирован на рисунке ниже.
Rebase удаленного репозитория
При работе с удаленным репозиторием в тематической ветке, например на GitHub, следует быть осторожным, используя rebase. Как вы уже знаете, rebase перезаписывает историю, в процессе изменяются хеши коммитов, а это может привести к конфликтам в работе с веткой у других членов команды. Поэтому, если вы работаете над тематической веткой не одни, стоит прибегнуть к нескольким правилам для предотвращения возможных проблем.
- Синхронизировать изменения. Перед тем как вы будете заливать свой код на тот же GitHub, выполните git pull изменений, чтобы избежать конфликтных ситуаций.
- Не перебазировать давно созданные ветки. Количество шагов в rebase равно количеству коммитов на перебазируемой ветке, если не указаны иные опции. Поэтому с увеличением количества неперебазированных коммитов, растет и вероятность появления конфликта.
- Чтобы внедрить изменения в мастер, стоит создать свою локальную ветку и перебазировать ее поверх origin/master. Тогда останется лишь сделать перемотку или бесконфликтное слияние для владельца.
- Не проводить rebase уже отправленных коммитов в публичный репозиторий. Коллегам придется выполнить слияние, что приведет к путанице.
Pull rebase
Чтобы запушить свою ветку, когда git не знает, как объединить ветки, используется режим force:
git push origin --force
С этим режимом будут скопированы родительские коммиты feature на origin, указатель перемещается, как он установлен на локальном репозитории. Важно указать идентификатор ветки в , иначе запушатся все локальные ветки ориджина.
А чтобы извлечь изменения из удаленного репозитория, вместо обычного pull можно использовать режим rebase:
git pull --rebase origin
Локальные merge коммиты не образуются, а история будет выглядеть линейно.
Дополнительные опции перебазирования
Ниже приведена таблица некоторых опций, которые могут быть полезны для работы с rebase.
| Опции | Пояснение |
| -s —strategy= | Использовать стратегию слияния вместо дефолтного “ort”, что изменит поведение rebase. Подробнее в документации. |
| -X —strategy-option= | Эта опция для применения более одной стратегии в порядке, заданном пользователем. |
| -x —exec | Выполнение одной или более shell-команд после каждого шага rebase в интерактивном режиме. Если выполнение команды неудачно, перебазирование остановится. |
| —no-keep-empty | Не оставлять пустые коммиты. То есть убирать те коммиты, которые ничего не меняют по отношению к родителю. |
| —allow-empty-message | Позволяет перебазировать пустые коммиты с пустым сообщением. |
| —autosquash | В интерактивном режиме берет коммиты, которые начинаются с fixup! или squash! и ставит соответствующую команду, чтобы объединить коммит с предыдущим.Чтобы это значение всегда работало по умолчанию, можно прописать следующее:“git config —global rebase.autosquash true” |
Заключение
В этой инструкции мы рассмотрели, как сделать rebase ветки в git, узнали про возможность более продвинутой манипуляции с коммитами в режиме interactive и onto, а также тонкости, которые следует соблюдать при работе с rebase.
Работа с ветками в Git (git branch)
Обзор Git Rebase
Удаление и перемещение коммитов в git опасны потерей данных или истории изменений. Git Rebase выполняет эти и другие операции. Владение этой командой повышает уверенность при работе с репозиторием.
Введение
Системы контроля версиями полезны, когда они могут рассказать историю всех изменений. Эта история может быть как реальный рассказ о жизни и развитии программной системы. Но может быть и кучкой коммитов, разобраться в которых нельзя и которые не несут пользы.
В больших системах путаница может быть невероятных размеров. Такие модели как Git Flow 1 сильно облегчают жизнь, но только в том случае, если разработчики аккуратно относятся к своей истории коммитов, когда каждый коммит — это небольшой (или даже совсем крохотный) рассказ об одном исправлении в системе. Это исправление настолько маленькое, что разобраться в нем не составляет труда, а название коммита, данное разработчиком, такое прозрачное, что заглядывать в тело коммита нет нужды.
Вести аккуратную историю помогает команда git rebase. Основная ее цель “перетаскивать” коммиты из одного места в другое. Также с помощью нее можно избавляться от ненужных коммитов, склеивать одни и менять порядок других.
Умение пользоваться командой git rebase придает уверенности при работе с репозиторием.
Предостережение
Ребейзинг может “удалить” коммиты. Ребейзинг может испортить историю коммитов.
Однако в действительности удалить коммиты может только сборщик мусора. Это знание не сильно поможет, если потерять все ссылки на коммит, но если добавить лишнюю ветку или просто запомнить sha-1 хеш коммита, то всегда можно восстановить ребейзнутые коммиты.
О структуре коммитов
Коммит — это изменения в файлах репозитория + дополнительная информация. Идентифицируются коммиты с помощью sha-1 хеша. Коммиты с одинаковым хешем — одинаковые, с разными хешами — разные.
Коммит хранит дату создания, поэтому если создать два одинаковых по содержанию коммита, то они будут иметь разные хеши и будут разными. Так происходит при выполнение команды git commit –amend — команда перезаписывает текущий коммит и даже если ничего не изменилось, хеш все равно станет новым.
Ребейзинг переприменяет коммиты, то есть создает коммиты с таким же содержанием, но в другом месте. Новые коммиты получат новые хеши.
Указатели на коммиты
Некоторые названия настолько неудачно подобраны, что, услышав термин, человек сразу понимает о чем идет речь, понимает приблизительно правильно и у него нет причин разбираться глубже.
Речь идет о ветках. Часто представляют ветку, как речку, ответвляющуюся от бурной реки и текущую дальше самостоятельно. Поэтому кажется, что при создании ветки происходит что-то важное. На деле ветка это просто указатель на коммит. Разница между хешом и веткой лишь та, что ветка перескакивает с одного коммита на другой по мере их добавления. В остальном, ветка — это буквенный синоним хеша.
Проще говоря, ветка указывает на коммит. Поэтому если ответвить 5 веток от master, то все они будут указывать на один и тот же коммит. Однако новые коммиты будут свои в каждой из веток.
Создание коммита
Каждый коммит (кроме начального) имеет родительский коммит, который для него аналог “предыдущего”. Из одного коммита может выходить несколько дочерних коммитов. Это делается с помощью ветвления. А так как ветки могут соединяться в одну, то у коммита может быть и несколько родительских коммитов. Обычно их два, но есть возможность сделать merge трех и более коммитов одновременно.
Иногда коммит бывает создан не в том месте и не в то время. Не в том месте означает, что он был создан не в той ветке, а не в то время означает, что коммит был создан, но потом ветка разработки обогатилась новым кодом и хочется пересоздать коммит, начиная с более свежего кода.
Пересоздание коммитов
Пересоздать коммит просто. Предположим типичную ситуацию — необходимо добавить фичу А. Создается отдельная ветка feature/A/super_code от ветки develop. На данном этапе новая ветка указывает по-прежнему на самый свежий коммит. Пусть фича мысленно разбивается на два коммита. Первый коммит с успехом создается. В это время в ветку develop добавляются важные коммиты с важным классом Х, без которого завершить фичу А не получится.
Что же делать? Подтягивать изменения. Можно слить ветку develop в ветку с задачей. Безопасно, но история будет подпорчена. Делается ребейзинг
git rebase develop
Предполагается, что develop уже содержит новые коммиты, то есть, что уже были сделаны fetch/pull.
Как работает команда git rebase? В простом случае, это работает так:
- текущая ветка перестает указывать на текущий коммит
- коммиты, которые есть в текущей ветке, но которых нет в develop (то есть новые коммиты) пересоздаются от последнего коммита в develop
- текущая ветка начинает указывать на только что созданные коммиты
- старые коммиты остаются висячими — на них ветка с задачей больше не указывает
Ниже приведены три дерева коммита
Ветка с задачей исходит из актуального коммита

Код разработки обновился, ветка с задачей исходит из старого коммита

Выполнен ребейзинг, ветка с задачей исходит из актуального коммита

Стоит обратить внимание на хеш коммита до ребейзинга (8f26890) и после (3b16148). Разумеется, по старому хешу можно найти старый коммит.
Создадим ветку, указывающую на старый коммит
git branch before_rebasing 8f26890

Нетрудно видеть, что старый коммит остался в целости и сохранности, однако, если на него никто не указывает, то он не отображается в истории коммитов. Такие висячие коммиты удаляются сборщиком мусора в последствии (например, через месяц).
Потеря коммитов
Чтобы избавиться от риска потерять коммиты, перед ребейзингом следует создать дополнительную ветку
git branch backup
Простой Rebase
Формат команды такой
git rebase [BRANCH or SHA1]
Команда изменяет текущую ветку. Переданный параметр — это просто указатель на новое начало коммитов. Пересоздаются (копируются) коммиты из диапазона [BRANCH or SHA1]..HEAD . То есть все предки текущего коммита (включая его самого) без предков коммита (включая его самого) [BRANCH or SHA1]. Это то, что интуитивно можно назвать как “новые” коммиты.
Но в Merge все наоборот!
- При ребейзинге текущая ветка — ветка с задачей, а ребейзятся относительно главной ветки.
- При слиянии текущей задачи — переключаются на главную ветку и сливают ветку с задачей.
Правило простое — изменению подвержена всегда текущая ветка. Почти все команды в git следуют этому правилу.
- При ребейзинге главная ветка не трогается, изменяется ветка с задачей — она пересоздается в другом месте.
- При слиянии главная ветка изменяется — в ней создается мерж-коммит. Ветка с задачей наоборот остается в прежнем виде.
Поэтому при ребейзинге придется дважды переключаться с ветки на ветку
git checkout develop git pull git checkout feature/A/super_code git rebase develop
Однако если использоваться слияние для подтягивания изменений, то сценарий похожий
git checkout develop git pull git checkout feature/A/super_code git merge develop
Разница есть только со сценарием завершения задачи
git checkout develop git pull git merge --no-ff feature/A/super_code git push git branch -d feature/A/super_code
Таким образом, для того, чтобы определить “что и куда”, надо задать вопрос “какую ветку надо изменить?”. Находиться следует в той ветке, которую надо изменить.
Интерактивный Rebase
Ребейзинг позволяет также переписывать историю своих коммитов.
Одна из таких ситуаций. В ветке с задачей 40 коммитов. Последние 2 отвечают за добавления фичи, а предыдущие 38 — это долгий и опасный рефакторинг. Для истории достаточно иметь один коммит для рефакторинга, поэтому эти коммиты следует склеить в один.
git rebase -i develop
Такая команда делает то же самое, что и раньше, но перед этим открывает текстовый редактор, в котором можно изменить поведение по умолчанию.
В редакторе помещены записи о коммитах. Почти тоже самое, что в логе коммитов, но порядок обратный. Также перед каждым коммитом записана команда — добавить коммит, объединить с предыдущим и так далее. Сразу после коммитов git приводит инструкцию в комментариях.
Удаление записи о коммите — удаляет коммит, а точнее не создает его. Изменение порядка записей вызывает изменение порядка создания коммитов.
Rebase и коммиты удаленного репозитория
Пересоздавать коммиты, которые были отправлены в удаленный репозиторий не стоит. Причина простая — у других разработчиков могут остаться ссылки на старые коммиты. Два одинаковых коммита в разных местах репозитория — печальная картина.
Правило здесь такое — если коммиты не были отправлены в удаленный репозиторий, то с ними можно делать что угодно. Если же коммиты стали общим достоянием, то ребейзинг не стоит делать без согласования с командой.
Конфликты
Конфликты случаются везде, где накладываются изменения из разных мест. Это происходит при слиянии (git merge), при отмене коммитов (git revert) и даже при переключении (git checkout, git stash). Во всех командах конфликты разрешаются по общим правилам. Поэтому в ребейзинге разрешение конфликтов такое же как и при слиянии.
При слиянии создается специальный мерж-коммит, в котором хранятся все изменения, сделанные в отдельной ветке. Поэтому все конфликты разрешаются в этом же коммите. В истории хранятся все коммиты из ветки с задачей и мерж-коммит. Последний можно рассматривать как завершающий штрих.
При ребейзинге дополнительных коммитов не создается. Поэтому разрешение конфликтов будет происходить прямо в коммитах задачи. По большому счету это большой плюс, так как изменения в коммитах становятся более актуальными. С другой стороны, разрешение конфликтов может стать болью — конфликты могут появиться в каждом коммите новой ветки.
В помощниках вроде TortoiseGit процесс разрешения конфликтов почти ничем не отличается от слияния. В консоли используются следующие команды.
git rebase --continue git rebase --abort
Детальный Rebase
Существует еще одна форма команды ребейзинга
git rebase [FROM] [TO] --onto [START]
FROM, TO, START – хеши коммитов или названия веток/тегов. Команда копирует коммиты из диапазона FROM..TO в START.
Если TO — хеш, а не ветка, то результат работы увидеть сложно. Обычно это изменяемая ветка. По сути новый параметр здесь только FROM, который обрезает ветку.
Стандартная команда, выполненная, находясь внутри ветки feature/A/super_code
git rebase develop
Может быть заменена на
git rebase develop feature/A/super_code --onto develop
Примеры
Необходимо скопировать последний коммит из ветки с задачей в develop
git rebase feature/A/super_code^ feature/A/super_code --onto develop
(в git можно указать на родительский коммит с помощью значка шапочки)
Коммит сделан в ветке feature/A, а должен был быть в ветке bug/B.
# save origin of bug/B git branch copy_bug_B bug/B # move bug/B to new commit git branch -f bug/B feature/A # move feature/A back git branch -f feature/A feature/A^ # copy new commit to saved origin of bug/B git rebase bug/B^ bug/B --onto copy_bug_B # remove temporary branch git branch -d copy_bug_B
Чистая история коммитов
Рефакторинг привыкли относить только к коду, но хорошая и наглядная история коммитов в репозитории может дать больше информации разработчику. Правило бойскаута из книги “Чистый код” Роберта Мартина «оставь место стоянки чище, чем оно было до твоего прихода» применимо и к истории коммитов. Поэтому использование Git Rebase также полезно в работе с репозиторием, как инструменты рефакторинга в IDE для работы с кодом.
- http://nvie.com/posts/a-successful-git-branching-model ↩
A3.8 Приложение C: Команды Git — Внесение исправлений
Некоторые команды в Git основываются на подходе к рассмотрению коммитов в терминах внесённых ими изменений, т. е. рассматривают историю коммитов как цепочку патчей. Ниже перечислены эти команды.
git cherry-pick
Команда git cherry-pick берёт изменения, вносимые одним коммитом, и пытается повторно применить их в виде нового коммита в текущей ветке. Эта возможность полезна в ситуации, когда нужно забрать парочку коммитов из другой ветки, а не сливать ветку целиком со всеми внесёнными в неё изменениями.
Этот процесс описан и показан в разделе Схема с перебазированием и отбором главы 5.
git rebase
git rebase — это «автоматизированный» cherry-pick . Он выполняет ту же работу, но для цепочки коммитов, тем самым как бы перенося ветку на новое место.
Мы в деталях разобрались с механизмом переноса веток в разделе Перебазирование главы 3, включая рассмотрение потенциальных проблем переноса опубликованных веток при совместной работе.
Мы использовали эту команду на практике для разбиения истории на два репозитория в разделе Замена главы 7, наряду с использованием флага —onto .
В разделе Rerere главы 7 мы рассмотрели случай возникновения конфликта во время переноса коммитов.
Также мы познакомились с интерактивным вариантом git rebase , включающемся с помощью опции -i , в разделе Изменение сообщений нескольких коммитов главы 7.
git revert
Команда git revert — полная противоположность git cherry-pick . Она создаёт новый коммит, который вносит изменения, противоположные указанному коммиту, по существу отменяя его.
Мы использовали её в разделе Отмена коммита главы 7 чтобы отменить коммит слияния (merge commit).