git-rebase
Название
git-rebase — повторное применение коммитов поверх вершины другой базовой ветки
Краткое описание
git rebase [-i | --interactive] [<options>] [--exec <cmd>]
[--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
--root [<branch>]
git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch) Описание
Перенесите последовательность коммитов на другую исходную точку. Также можно использовать git rebase, чтобы изменить порядок коммитов или объединить их: см. раздел «ИНТЕРАКТИВНЫЙ РЕЖИМ» ниже.
Например, представьте, что вы работали над веткой topic в этой истории и хотите «синхронизироваться» с изменениями, внесёнными в ветку master.
A---B---C topic
/
D---E---F---G master Вы хотите перенести коммиты, созданные вами в ветке topic после её ответвления от master (то есть A, B и C), поверх текущей ветки master. Это можно сделать, выполнив команду git rebase master, когда выбрана ветка topic. Если вы хотите перебазировать topic, находясь в другой ветке, команда git rebase master topic является сокращением для git checkout topic && git rebase master.
A'--B'--C' topic
/
D---E---F---G master Если в ходе этого процесса возникнет конфликт слияния, git rebase остановится на первом проблемном коммите и оставит маркеры конфликта. В этом случае можно сделать одно из следующего:
-
Разрешить конфликт. Можно использовать
gitdiff, чтобы найти маркеры (<<<<<<) и внести изменения для разрешения конфликта. Для каждого изменённого файла нужно сообщить Git, что конфликт разрешён. Отметить конфликт как разрешённый можно с помощью командыgitadd<filename>. После разрешения всех конфликтов можно продолжить перебазирование командойgit rebase --continue
-
Остановить
gitrebaseи вернуть ветку в исходное состояние командойgit rebase --abort
-
Пропустить коммит, вызвавший конфликт слияния, командой
git rebase --skip
Если при перебазировании не указать <upstream>, будет использована вышестоящая ветка, настроенная с помощью параметров branch.<name>.remote и branch.<name>.merge (подробности см. в git-config[1]), а параметр --fork-point считается заданным. Если вы сейчас не находитесь ни в одной ветке или для текущей ветки не настроена вышестоящая ветка, перебазирование будет прервано.
Ниже приведено упрощённое описание того, что делает git rebase <upstream>:
-
Составить список всех коммитов текущей ветки, созданных после её ответвления от <upstream>, для которых нет эквивалентного коммита в <upstream>.
-
Переключиться на <upstream> с помощью команды, эквивалентной
gitcheckout--detach<upstream>. -
Повторно применить коммиты по одному, в заданном порядке. Это похоже на выполнение команды
gitcherry-pick<commit> для каждого коммита. Об обработке слияний см. раздел «ПЕРЕБАЗИРОВАНИЕ СЛИЯНИЙ». -
Обновить указатель ветки, чтобы он указывал на последний коммит, с помощью команды, эквивалентной
gitcheckout-B<branch>.
| Примечание | При запуске перебазирования ORIG_HEAD указывает на коммит в вершине ветки, которую предстоит перебазировать. Однако не гарантируется, что в конце перебазирования ORIG_HEAD по-прежнему будет указывать на этот коммит, если во время перебазирования используются другие команды, изменяющие ORIG_HEAD (например, git reset). Тем не менее прежняя вершина ветки доступна через журнал ссылок текущей ветки (то есть @{1}; см. gitrevisions[7]). |
Перенос тематической ветки с помощью --onto
Ниже описано, как перенести тематическую ветку, основанную на одной ветке, на другую, создав видимость того, что тематическая ветка была ответвлена от второй ветки; для этого используется rebase --onto.
Сначала предположим, что ваша topic основана на ветке next. Например, функция, разработанная в topic, зависит от некоторой функциональности, имеющейся в next.
o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topic Мы хотим, чтобы topic была ответвлена от ветки master; например, потому что функциональность, от которой зависит topic, была влита в более стабильную ветку master. Мы хотим получить такую структуру дерева:
o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o next Этого можно добиться следующей командой:
git rebase --onto master next topic
Ещё один пример использования параметра --onto — перебазирование части ветки. Допустим, имеется следующая ситуация:
H---I---J topicB
/
E---F---G topicA
/
A---B---C---D master тогда команда
git rebase --onto master topicA topicB
даст следующий результат:
H'--I'--J' topicB
/
| E---F---G topicA
|/
A---B---C---D master Это полезно, если topicB не зависит от topicA.
При перебазировании также можно удалить диапазон коммитов. Допустим, имеется следующая ситуация:
E---F---G---H---I---J topicA
тогда команда
git rebase --onto topicA~5 topicA~3 topicA
приведёт к удалению коммитов F и G:
E---H'---I'---J' topicA
Это полезно, если F и G были ошибочными или не должны входить в topicA. Обратите внимание, что аргумент --onto и параметр <upstream> могут быть любым допустимым идентификатором коммита.
Параметры режима
Параметры в этом разделе нельзя использовать вместе с какими-либо другими параметрами, в том числе друг с другом:
- --continue
-
Продолжить процесс перебазирования после разрешения конфликта слияния.
- --skip
-
Продолжить процесс перебазирования, пропустив текущий патч.
- --abort
-
Прервать операцию перебазирования и сбросить HEAD к исходной ветке. Если при запуске операции перебазирования была указана <branch>, то
HEADбудет сброшена к <branch>. В противном случаеHEADбудет сброшена к состоянию на момент запуска операции перебазирования. - --quit
-
Прервать операцию перебазирования, не сбрасывая
HEADк исходной ветке. Индекс и рабочее дерево также останутся без изменений. Если с помощью--autostashбыла создана временная запись в stash, она будет сохранена в списке stash. - --edit-todo
-
Изменить список todo во время интерактивного перебазирования.
- --show-current-patch
-
Показать текущий патч при интерактивном перебазировании или если перебазирование остановлено из-за конфликтов. Эквивалент команды
gitshowREBASE_HEAD.
Параметры
- --onto <newbase>
-
Начальная точка, от которой создаются новые коммиты. Если параметр
--ontoне указан, начальной точкой является <upstream>. Это может быть любой допустимый коммит, а не только имя существующей ветки.В качестве особого случая можно использовать «A...B» как сокращение для базового коммита слияния A и B, если такой коммит ровно один. Можно опустить не более одного из A и B; в этом случае по умолчанию используется HEAD.
Примеры см. выше в разделе ПЕРЕНОС ТЕМАТИЧЕСКОЙ ВЕТКИ С ПОМОЩЬЮ --ONTO.
- --keep-base
-
Задать начальной точкой для создания новых коммитов базовый коммит слияния <upstream> и <branch>. Выполнение команды
gitrebase--keep-base<upstream> <branch> эквивалентно выполнению командыgitrebase--reapply-cherry-picks--no-fork-point--onto<upstream>...<branch> <upstream> <branch>.Этот параметр полезен, если вы разрабатываете функцию поверх upstream-ветки. Пока ведётся работа над функцией, upstream-ветка может продвинуться; в таком случае, возможно, лучше не выполнять перебазирование поверх upstream-ветки, а оставить базовый коммит неизменным. Поскольку базовый коммит не меняется, этот параметр подразумевает
--reapply-cherry-picks, чтобы избежать потери коммитов.Хотя этот параметр и
--fork-pointнаходят базовый коммит слияния между <upstream> и <branch>, этот параметр использует базовый коммит слияния в качествеstarting point, поверх которого будут создаваться новые коммиты, тогда как--fork-pointиспользует базовый коммит слияния для определенияset of commits, которые будут перебазированы.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- <upstream>
-
Upstream-ветка для сравнения. Это может быть любой допустимый коммит, а не только имя существующей ветки. По умолчанию используется настроенная upstream-ветка текущей ветки.
- <branch>
-
Рабочая ветка; по умолчанию используется
HEAD. - --apply
-
Использовать стратегию применения патчей для перебазирования (внутренний вызов
git-am). В будущем этот параметр может стать пустой операцией, когда механизм слияния будет выполнять всё то же, что и механизм применения патчей.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- --empty=(drop|keep|stop)
-
Как поступать с коммитами, которые изначально не пусты и не являются точными копиями каких-либо upstream-коммитов, но становятся пустыми после перебазирования (поскольку содержат подмножество изменений, уже внесённых в upstream-ветку):
-
drop -
Коммит будет отброшен. Это поведение по умолчанию.
-
keep -
Коммит будет сохранён. Этот параметр подразумевается, если указан
--exec, если только не указан также-i/--interactive. -
stop -
ask -
Перебазирование остановится при применении коммита, чтобы вы могли выбрать: отбросить его, дополнительно отредактировать файлы или просто создать коммит с пустыми изменениями. Этот параметр подразумевается, если указан
-i/--interactive.ask— устаревший синонимstop.
Обратите внимание: коммиты, изначально пустые, сохраняются (если не указан
--no-keep-empty), а коммиты, являющиеся точными копиями (определяется с помощьюgitlog--cherry-mark...), выявляются и отбрасываются на предварительном этапе (если не передан параметр--reapply-cherry-picksили--keep-base).См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
-
- --no-keep-empty
- --keep-empty
-
Не сохранять в результате коммиты, изначально пустые до перебазирования (то есть не изменяющие ничего по сравнению с родительским коммитом). По умолчанию изначально пустые коммиты сохраняются, поскольку для их создания необходимо передать в
gitcommitпереопределяющий флаг--allow-empty, что означает, что пользователь намеренно создаёт такой коммит и поэтому хочет его сохранить.Этот флаг, вероятно, будет использоваться редко: от коммитов, изначально пустых, можно избавиться, запустив интерактивное перебазирование и удалив строки, соответствующие ненужным коммитам. Флаг служит удобным сокращением, например, в случаях, когда внешние инструменты создают множество пустых коммитов, от которых требуется избавиться.
О коммитах, которые изначально не пусты, но становятся пустыми после перебазирования, см. описание флага
--empty.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- --reapply-cherry-picks
- --no-reapply-cherry-picks
-
Повторно применить все точные копии каких-либо upstream-коммитов, а не отбрасывать их заранее. (Если после перебазирования эти коммиты станут пустыми, поскольку содержат подмножество изменений, уже внесённых в upstream-ветку, их обработка будет определяться флагом
--empty.)Если
--keep-baseне указан (или указан--no-reapply-cherry-picks), эти коммиты будут отброшены автоматически. Для этого необходимо прочитать все upstream-коммиты, что может быть затратным в репозиториях с большим количеством upstream-коммитов. При использовании механизмаmergeдля каждого отброшенного коммита будет выведено предупреждение (если не указан--quiet). Также будут выводиться рекомендации, если для параметраadvice.skippedCherryPicksне задано значение false (см. git-config[1]).--reapply-cherry-picksпозволяет перебазированию не читать все upstream-коммиты, что потенциально повышает производительность.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- --allow-empty-message
-
Ничего не делает. Раньше перебазирование коммитов с пустым сообщением завершалось ошибкой, и этот параметр позволял переопределить такое поведение, разрешая перебазирование коммитов с пустыми сообщениями. Теперь коммиты с пустыми сообщениями не приводят к остановке перебазирования.
См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- -m
- --merge
-
Использовать стратегии слияния для перебазирования (по умолчанию).
Обратите внимание: слияние при перебазировании выполняется путём повторного применения каждого коммита рабочей ветки поверх ветки <upstream>. Поэтому при конфликте слияния стороной
oursсчитается уже перебазированная к этому моменту последовательность, начинающаяся с <upstream>, а сторонойtheirs— рабочая ветка. Другими словами, стороны меняются местами.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- -s <strategy>
- --strategy=<strategy>
-
Использовать указанную стратегию слияния вместо стратегии по умолчанию
ort. Это подразумевает--merge.Поскольку
gitrebaseповторно применяет каждый коммит рабочей ветки поверх ветки <upstream> с использованием указанной стратегии, использование стратегииoursпросто удалит все патчи из ветки <branch>, что лишено смысла.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- -X <strategy-option>
- --strategy-option=<strategy-option>
-
Передать <strategy-option> стратегии слияния. Это подразумевает
--merge, а если стратегия не указана —-sort. Обратите внимание на перестановкуoursиtheirs, описанную выше для параметра-m.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
-
--rerere-autoupdate -
--no-rerere-autoupdate -
После того как механизм rerere повторно использует сохранённое разрешение текущего конфликта для обновления файлов в рабочем дереве, разрешить ему также обновить индекс результатом разрешения конфликта. Параметр
--no-rerere-autoupdateпозволяет перепроверить результат работы git-rerere[1] и выявить возможные ошибки слияния, прежде чем отдельной командой git-add[1] добавить результат в индекс. - -S[<keyid>]
- --gpg-sign[=<keyid>]
- --no-gpg-sign
-
Подписывать коммиты с помощью GPG. Аргумент
keyidнеобязателен; по умолчанию используется идентификатор автора коммита. Если он указан, его следует указывать сразу после параметра, без пробела. Параметр--no-gpg-signполезен для отмены действия как переменной конфигурацииcommit.gpgSign, так и ранее заданного параметра--gpg-sign. - -q
- --quiet
-
Не выводить сообщения. Подразумевает
--no-stat. - -v
- --verbose
-
Выводить подробные сообщения. Подразумевает
--stat. - --stat
-
Показывать статистику различий между текущим состоянием и upstream-веткой после последнего перебазирования. Вывод статистики также управляется параметром конфигурации rebase.stat.
- -n
- --no-stat
-
Не показывать статистику различий в процессе перебазирования.
- --no-verify
-
Этот параметр отключает хук pre-rebase. См. также githooks[5].
- --verify
-
Разрешить запуск хука pre-rebase; это поведение используется по умолчанию. Этот параметр можно использовать для переопределения
--no-verify. См. также githooks[5]. - -C<n>
-
Убедиться, что перед каждым изменением и после него совпадает не менее <n> строк окружающего контекста. Если строк окружающего контекста меньше, должны совпадать все они. По умолчанию контекст не игнорируется. Подразумевает
--apply.См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- --no-ff
- --force-rebase
- -f
-
Повторно применять каждый перебазируемый коммит по отдельности, вместо того чтобы выполнять перемотку вперёд для неизменённых коммитов. Это гарантирует, что вся история перебазированной ветки будет состоять из новых коммитов.
Этот параметр может быть полезен после отмены слияния тематической ветки: он заново создаёт тематическую ветку с новыми коммитами, благодаря чему её можно успешно слить повторно без необходимости «отменять отмену» (подробности см. в руководстве по отмене ошибочного слияния).
- --fork-point
- --no-fork-point
-
Используйте reflog, чтобы найти более подходящего общего предка для <upstream> и <branch> при определении коммитов, добавленных в <branch>.
Если активен параметр
--fork-point, для вычисления набора коммитов, подлежащих перебазированию, вместо <upstream> будет использоватьсяfork_point, гдеfork_point— результат выполнения командыgitmerge-base--fork-point<upstream> <branch> (см. git-merge-base[1]). Если в итогеfork_pointокажется пустым, в качестве запасного варианта будет использоваться <upstream>.Если <upstream> или
--keep-baseуказан в командной строке, значением по умолчанию будет--no-fork-point, в противном случае значением по умолчанию будет--fork-point. См. такжеrebase.forkpointв git-config[1].Если ваша ветка была основана на <upstream>, но <upstream> была перемотана назад, а ваша ветка содержит коммиты, которые были удалены, этот параметр можно использовать с
--keep-base, чтобы удалить эти коммиты из вашей ветки.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --ignore-whitespace
-
Игнорировать различия в пробелах при попытке согласовать изменения. В настоящее время каждый бэкенд реализует приблизительное поведение:
- бэкенд apply
-
При применении патча игнорировать изменения в пробелах в контекстных строках. К сожалению, это означает, что если «старые» строки, заменяемые патчем, отличаются от существующего файла только пробелами, вместо успешного применения патча возникнет конфликт слияния.
- бэкенд merge
-
При слиянии считать строки, отличающиеся только пробелами, неизменёнными. К сожалению, это означает, что любые фрагменты патча, предназначенные для изменения только пробелов, будут отброшены, даже если в другой ветке не было конфликтующих изменений.
- --whitespace=<option>
-
Этот флаг передаётся программе
gitapply, применяющей патч (см. git-apply[1]). Подразумевает--apply.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --committer-date-is-author-date
-
Вместо текущего времени использовать в качестве даты коммиттера дату автора перебазируемого коммита. Этот параметр подразумевает
--force-rebase.ПредупреждениеМеханизм обхода истории предполагает, что временные метки коммитов не убывают. Подумайте, действительно ли вам нужно использовать этот параметр. Его следует использовать для переопределения даты коммиттера только при перебазировании коммитов на основу, коммит которой старше (по дате коммита), чем самый старый применяемый коммит (по дате автора). - --ignore-date
- --reset-author-date
-
Вместо даты автора исходного коммита использовать текущее время в качестве даты автора перебазированного коммита. Этот параметр подразумевает
--force-rebase.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --signoff
-
Добавить трейлер
Signed-off-byко всем перебазированным коммитам. Обратите внимание: если указан параметр--interactive, трейлер будет добавлен только к коммитам, помеченным для выбора, редактирования или изменения сообщения.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --trailer=<trailer>
-
Добавить указанный трейлер к сообщению каждого перебазированного коммита, обработав его с помощью git-interpret-trailers[1]. Этот параметр подразумевает
--force-rebase.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- -i
- --interactive
-
Составить список коммитов, которые предстоит перебазировать. Перед перебазированием предоставить пользователю возможность отредактировать этот список. Этот режим также можно использовать для разделения коммитов (см. раздел «РАЗДЕЛЕНИЕ КОММИТОВ» ниже).
Формат списка коммитов можно изменить, задав параметр конфигурации rebase.instructionFormat. К началу пользовательского формата инструкции автоматически добавляется хеш коммита.
См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- -r
- --rebase-merges[=(rebase-cousins|no-rebase-cousins)]
- --no-rebase-merges
-
По умолчанию при перебазировании коммиты слияния просто исключаются из списка задач, а перебазированные коммиты помещаются в одну линейную ветку. При использовании
--rebase-mergesперебазирование будет пытаться сохранить структуру ветвления среди коммитов, подлежащих перебазированию, заново создавая коммиты слияния. Все разрешённые конфликты слияния или внесённые вручную изменения в этих коммитах слияния придётся разрешить или применить повторно вручную. Параметр--no-rebase-mergesможно использовать для отмены действия как параметра конфигурацииrebase.rebaseMerges, так и ранее заданного параметра--rebase-merges.При перебазировании слияний предусмотрено два режима:
rebase-cousinsиno-rebase-cousins. Если режим не указан, по умолчанию используетсяno-rebase-cousins. В режимеno-rebase-cousinsкоммиты, у которых <upstream> не является непосредственным предком, сохранят исходную точку ответвления; то есть коммиты, которые исключил бы параметр--ancestry-pathкоманды git-log[1], по умолчанию сохранят исходную историю предков. В режимеrebase-cousinsтакие коммиты вместо этого перебазируются на <upstream> (или на <onto>, если он указан).В настоящее время воссоздать коммиты слияния можно только с помощью стратегии слияния
ort; другие стратегии слияния можно использовать только с помощью явных командexecgitmerge-s<strategy> [...].См. также разделы «ПЕРЕБАЗИРОВАНИЕ СЛИЯНИЙ» и «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- -x <cmd>
- --exec <cmd>
-
Добавлять «exec <cmd>» после каждой строки, создающей коммит в итоговой истории. <cmd> будет интерпретироваться как одна или несколько команд оболочки. При сбое любой команды перебазирование будет прервано с кодом завершения 1.
Можно выполнить несколько команд, указав их в одном экземпляре
--exec:git rebase -i --exec "cmd1 && cmd2 && ..."
или указав несколько параметров
--exec:git rebase -i --exec "cmd1" --exec "cmd2" --exec ...
Если используется
--autosquash, строкиexecне будут добавляться для промежуточных коммитов и появятся только в конце каждой серии squash/fixup.Внутри используется механизм
--interactive, но его можно запускать и без явного--interactive.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --root
-
Перебазировать все коммиты, достижимые из <branch>, не ограничивая их параметром <upstream>. Это позволяет перебазировать корневые коммиты ветки.
См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --autosquash
- --no-autosquash
-
Автоматически объединять коммиты со специально оформленными сообщениями с предыдущими перебазируемыми коммитами. Если сообщение коммита начинается с «squash! », «fixup! » или «amend! », оставшаяся часть заголовка рассматривается как указатель коммита. Она сопоставляется с предыдущим коммитом по заголовку или хешу этого коммита. Если полного совпадения нет, рассматриваются совпадения, при которых указатель совпадает с началом заголовка коммита.
В списке задач перебазирования действия для коммитов squash, fixup и amend изменяются с
pickнаsquash,fixupилиfixup-Cсоответственно, а сами коммиты перемещаются сразу после изменяемого ими коммита. Параметр--interactiveпозволяет проверить и отредактировать список задач перед продолжением.Рекомендуемый способ создавать коммиты с маркерами squash — использовать параметры
--squash,--fixup,--fixup=amend:или--fixup=reword:команды git-commit[1]. Они принимают целевой коммит в качестве аргумента и автоматически подставляют его заголовок в новый коммит.Если установить для переменной конфигурации
rebase.autoSquashзначение true, автоматическое объединение по умолчанию будет включено для интерактивного перебазирования. Параметр--no-autosquashпозволяет переопределить эту настройку.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
- --autostash
- --no-autostash
-
Автоматически создать временную запись stash перед началом операции и применить её после завершения операции. Это позволяет запускать перебазирование в рабочем дереве с незакоммиченными изменениями. Однако используйте этот параметр осторожно: применение stash после успешного перебазирования может привести к сложным конфликтам.
- --reschedule-failed-exec
- --no-reschedule-failed-exec
-
Автоматически повторно ставить в очередь команды
exec, завершившиеся с ошибкой. Это имеет смысл только в интерактивном режиме (или если был указан параметр--exec).Этот параметр применяется после начала перебазирования. Его значение сохраняется на протяжении всего перебазирования и определяется в следующем порядке: параметр командной строки, указанный при первоначальном вызове
gitrebase, настройкаrebase.rescheduleFailedExec(см. git-config[1] или раздел «КОНФИГУРАЦИЯ» ниже) либо значение false по умолчанию.Сохранение этого параметра на протяжении всего перебазирования — это удобная возможность. Иначе явный параметр
--no-reschedule-failed-exec, указанный в начале, был бы переопределён настройкойrebase.rescheduleFailedExec=trueпри вызовеgitrebase--continue. В настоящее время нельзя передать--[no-]reschedule-failed-execкомандеgitrebase--continue. - --update-refs
- --no-update-refs
-
Автоматически принудительно обновлять любые ветки, указывающие на перебазируемые коммиты. Ветки, выбранные в рабочем дереве, таким образом не обновляются.
Если для переменной конфигурации
rebase.updateRefsзадано значение, этот параметр можно использовать, чтобы переопределить и отключить эту настройку.См. также раздел «НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ» ниже.
Несовместимые параметры
Следующие параметры:
-
--apply
-
--whitespace
-
-C
несовместимы со следующими параметрами:
-
--merge
-
--strategy
-
--strategy-option
-
--autosquash
-
--rebase-merges
-
--interactive
-
--exec
-
--no-keep-empty
-
--empty=
-
--[no-]reapply-cherry-picks при использовании без --keep-base
-
--update-refs
-
--root при использовании без --onto
-
--trailer
Кроме того, следующие пары параметров несовместимы:
-
--keep-base и --onto
-
--keep-base и --root
-
--fork-point и --root
Различия в поведении
git rebase имеет две основные серверные части: apply и merge. (Ранее серверная часть apply называлась серверной частью am, однако это название вводило в заблуждение, поскольку похоже на глагол, а не на существительное. Также серверная часть merge ранее называлась интерактивной серверной частью, но теперь используется и в неинтерактивных случаях. Обе были переименованы в соответствии с низкоуровневой функциональностью, на которой основана каждая из них.) В поведении этих двух серверных частей есть некоторые тонкие различия:
Пустые коммиты
К сожалению, серверная часть apply отбрасывает намеренно пустые коммиты, то есть коммиты, изначально не содержащие изменений, хотя на практике такие коммиты встречаются редко. Она также отбрасывает коммиты, которые становятся пустыми, и не предоставляет возможности управлять этим поведением.
Серверная часть merge по умолчанию сохраняет намеренно пустые коммиты (однако с -i они помечаются как пустые в редакторе списка операций либо автоматически отбрасываются с помощью --no-keep-empty).
Как и серверная часть apply, серверная часть merge по умолчанию отбрасывает коммиты, которые становятся пустыми, если не указан параметр -i/--interactive (в этом случае она останавливается и спрашивает пользователя, что делать). Серверная часть merge также имеет параметр --empty=(drop|keep|stop), позволяющий изменить обработку коммитов, которые становятся пустыми.
Обнаружение переименования каталогов
Из-за отсутствия точной информации о дереве (возникающего при создании фиктивных предков на основе ограниченной информации, доступной в патчах) в серверной части apply отключено обнаружение переименования каталогов. Отключение обнаружения переименования каталогов означает, что если одна сторона истории переименовывает каталог, а другая добавляет новые файлы в старый каталог, новые файлы останутся в старом каталоге без каких-либо предупреждений во время перебазирования о том, что, возможно, следует переместить эти файлы в новый каталог.
Серверная часть merge поддерживает обнаружение переименования каталогов и предупреждает вас в таких случаях.
Контекст
Серверная часть apply работает, создавая последовательность патчей (внутренне вызывая format-patch), а затем последовательно применяя эти патчи (внутренне вызывая am). Патчи состоят из нескольких фрагментов, каждый из которых содержит номера строк, контекстную область и собственно изменения. Номера строк необходимо корректировать с учетом смещения, поскольку другая сторона, вероятно, вставила или удалила строки ранее в файле. Контекстная область предназначена для того, чтобы помочь определить, как скорректировать номера строк и применить изменения к нужным строкам. Однако если в нескольких областях кода окружающие строки контекста совпадают, может быть выбрана не та область. Известны реальные случаи, когда из-за этого коммиты повторно применялись неверно, при этом конфликты не сообщались. Установка для diff.context большего значения может предотвратить подобные проблемы, но повышает вероятность ложных конфликтов (поскольку для применения потребуется совпадение большего числа строк контекста).
Серверная часть merge работает с полной копией каждого соответствующего файла, что исключает подобные проблемы.
Подписи маркеров конфликтов
При возникновении конфликтов содержимого механизм слияния пытается снабдить маркеры конфликта для каждой стороны аннотациями, указывающими коммиты, из которых взято содержимое. Поскольку серверная часть apply отбрасывает исходную информацию о перебазируемых коммитах и их родителях (и вместо этого создает новые фиктивные коммиты на основе ограниченной информации из сгенерированных патчей), определить эти коммиты невозможно; вместо этого приходится использовать сводку коммита. Кроме того, если для merge.conflictStyle задано значение diff3 или zdiff3, серверная часть apply будет использовать подпись «созданная база слияния» для содержимого из базы слияния и, таким образом, не предоставит никакой информации о коммите базы слияния.
Серверная часть merge работает с полными коммитами обеих сторон истории, поэтому таких ограничений у нее нет.
Хуки
Серверная часть apply традиционно не вызывала хук post-commit, тогда как серверная часть merge вызывала его. Обе вызывали хук post-checkout, однако серверная часть merge подавляла его вывод. Кроме того, обе серверные части вызывают хук post-checkout только для коммита, с которого начинается перебазирование, но не для промежуточных или конечного коммитов. В каждом случае вызов этих хуков был следствием особенностей реализации, а не результатом намеренного проектирования (обе серверные части изначально были реализованы как скрипты оболочки и случайно вызывали другие команды, например git checkout или git commit, которые вызывали хуки). Поведение обеих серверных частей должно быть одинаковым, хотя не совсем ясно, какое именно поведение, если таковое вообще есть, является правильным. Вероятно, в будущем команда rebase перестанет вызывать любой из этих хуков.
Обработка прерываний
У серверной части apply возникают проблемы с безопасностью при прерывании в неподходящий момент: если пользователь нажмет Ctrl-C не вовремя, пытаясь отменить перебазирование, перебазирование может перейти в состояние, из которого его невозможно отменить последующей командой git rebase --abort. По-видимому, у серверной части merge такого недостатка нет. (Подробности см. на странице https://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/.)
Изменение сообщения коммита
Если во время перебазирования возникает конфликт, перебазирование останавливается и предлагает пользователю разрешить его. Поскольку при разрешении конфликтов пользователю может потребоваться внести существенные изменения, после разрешения конфликтов и выполнения команды git rebase --continue перебазирование должно открыть редактор и предложить пользователю обновить сообщение коммита. Серверная часть merge делает это, а серверная часть apply без изменений использует исходное сообщение коммита.
Прочие различия
Есть и несколько других различий в поведении, которые большинство, вероятно, сочтет несущественными, но для полноты картины они перечислены ниже:
-
Журнал ссылок: две серверные части используют разные формулировки для описания изменений в журнале ссылок, хотя обе употребляют слово «rebase».
-
Сообщения о ходе выполнения, информационные сообщения и сообщения об ошибках: две серверные части выводят несколько различающиеся сообщения о ходе выполнения и информационные сообщения. Кроме того, серверная часть apply выводит сообщения об ошибках (например, «Ваши файлы будут перезаписаны…») в stdout, а серверная часть merge — в stderr.
-
Каталоги состояния: две серверные части хранят состояние в разных каталогах внутри
.git/
Стратегии слияния
Механизм слияния (команды git merge и git pull) позволяет выбрать серверную часть merge strategies с помощью параметра -s. Некоторые стратегии также принимают собственные параметры, которые можно передать, задав аргументы -X<option> для команд git merge и/или git pull.
-
ort -
Это стратегия слияния по умолчанию при извлечении или слиянии одной ветки. Эта стратегия может разрешать конфликты только между двумя вершинами с помощью алгоритма трёхстороннего слияния. Если для трёхстороннего слияния можно использовать несколько общих предков, она создаёт объединённое дерево общих предков и использует его в качестве опорного дерева для трёхстороннего слияния. Согласно проверкам, выполненным на реальных коммитах слияния из истории разработки ядра Linux 2.6, это позволяет уменьшить количество конфликтов слияния, не вызывая ошибочных слияний. Кроме того, эта стратегия может обнаруживать и обрабатывать слияния с переименованиями. Обнаруженные копии не используются. Название этого алгоритма — акроним («Ostensibly Recursive’s Twin», «якобы двойник рекурсивной») — связано с тем, что он был написан на замену предыдущему алгоритму по умолчанию,
recursive.Если путь относится к подмодулю, и коммит подмодуля, используемый с одной стороны слияния, является потомком коммита подмодуля, используемого с другой стороны, Git пытается выполнить перемотку вперёд до коммита-потомка. В противном случае Git рассматривает этот случай как конфликт и предлагает в качестве решения коммит подмодуля, являющийся потомком конфликтующих коммитов, если такой существует.
Стратегия
ortможет принимать следующие параметры:-
ours -
Этот параметр принудительно разрешает конфликтующие фрагменты, выбирая версию
our. Изменения из другого дерева, не конфликтующие с нашей стороной, отражаются в результате слияния. Для двоичного файла берётся всё содержимое с нашей стороны.Не следует путать этот параметр со стратегией слияния
ours, которая вообще не проверяет содержимое другого дерева. Она отбрасывает все изменения, внесённые в другое дерево, объявляя, что историяourсодержит всё, что в нём произошло. -
theirs -
Это противоположность параметра
ours; обратите внимание: в отличие отours, стратегии слиянияtheirsне существует, поэтому её нельзя спутать с этим параметром слияния. -
ignore-space-change -
ignore-all-space -
ignore-space-at-eol -
ignore-cr-at-eol -
Для целей трёхстороннего слияния считает строки с указанным типом изменений пробельных символов неизменёнными. Изменения пробельных символов, смешанные с другими изменениями строки, не игнорируются. См. также git-diff[1]
-b,-w,--ignore-space-at-eolи--ignore-cr-at-eol.-
Если версия
theirвносит в строку только изменения пробельных символов, используется версияour; -
Если версия
ourвносит изменения пробельных символов, но версияtheirсодержит существенное изменение, используется версияtheir; -
В противном случае слияние выполняется обычным образом.
-
-
renormalize -
Выполняет виртуальные извлечение и помещение в индекс для всех трёх состояний каждого файла, которому требуется трёхстороннее слияние. Этот параметр предназначен для слияния веток с различающимися фильтрами очистки или правилами нормализации конца строки. Подробнее см. раздел «Слияние веток с различающимися атрибутами извлечения и помещения в индекс» в gitattributes[5].
-
no-renormalize -
Отключает параметр
renormalize. Этот параметр переопределяет переменную конфигурацииmerge.renormalize. -
find-renames[=<n>] -
Включает обнаружение переименований, при необходимости задавая порог сходства. Это поведение используется по умолчанию. Параметр переопределяет переменную конфигурации
merge.renames. См. также git-diff[1]--find-renames. -
rename-threshold=<n> -
Устаревший синоним для
find-renames=<n>. -
no-renames -
Отключает обнаружение переименований. Параметр переопределяет переменную конфигурации
merge.renames. См. также git-diff[1]--no-renames. -
histogram -
Устаревший синоним для
diff-algorithm=histogram. -
patience -
Устаревший синоним для
diff-algorithm=patience. -
diff-algorithm=(histogram|minimal|myers|patience) -
Использует при слиянии другой алгоритм сравнения, который может помочь избежать ошибочных слияний, возникающих из-за несущественных совпадающих строк (например, фигурных скобок из разных функций). См. также git-diff[1]
--diff-algorithm. Обратите внимание: по умолчаниюortиспользуетdiff-algorithm=histogram, тогда как обычные сравнения в настоящее время используют параметр конфигурацииdiff.algorithm. -
subtree[=<path>] -
Этот параметр представляет собой более сложный вариант стратегии
subtree, в которой стратегия пытается определить, как сдвинуть два дерева, чтобы они совпали при слиянии. Вместо этого указанный путь добавляется в начало (или удаляется из начала), чтобы привести структуру двух деревьев к совпадению.
-
-
recursive -
Теперь это синоним для
ort. До версии v2.49.0 это была альтернативная реализация, но в версии v2.50.0 её переопределили какort. Предыдущая стратегия recursive была стратегией по умолчанию для разрешения конфликтов между двумя вершинами начиная с Git v0.99.9k и до v2.33.0. -
resolve -
Эта стратегия может разрешать конфликты только между двумя вершинами (то есть текущей веткой и другой веткой, из которой вы выполняли извлечение) с помощью алгоритма трёхстороннего слияния. Она пытается тщательно обнаруживать неоднозначности перекрёстных слияний. Переименования не обрабатываются.
-
octopus -
Эта стратегия разрешает случаи с более чем двумя вершинами, но отказывается выполнять сложное слияние, требующее ручного разрешения. Она предназначена главным образом для объединения вершин тематических веток. Это стратегия слияния по умолчанию при извлечении или слиянии более чем одной ветки.
-
ours -
Эта стратегия разрешает любое количество вершин, но результирующее дерево слияния всегда совпадает с деревом текущей вершины ветки, фактически игнорируя все изменения из всех остальных веток. Она предназначена для замены старой истории разработки боковых веток. Обратите внимание: это отличается от параметра
-Xoursстратегии слиянияort. -
subtree -
Это модифицированная стратегия
ort. При слиянии деревьев A и B, если B соответствует поддереву A, дерево B сначала корректируется, чтобы соответствовать структуре дерева A, вместо того чтобы считывать деревья на одном уровне. Такая же корректировка выполняется и для дерева общего предка.
При использовании стратегий, основанных на трёхстороннем слиянии (включая стратегию по умолчанию ort), если изменение внесено в обеих ветках, но затем отменено в одной из них, это изменение будет присутствовать в результате слияния; некоторым такое поведение кажется непонятным. Это происходит потому, что при слиянии учитываются только вершины и база слияния, а не отдельные коммиты. Поэтому алгоритм слияния считает отменённое изменение полным отсутствием изменений и подставляет изменённую версию.
Примечания
Следует понимать последствия использования git rebase в общем репозитории. См. также раздел «ВОССТАНОВЛЕНИЕ ПОСЛЕ ПЕРЕБАЗИРОВАНИЯ ВЫШЕСТОЯЩЕЙ ВЕТКИ» ниже.
При запуске перебазирования сначала будет выполнен хук pre-rebase, если он существует. Этот хук можно использовать для проверки корректности и отмены перебазирования, если оно неуместно. Пример приведён в шаблонном скрипте хука pre-rebase.
По завершении текущей веткой станет <branch>.
Интерактивный режим
Интерактивное перебазирование позволяет редактировать перебазируемые коммиты. Вы можете менять порядок коммитов и удалять их (отсеивая плохие или нежелательные по другим причинам исправления).
Интерактивный режим предназначен для следующего рабочего процесса:
-
придумать замечательную идею
-
поработать над кодом
-
подготовить серию изменений для отправки
-
отправить её
где пункт 2 состоит из нескольких повторений следующих действий
a) обычная работа
-
закончить что-нибудь достойное коммита
-
создать коммит
b) отдельное исправление
-
заметить, что что-то не работает
-
исправить это
-
создать коммит с исправлением
Иногда исправление из пункта b.2 нельзя добавить к не совсем идеальному коммиту, который оно исправляет, потому что этот коммит глубоко спрятан в серии изменений. Именно для этого и нужно интерактивное перебазирование: после множества повторений пунктов «a» и «b» используйте его, чтобы переставить коммиты, отредактировать их и объединить несколько коммитов в один.
Запустите его, указав последний коммит, который нужно оставить без изменений:
git rebase -i <after-this-commit>
Откроется редактор со всеми коммитами текущей ветки (за исключением коммитов слияния), которые следуют за указанным коммитом. Вы можете менять порядок коммитов в этом списке как угодно, а также удалять их. Список выглядит примерно так:
pick deadbee The oneline of this commit pick fa1afe1 The oneline of the next commit ...
Однострочные описания приведены исключительно для вашего удобства; git rebase не обращает на них внимания, а использует имена коммитов («deadbee» и «fa1afe1» в этом примере), поэтому не удаляйте и не редактируйте эти имена.
Заменив команду "pick" на команду "edit", вы можете указать git rebase остановиться после применения этого коммита, чтобы вы могли отредактировать файлы и/или сообщение коммита, изменить коммит и продолжить перебазирование.
Чтобы прервать перебазирование (как при использовании команды "edit", но без предварительного применения какого-либо коммита с помощью cherry-pick), используйте команду "break".
Если вы хотите отредактировать только сообщение коммита, замените команду "pick" на команду "reword".
Чтобы удалить коммит, замените команду "pick" на "drop" или просто удалите соответствующую строку.
Чтобы объединить два или более коммита в один, замените команду "pick" у второго и последующих коммитов на "squash" или "fixup". Если у коммитов были разные авторы, объединённый коммит будет приписан автору первого коммита. Предлагаемое сообщение объединённого коммита составляется путём объединения сообщения первого коммита с сообщениями коммитов, помеченных командой "squash", без сообщений коммитов, помеченных командой "fixup", если не используется "fixup -c". В этом случае предлагается только сообщение коммита "fixup -c", и открывается редактор, в котором можно отредактировать сообщение. Содержимое (исправление) коммита "fixup -c" всё равно включается в объединённый коммит. Если коммитов "fixup -c" несколько, используется сообщение последнего из них. Также можно использовать "fixup -C": он работает так же, как "fixup -c", но редактор не открывается.
git rebase остановится, если команда "pick" заменена на "edit" или если команда завершится с ошибкой слияния. Когда вы закончите редактирование и/или разрешение конфликтов, можно продолжить с помощью git rebase --continue.
Например, если вы хотите изменить порядок последних 5 коммитов так, чтобы то, что раньше было HEAD~4, стало новым HEAD. Для этого вызовите git rebase следующим образом:
$ git rebase -i HEAD~5
И переместите первое исправление в конец списка.
Возможно, вы захотите заново создать коммиты слияния, например, если история выглядит так:
X
\
A---M---B
/
---o---O---P---Q Предположим, вы хотите перебазировать боковую ветку, начинающуюся с "A", на "Q". Убедитесь, что текущий HEAD — это "B", и вызовите
$ git rebase -i -r --onto Q O
Изменение порядка коммитов и их редактирование обычно создаёт непроверенные промежуточные состояния. Чтобы убедиться, что при редактировании истории ничего не сломалось, можно запустить тест или хотя бы повторно скомпилировать проект на промежуточных этапах истории с помощью команды "exec" (сокращение — "x"). Для этого можно создать список задач, например, такой:
pick deadbee Implement feature XXX fixup f1a5c00 Fix to feature XXX exec make pick c0ffeee The oneline of the next commit edit deadbab The oneline of the commit after exec cd subdir; make test ...
Интерактивное перебазирование остановится, если команда завершится с ошибкой (то есть вернёт ненулевой код завершения), чтобы дать вам возможность исправить проблему. Продолжить можно с помощью git rebase --continue.
Команда "exec" запускает команду в оболочке (оболочке по умолчанию, обычно /bin/sh), поэтому можно использовать возможности оболочки (например, "cd", ">", ";" …). Команда выполняется из корня рабочего дерева.
$ git rebase -i --exec "make test"
Эта команда позволяет проверить, что промежуточные коммиты компилируются. Список задач будет выглядеть так:
pick 5928aea one exec make test pick 04d0fda two exec make test pick ba46169 three exec make test pick f4593f9 four exec make test
Разделение коммитов
В интерактивном режиме можно помечать коммиты действием "edit". Однако это не обязательно означает, что git rebase ожидает, что результатом редактирования будет ровно один коммит. На самом деле вы можете отменить коммит или добавить другие коммиты. Это можно использовать, чтобы разделить один коммит на два:
-
Запустите интерактивное перебазирование с помощью
gitrebase-i<commit>^, где <commit> — коммит, который вы хотите разделить. В действительности подойдёт любой диапазон коммитов, если он включает этот коммит. -
Пометьте коммит, который хотите разделить, действием "edit".
-
Когда дойдёт очередь редактировать этот коммит, выполните
gitresetHEAD^. В результатеHEADоткатится на один коммит, и индекс будет приведён в соответствие. Однако рабочее дерево останется без изменений. -
Теперь добавьте в индекс изменения, которые хотите включить в первый коммит. Для этого можно использовать
gitadd(возможно, в интерактивном режиме) илиgitgui(или обе команды). -
Создайте коммит из текущего индекса, используя подходящее на данный момент сообщение коммита.
-
Повторяйте два последних шага, пока рабочее дерево не станет чистым.
-
Продолжите перебазирование с помощью
gitrebase--continue.
Если вы не уверены, что промежуточные ревизии согласованы (собираются, проходят набор тестов и т. д.), используйте git stash, чтобы сохранить ещё не закоммиченные изменения после каждого коммита, протестировать его и изменить коммит, если потребуется исправить ошибки.
Восстановление после перебазирования вышестоящей ветки
Перебазировать (или иным образом переписывать) ветку, на основе которой другие уже ведут работу, — плохая идея: всем, чья работа зависит от этой ветки, придётся вручную исправлять свою историю. В этом разделе объясняется, как это сделать с точки зрения зависимой ветки. Однако правильным решением было бы вообще не перебазировать вышестоящую ветку.
Предположим, что кто-то работает над веткой subsystem, а вы работаете над topic, которая зависит от этой subsystem. История может выглядеть следующим образом:
o---o---o---o---o---o---o---o master
\
o---o---o---o---o subsystem
\
*---*---* topic Если subsystem перебазировать на master, произойдёт следующее:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic Если теперь продолжить разработку как обычно и в итоге объединить topic с subsystem, коммиты из subsystem останутся дубликатами навсегда:
o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
\ /
*---*---*-..........-*--* topic Такие дубликаты обычно не приветствуются, поскольку загромождают историю и затрудняют её чтение. Чтобы навести порядок, нужно перенести коммиты из topic на новую вершину subsystem, то есть перебазировать topic. Это вызывает цепную реакцию: всем, чья работа зависит от topic, тоже придётся выполнить перебазирование, и так далее!
В следующих подразделах рассматриваются два способа исправления:
- Простой случай: изменения в точности совпадают.
-
Такое происходит, если перебазирование
subsystemбыло простым и не сопровождалось конфликтами. - Сложный случай: изменения не совпадают.
-
Такое происходит, если при перебазировании
subsystemвозникали конфликты или использовался--interactiveдля исключения, редактирования, объединения или исправления коммитов; либо если вышестоящая ветка использовала одну из командcommit--amend,resetили такую команду полного переписывания истории, какfilter-repo.
Простой случай
Работает, только если изменения (идентификаторы исправлений, рассчитанные на основе содержимого diff) в subsystem в точности совпадают до и после выполненного subsystem перебазирования.
В этом случае исправление несложно, потому что git rebase умеет пропускать изменения, уже имеющиеся в новой вышестоящей ветке (если не указано --reapply-cherry-picks). Поэтому, если выполнить следующую команду (предполагая, что вы находитесь в topic)
$ git rebase subsystem
получится исправленная история
o---o---o---o---o---o---o---o master
\
o'--o'--o'--o'--o' subsystem
\
*---*---* topic Сложный случай
Ситуация усложняется, если изменения subsystem не полностью соответствуют изменениям до перебазирования.
| Примечание | Иногда восстановление по сценарию «простого случая» кажется успешным даже в сложном случае, но это может привести к нежелательным последствиям. Например, коммит, удалённый с помощью git rebase --interactive, будет восстановлен! |
Идея заключается в том, чтобы вручную указать git rebase, «где закончилась старая subsystem и началась ваша topic», то есть определить старую базу слияния между ними. Нужно найти способ указать последний коммит старой subsystem, например:
-
С помощью журнала ссылок
subsystem: послеgitfetchстарая вершинаsubsystemнаходится вsubsystem@{1}. При последующих загрузках номер будет увеличиваться. (См. git-reflog[1].) -
Относительно вершины
topic: если известно, что вашаtopicсостоит из трёх коммитов, старая вершинаsubsystemдолжна бытьtopic~3.
Затем можно перенести старую subsystem..topic на новую вершину, выполнив следующую команду (для случая с журналом ссылок и при условии, что вы уже находитесь в topic):
$ git rebase --onto subsystem subsystem@{1} Цепная реакция при восстановлении в «сложном случае» особенно неприятна: тем, чья работа зависит от everyone и находится ниже по цепочке, теперь тоже придётся выполнять восстановление в «сложном случае» для topic!
Перебазирование слияний
Команда интерактивного перебазирования изначально предназначалась для обработки отдельных серий патчей. Поэтому имеет смысл исключать коммиты слияния из списка задач: разработчик мог выполнить слияние текущей на тот момент версии master во время работы над веткой, а затем в конечном итоге перебазировать все коммиты на master, пропустив коммиты слияния.
Однако существуют обоснованные причины, по которым разработчик может захотеть воссоздать коммиты слияния: чтобы сохранить структуру веток (или «топологию коммитов») при работе с несколькими взаимосвязанными ветками.
В следующем примере разработчик работает над тематической веткой, в которой рефакторит способ определения кнопок, и над другой тематической веткой, использующей этот рефакторинг для реализации кнопки «Сообщить об ошибке». Результат выполнения git log --graph --format=%s -5 может выглядеть так:
* Merge branch 'report-a-bug' |\ | * Add the feedback button * | Merge branch 'refactor-button' |\ \ | |/ | * Use the Button class for all buttons | * Extract a generic Button class from the DownloadButton one
Разработчик может захотеть перебазировать эти коммиты на более новую версию master, сохранив структуру веток, например, если ожидается, что первая тематическая ветка будет включена в master значительно раньше второй, чтобы разрешить конфликты слияния с изменениями класса DownloadButton, вошедшими в master.
Это перебазирование можно выполнить с помощью параметра --rebase-merges. В результате будет сформирован список задач, выглядящий так:
label onto # Branch: refactor-button reset onto pick 123456 Extract a generic Button class from the DownloadButton one pick 654321 Use the Button class for all buttons label refactor-button # Branch: report-a-bug reset refactor-button # Use the Button class for all buttons pick abcdef Add the feedback button label report-a-bug reset onto merge -C a1b2c3 refactor-button # Merge 'refactor-button' merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'
В отличие от обычного интерактивного перебазирования, помимо команд pick в списке есть команды label, reset и merge.
Команда label связывает метку с текущим HEAD в момент выполнения этой команды. Эти метки создаются как ссылки, локальные для рабочего дерева (refs/rewritten/<label>), и удаляются по завершении перебазирования. Благодаря этому операции перебазирования в нескольких рабочих деревьях, связанных с одним репозиторием, не мешают друг другу. Если команда label завершается с ошибкой, она немедленно добавляется в список повторно с полезным сообщением о дальнейших действиях.
Команда reset сбрасывает HEAD, индекс и рабочее дерево до указанной ревизии. Она похожа на exec git reset --hard <label>, но отказывается перезаписывать неотслеживаемые файлы. Если команда reset завершается с ошибкой, она немедленно добавляется в список повторно с полезным сообщением о том, как отредактировать список задач (обычно это происходит, если команда reset была вручную добавлена в список задач и содержит опечатку).
Команда merge выполнит слияние указанных ревизий с тем, на что в этот момент указывает HEAD. При использовании -C <original-commit> будет использовано сообщение указанного коммита слияния. Если -C изменить на строчную -c, после успешного слияния сообщение откроется в редакторе, чтобы пользователь мог его отредактировать.
Если команда merge завершается с ошибкой по любой причине, кроме конфликтов слияния (то есть операция слияния даже не началась), она немедленно добавляется в список повторно.
По умолчанию команда merge использует стратегию слияния ort для обычных слияний и octopus для слияний типа octopus. При вызове перебазирования можно указать стратегию по умолчанию для всех слияний с помощью аргумента --strategy. Для переопределения стратегии отдельных слияний в интерактивном списке команд можно использовать команду exec, чтобы явно вызвать git merge с аргументом --strategy. Обратите внимание: при явном вызове git merge таким образом можно воспользоваться тем, что метки являются ссылками, локальными для рабочего дерева (например, ссылка refs/rewritten/onto соответствует метке onto), чтобы указать ветки, которые нужно объединить.
Примечание: первая команда (label onto) присваивает метку ревизии, на которую перебазируются коммиты. Название onto — всего лишь условное обозначение, отсылающее к параметру --onto.
Также можно создать совершенно новые коммиты слияния с нуля, добавив команду вида merge <merge-head>. Эта форма сформирует предварительный вариант сообщения коммита и всегда откроет редактор, чтобы пользователь мог его отредактировать. Это может быть полезно, например, когда тематическая ветка оказывается посвящена нескольким задачам и её нужно разделить на две или более тематические ветки. Рассмотрим следующий список задач:
pick 192837 Switch from GNU Makefiles to CMake pick 5a6c7e Document the switch to CMake pick 918273 Fix detection of OpenSSL in CMake pick afbecd http: add support for TLS v1.3 pick fdbaec Fix detection of cURL in CMake on Windows
Единственный коммит в этом списке, не связанный с CMake, вполне мог появиться в ходе работы над исправлением всех ошибок, возникших после перехода на CMake, но он решает другую задачу. Чтобы разделить эту ветку на две тематические ветки, список задач можно отредактировать следующим образом:
label onto pick afbecd http: add support for TLS v1.3 label tlsv1.3 reset onto pick 192837 Switch from GNU Makefiles to CMake pick 918273 Fix detection of OpenSSL in CMake pick fdbaec Fix detection of cURL in CMake on Windows pick 5a6c7e Document the switch to CMake label cmake reset onto merge tlsv1.3 merge cmake
Настройка
Весь текст ниже в этом разделе выборочно включён из документации git-config[1]. Содержимое совпадает с тем, что приведено там:
- rebase.backend
-
Backend по умолчанию для перебазирования. Возможные варианты:
applyилиmerge. В будущем, если backend слияния получит все оставшиеся возможности backend применения патчей, эта настройка может стать ненужной. - rebase.stat
-
Показывать ли diffstat изменений в вышестоящей ветке, появившихся с момента последнего перебазирования. По умолчанию выключено.
- rebase.autoSquash
-
Если установлено значение true, по умолчанию включается параметр
--autosquashкоманды git-rebase[1] в интерактивном режиме. Это можно переопределить параметром--no-autosquash. - rebase.autoStash
-
Если установлено значение true, перед началом операции автоматически создаётся временная запись в stash, а после её завершения она применяется. Это позволяет выполнять перебазирование в грязном рабочем дереве. Однако используйте эту настройку с осторожностью: применение stash после успешного перебазирования может привести к нетривиальным конфликтам. Эту настройку можно переопределить параметрами
--no-autostashи--autostashкоманды git-rebase[1]. По умолчанию выключено. - rebase.updateRefs
-
Если установлено значение true, по умолчанию включается параметр
--update-refs. - rebase.missingCommitsCheck
-
Если установлено значение "warn", git rebase -i выведет предупреждение, если некоторые коммиты удалены (например, если строка была удалена), но перебазирование всё равно продолжится. Если установлено значение "error", будет выведено такое же предупреждение, а перебазирование остановится; затем можно использовать
git rebase --edit-todo, чтобы исправить ошибку. Если установлено значение "ignore", проверка не выполняется. Чтобы удалить коммит без предупреждения или ошибки, используйте командуdropв списке задач. По умолчанию установлено значение "ignore". - rebase.instructionFormat
-
Строка формата, как указано в документации git-log[1], которая используется для списка задач при интерактивном перебазировании. Хеш коммита автоматически добавляется перед указанным форматом.
- rebase.abbreviateCommands
-
Если установлено значение true, команда
gitrebaseбудет использовать в списке задач сокращённые имена команд, например:p deadbee The oneline of the commit p fa1afe1 The oneline of the next commit ...вместо:
pick deadbee The oneline of the commit pick fa1afe1 The oneline of the next commit ...По умолчанию выключено.
- rebase.rescheduleFailedExec
-
Автоматически повторно добавлять в список команды
exec, завершившиеся с ошибкой. Это имеет смысл только в интерактивном режиме (или если указан параметр--exec). Это то же самое, что указать параметр--reschedule-failed-exec. - rebase.forkPoint
-
Если установлено значение false, по умолчанию устанавливается параметр
--no-fork-point. - rebase.rebaseMerges
-
Определяет, следует ли устанавливать параметр
--rebase-mergesпо умолчанию и каким образом. Возможные значения:rebase-cousins,no-rebase-cousinsили логическое значение. Значение true илиno-rebase-cousinsэквивалентно--rebase-merges=no-rebase-cousins, значениеrebase-cousinsэквивалентно--rebase-merges=rebase-cousins, а значение false эквивалентно--no-rebase-merges. Передача--rebase-mergesв командной строке, с аргументом или без него, переопределяет любую настройкуrebase.rebaseMerges. - rebase.maxLabelLength
-
При создании имён меток из тем коммитов обрезать их до указанной длины. По умолчанию имена обрезаются до значения чуть меньше
NAME_MAX(чтобы, например, можно было создавать файлы.lockдля соответствующих свободных ссылок). - sequence.editor
-
Текстовый редактор, используемый командой
gitrebase-iдля редактирования файла инструкций перебазирования. При использовании значение обрабатывается оболочкой. Его можно переопределить с помощью переменной средыGIT_SEQUENCE_EDITOR. Если настройка не задана, вместо него используется редактор сообщений коммитов по умолчанию.
rebase
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-rebase