Перейти к содержимому

Rebase git что это

  • автор:

Введение в Git Merge и Git Rebase: зачем и когда их использовать

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

image

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

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

Git Merge

image

Слияние — обычная практика для разработчиков, использующих системы контроля версий. Независимо от того, созданы ли ветки для тестирования, исправления ошибок или по другим причинам, слияние фиксирует изменения в другом месте. Слияние принимает содержимое ветки источника и объединяет их с целевой веткой. В этом процессе изменяется только целевая ветка. История исходных веток остается неизменной.

Плюсы:

  • простота;
  • сохраняет полную историю и хронологический порядок;
  • поддерживает контекст ветки.
  • история коммитов может быть заполнена (загрязнена) множеством коммитов;
  • отладка с использованием git bisect может стать сложнее.

Слейте ветку master в ветку feature, используя команды checkout и merge.

$ git checkout feature $ git merge master (or) $ git merge master feature

Это создаст новый «Merge commit» в ветке feature, который содержит историю обеих веток.

Git Rebase

Rebase — еще один способ перенести изменения из одной ветки в другую. Rebase сжимает все изменения в один «патч». Затем он интегрирует патч в целевую ветку.

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

image

  • Упрощает потенциально сложную историю
  • Упрощение манипуляций с единственным коммитом
  • Избежание слияния коммитов в занятых репозиториях и ветках
  • Очищает промежуточные коммиты, делая их одним коммитом, что полезно для 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, и так далее.

image

Какой из них использовать?

Так что же лучше? Что рекомендуют эксперты?

Трудно принять единственно правильное решение о том, что лучше использовать, поскольку все команды разные. Всё зависит от потребностей и традиций внутри команды.

Принимайте решения на основании компетенции команды в 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)

Поставлено две задачи:

  1. Поменять местами коммиты qk01ru3 и 4kq5jn2;
  2. исправить ошибку в комментарии четвертого коммита (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 

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

  1. Для того чтобы поменять коммиты местами, мы просто меняем местами их строчки.
  2. Чтобы исправить ошибку в комментарии, мы меняем команду “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 перезаписывает историю, в процессе изменяются хеши коммитов, а это может привести к конфликтам в работе с веткой у других членов команды. Поэтому, если вы работаете над тематической веткой не одни, стоит прибегнуть к нескольким правилам для предотвращения возможных проблем.

  1. Синхронизировать изменения. Перед тем как вы будете заливать свой код на тот же GitHub, выполните git pull изменений, чтобы избежать конфликтных ситуаций.
  2. Не перебазировать давно созданные ветки. Количество шагов в rebase равно количеству коммитов на перебазируемой ветке, если не указаны иные опции. Поэтому с увеличением количества неперебазированных коммитов, растет и вероятность появления конфликта.
  3. Чтобы внедрить изменения в мастер, стоит создать свою локальную ветку и перебазировать ее поверх origin/master. Тогда останется лишь сделать перемотку или бесконфликтное слияние для владельца.
  4. Не проводить 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 для работы с кодом.

  1. 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).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *