Spec-Zone.ru › Git

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 остановится на первом проблемном коммите и оставит маркеры конфликта. В этом случае можно сделать одно из следующего:

  1. Разрешить конфликт. Можно использовать git diff, чтобы найти маркеры (<<<<<<) и внести изменения для разрешения конфликта. Для каждого изменённого файла нужно сообщить Git, что конфликт разрешён. Отметить конфликт как разрешённый можно с помощью команды git add <filename>. После разрешения всех конфликтов можно продолжить перебазирование командой

    git rebase --continue
  2. Остановить git rebase и вернуть ветку в исходное состояние командой

    git rebase --abort
  3. Пропустить коммит, вызвавший конфликт слияния, командой

    git rebase --skip

Если при перебазировании не указать <upstream>, будет использована вышестоящая ветка, настроенная с помощью параметров branch.<name>.remote и branch.<name>.merge (подробности см. в git-config[1]), а параметр --fork-point считается заданным. Если вы сейчас не находитесь ни в одной ветке или для текущей ветки не настроена вышестоящая ветка, перебазирование будет прервано.

Ниже приведено упрощённое описание того, что делает git rebase <upstream>:

  1. Составить список всех коммитов текущей ветки, созданных после её ответвления от <upstream>, для которых нет эквивалентного коммита в <upstream>.

  2. Переключиться на <upstream> с помощью команды, эквивалентной git checkout --detach <upstream>.

  3. Повторно применить коммиты по одному, в заданном порядке. Это похоже на выполнение команды git cherry-pick <commit> для каждого коммита. Об обработке слияний см. раздел «ПЕРЕБАЗИРОВАНИЕ СЛИЯНИЙ».

  4. Обновить указатель ветки, чтобы он указывал на последний коммит, с помощью команды, эквивалентной git checkout -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

Показать текущий патч при интерактивном перебазировании или если перебазирование остановлено из-за конфликтов. Эквивалент команды git show REBASE_HEAD.

Параметры

--onto <newbase>

Начальная точка, от которой создаются новые коммиты. Если параметр --onto не указан, начальной точкой является <upstream>. Это может быть любой допустимый коммит, а не только имя существующей ветки.

В качестве особого случая можно использовать «A...B» как сокращение для базового коммита слияния A и B, если такой коммит ровно один. Можно опустить не более одного из A и B; в этом случае по умолчанию используется HEAD.

Примеры см. выше в разделе ПЕРЕНОС ТЕМАТИЧЕСКОЙ ВЕТКИ С ПОМОЩЬЮ --ONTO.

--keep-base

Задать начальной точкой для создания новых коммитов базовый коммит слияния <upstream> и <branch>. Выполнение команды git rebase --keep-base <upstream> <branch> эквивалентно выполнению команды git rebase --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), а коммиты, являющиеся точными копиями (определяется с помощью git log --cherry-mark ...), выявляются и отбрасываются на предварительном этапе (если не передан параметр --reapply-cherry-picks или --keep-base).

См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.

--no-keep-empty
--keep-empty

Не сохранять в результате коммиты, изначально пустые до перебазирования (то есть не изменяющие ничего по сравнению с родительским коммитом). По умолчанию изначально пустые коммиты сохраняются, поскольку для их создания необходимо передать в git commit переопределяющий флаг --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.

Поскольку git rebase повторно применяет каждый коммит рабочей ветки поверх ветки <upstream> с использованием указанной стратегии, использование стратегии ours просто удалит все патчи из ветки <branch>, что лишено смысла.

См. также раздел НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.

-X <strategy-option>
--strategy-option=<strategy-option>

Передать <strategy-option> стратегии слияния. Это подразумевает --merge, а если стратегия не указана — -s ort. Обратите внимание на перестановку 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 — результат выполнения команды git merge-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>

Этот флаг передаётся программе git apply, применяющей патч (см. 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; другие стратегии слияния можно использовать только с помощью явных команд exec git merge -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).

Этот параметр применяется после начала перебазирования. Его значение сохраняется на протяжении всего перебазирования и определяется в следующем порядке: параметр командной строки, указанный при первоначальном вызове git rebase, настройка rebase.rescheduleFailedExec (см. git-config[1] или раздел «КОНФИГУРАЦИЯ» ниже) либо значение false по умолчанию.

Сохранение этого параметра на протяжении всего перебазирования — это удобная возможность. Иначе явный параметр --no-reschedule-failed-exec, указанный в начале, был бы переопределён настройкой rebase.rescheduleFailedExec=true при вызове git rebase --continue. В настоящее время нельзя передать --[no-]reschedule-failed-exec команде git rebase --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>.

Интерактивный режим

Интерактивное перебазирование позволяет редактировать перебазируемые коммиты. Вы можете менять порядок коммитов и удалять их (отсеивая плохие или нежелательные по другим причинам исправления).

Интерактивный режим предназначен для следующего рабочего процесса:

  1. придумать замечательную идею

  2. поработать над кодом

  3. подготовить серию изменений для отправки

  4. отправить её

где пункт 2 состоит из нескольких повторений следующих действий

a) обычная работа

  1. закончить что-нибудь достойное коммита

  2. создать коммит

b) отдельное исправление

  1. заметить, что что-то не работает

  2. исправить это

  3. создать коммит с исправлением

Иногда исправление из пункта 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 ожидает, что результатом редактирования будет ровно один коммит. На самом деле вы можете отменить коммит или добавить другие коммиты. Это можно использовать, чтобы разделить один коммит на два:

  • Запустите интерактивное перебазирование с помощью git rebase -i <commit>^, где <commit> — коммит, который вы хотите разделить. В действительности подойдёт любой диапазон коммитов, если он включает этот коммит.

  • Пометьте коммит, который хотите разделить, действием "edit".

  • Когда дойдёт очередь редактировать этот коммит, выполните git reset HEAD^. В результате HEAD откатится на один коммит, и индекс будет приведён в соответствие. Однако рабочее дерево останется без изменений.

  • Теперь добавьте в индекс изменения, которые хотите включить в первый коммит. Для этого можно использовать git add (возможно, в интерактивном режиме) или git gui (или обе команды).

  • Создайте коммит из текущего индекса, используя подходящее на данный момент сообщение коммита.

  • Повторяйте два последних шага, пока рабочее дерево не станет чистым.

  • Продолжите перебазирование с помощью git rebase --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: после git fetch старая вершина 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, команда git rebase будет использовать в списке задач сокращённые имена команд, например:

        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

Текстовый редактор, используемый командой git rebase -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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API