Русский ▾ Topics ▾ Latest version ▾ git-rebase last updated in 2.54.0

НАЗВАНИЕ

git-rebase - Повторное применение коммитов над верхушкой другой ветки

ОБЗОР

git rebase [-i | --interactive] [<параметры>] [--exec <команда>]
	[--onto <новая-база> | --keep-base] [<вышестоящая-ветка> [<ветка>]]
git rebase [-i | --interactive] [<параметры>] [--exec <команда>]
	[--onto <новая-база>] --root [<ветка>]
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 <имя-файла>. После разрешения всех конфликтов вы можете продолжить процесс перемещения с помощью

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

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

    git rebase --skip

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

Вот упрощённое описание того, что делает git rebase <вышестоящая-ветка>:

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

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

  3. Воспроизвести коммиты один за другим по порядку. Это похоже на выполнение git cherry-pick <коммит> для каждого коммита. См. ПЕРЕМЕЩЕНИЕ СЛИЯНИЙ о том, как обрабатываются слияния.

  4. Обновить вашу ветку, чтобы она указывала на конечный коммит, с помощью эквивалента git checkout -B <ветка>.

Note
При запуске перемещения 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 и параметр <вышестоящая-ветка> могут быть любым допустимым указателем коммита.

ПАРАМЕТРЫ РЕЖИМА

Параметры в этом разделе нельзя использовать с любыми другими параметрами, включая друг друга:

--continue

Перезапустить процесс перемещения после разрешения конфликта слияния.

--skip

Перезапустить процесс перемещения, пропустив текущий патч.

--abort

Прервать операцию перемещения и сбросить HEAD на исходную ветку. Если <ветка> была указана при запуске операции перемещения, то HEAD будет сброшен на <ветку>. В противном случае HEAD будет сброшен туда, где он был, когда операция перемещения была запущена.

--quit

Прервать операцию перемещения, но HEAD не сбрасывается обратно на исходную ветку. Индекс и рабочий каталог также остаются неизменными. Если временное спрятанное изменение было создано с помощью --autostash, оно будет сохранено в список спрятанных изменений.

--edit-todo

Редактировать список задач во время интерактивного перемещения.

--show-current-patch

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

ПАРАМЕТРЫ

--onto <новая-основа>

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

В качестве особого случая вы можете использовать "A...B" как краткую форму для основы слияния A и B, если существует ровно одна основа слияния. Вы можете опустить не более одного из A и B, и в этом случае по умолчанию используется HEAD.

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

--keep-base

Установить начальную точку, в которой создаются новые коммиты, на основу слияния <вышестоящей-ветки> и <ветки>. Выполнение git rebase --keep-base <вышестоящая-ветка> <ветка> эквивалентно выполнению git rebase --reapply-cherry-picks --no-fork-point --onto <вышестоящая-ветка>...<ветка> <вышестоящая-ветка> <ветка>.

Этот параметр полезен в случае, когда вы разрабатываете функцию поверх вышестоящей ветки. Пока ведётся работа над функцией, вышестоящая ветка может продвинуться, и не всегда лучшей идеей будет продолжать перемещение поверх вышестоящей ветки, а лучше оставить базовый коммит как есть. Поскольку базовый коммит не изменяется, этот параметр подразумевает --reapply-cherry-picks, чтобы избежать потери коммитов.

Хотя и этот параметр, и --fork-point находят основу слияния между <вышестоящей-веткой> и <веткой>, этот параметр использует основу слияния как начальную точку, в которой будут созданы новые коммиты, тогда как --fork-point использует основу слияния для определения набора коммитов, которые будут перемещены.

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

<вышестоящая-ветка>

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

<ветка>

Рабочая ветка; по умолчанию HEAD.

--apply

Использовать стратегии применения для перемещения (внутренне вызывая git-am). Этот параметр может стать неоперацией в будущем, когда внутренний механизм слияния будет обрабатывать всё то, что делает механизм применения.

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

--empty=(drop|keep|stop)

Как обрабатывать коммиты, которые изначально не являются пустыми и не являются чистыми копиями какого-либо вышестоящего коммита, но становятся пустыми после перемещения (поскольку они содержат подмножество уже вышестоящих изменений):

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

Не сохранять в результате коммиты, которые изначально пусты до перемещения (т.е. которые ничего не меняют относительно своего родителя). По умолчанию сохраняются коммиты, которые изначально пусты, поскольку создание таких коммитов требует передачи флага переопределения --allow-empty в git commit, что означает, что пользователь очень намеренно создаёт такой коммит и, следовательно, хочет его сохранить.

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

Для коммитов, которые не являются изначально пустыми, но становятся пустыми после перемещения, см. флаг --empty.

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

--reapply-cherry-picks
--no-reapply-cherry-picks

Повторно применить все чистые копии любого вышестоящего коммита вместо их упреждающего удаления. (Если эти коммиты затем станут пустыми после перемещения, потому что они содержат подмножество уже вышестоящих изменений, поведение по отношению к ним контролируется флагом --empty.)

При отсутствии --keep-base (или если указан --no-reapply-cherry-picks) эти коммиты будут автоматически удалены. Поскольку это требует чтения всех вышестоящих коммитов, это может быть дорогостоящим в репозиториях с большим количеством вышестоящих коммитов, которые необходимо прочитать. При использовании внутреннего механизма merge будут выданы предупреждения для каждого удалённого коммита (если не указан --quiet). Также будет выдана рекомендация, если advice.skippedCherryPicks не установлен в false (см. git-config[1]).

--reapply-cherry-picks позволяет перемещению отказаться от чтения всех вышестоящих коммитов, потенциально улучшая производительность.

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

--allow-empty-message

Неоперация. Раньше перемещение коммитов с пустым сообщением приводило к ошибке, и этот параметр переопределял это поведение, позволяя перемещать коммиты с пустыми сообщениями. Теперь коммиты с пустым сообщением не вызывают остановку перемещения.

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

-m
--merge

Использование стратегий слияния для перемещения (по умолчанию).

Обратите внимание, что слияние при перемещении работает путём воспроизведения каждого коммита из рабочей ветки поверх ветки <вышестоящая-ветка>. Из-за этого, когда возникает конфликт слияния, сторона, сообщаемая как ours, — это перемещённая на данный момент серия, начинающаяся с <вышестоящей-ветки>, а theirs — это рабочая ветка. Другими словами, стороны поменяны местами.

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

-s <стратегия>
--strategy=<strategy>

Использовать указанную стратегию слияния вместо ort по умолчанию. Это подразумевает --merge.

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

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

-X <параметр-стратегии>
--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[<id-ключа>]
--gpg-sign[=<id-ключа>]
--no-gpg-sign

Подписывать коммиты с помощью GPG. Аргумент id-ключа необязателен, и если не указан, в качестве значения по умолчанию будет использоваться личное имя коммиттера; если аргумент указан, он должен следовать сразу после параметра, без пробела. Параметр --no-gpg-sign полезен, если нужно отменить переменную конфигурации commit.gpgSign или параметр --gpg-sign, заданный ранее.

-q
--quiet

Быть тихим. Подразумевает --no-stat.

-v
--verbose

Быть подробным. Подразумевает --stat.

--stat

Показывать статистику различий того, что изменилось вышестоящей ветке с последнего перемещения. Статистика различий также управляется параметром конфигурации rebase.stat.

-n
--no-stat

Не показывать статистику различий как часть процесса перемещения.

--no-verify

Этот параметр обходит перехватчик pre-rebase. См. также githooks[5].

--verify

Позволяет запустить перехватчик pre-rebase, что является поведением по умолчанию. Этот параметр можно использовать для переопределения --no-verify. См. также githooks[5].

-C<n>

Гарантировать, что по крайней мере <число> строк окружающего контекста совпадают до и после каждого изменения. Когда существует меньше строк окружающего контекста, все они должны совпадать. По умолчанию контекст никогда не игнорируется. Подразумевает --apply.

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

--no-ff
--force-rebase
-f

Индивидуально воспроизводить все перемещаемые коммиты вместо перемотки вперёд через неизменённые. Это гарантирует, что вся история перемещённой ветки состоит из новых коммитов.

Это может быть полезно после отмены слияния тематической ветки, поскольку этот параметр воссоздаёт тематическую ветку с новыми коммитами, чтобы её можно было успешно слить повторно без необходимости "отменять отмену" (подробности см. в revert-a-faulty-merge How-To).

--fork-point
--no-fork-point

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

Когда активен --fork-point, точка_ответвления будет использоваться вместо <вышестоящей-ветки> для вычисления набора коммитов для перемещения, где fork_point является результатом команды git merge-base --fork-point <вышестоящая-ветка> <ветка> (см. git-merge-base[1]). Если точка_ответвления оказывается пустой, в качестве резервного варианта будет использоваться <вышестоящая-ветка>.

Если <вышестоящая-ветка> или --keep-base указаны в командной строке, то по умолчанию используется --no-fork-point, в противном случае по умолчанию используется --fork-point. См. также rebase.forkpoint в git-config[1].

Если ваша ветка была основана на <вышестоящей-ветке>, но <вышестоящая-ветка> была перемотана назад и ваша ветка содержит коммиты, которые были удалены, этот параметр можно использовать с --keep-base, чтобы удалить эти коммиты из вашей ветки.

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

--ignore-whitespace

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

внутренний механизм apply

При применении патча игнорировать изменения в пробелах в строках контекста. К сожалению, это означает, что если "старые" строки, заменяемые патчем, отличаются от существующего файла только пробелами, вы получите конфликт слияния вместо успешного применения патча.

merge backend

Обрабатывать строки только с изменениями пробелов как неизменённые при слиянии. К сожалению, это означает, что любые части патчей, которые были предназначены для изменения только пробелов, будут удалены, даже если другая сторона не имела конфликтующих изменений.

--whitespace=<option>

Этот флаг передаётся программе git apply (см. git-apply[1]), которая применяет патч. Подразумевает --apply.

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

--committer-date-is-author-date

Вместо использования текущего времени в качестве даты коммиттера использовать дату создания перемещаемого коммита в качестве даты коммиттера. Этот параметр подразумевает --force-rebase.

Warning
Механизм обхода истории предполагает, что коммиты имеют неубывающие временные метки коммитов. Вы должны подумать, действительно ли вам нужно использовать этот параметр. Затем вы должны использовать этот параметр только для переопределения даты коммиттера при перемещении коммитов поверх основы, чей коммит старше (с точки зрения даты коммита), чем самый старый коммит, который вы применяете (с точки зрения даты создания).
--ignore-date
--reset-author-date

Вместо использования даты автора исходного коммита используйте текущее время в качестве даты автора перемещённого коммита. Этот параметр подразумевает --force-rebase.

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

--signoff

Добавляет завершитель Signed-off-by ко всем перемещённым коммитам. Обратите внимание, что если указан --interactive, то завершитель будет добавлен только к коммитам, отмеченным для выбора, редактирования или переформулирования.

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

--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 коммиты, которые не имеют <вышестоящей-ветки> в качестве прямого предка, сохранят свою исходную точку ветвления, т.е. коммиты, которые были бы исключены параметром --ancestry-path команды git-log[1], по умолчанию сохранят свою исходную родословную. В режиме rebase-cousins такие коммиты вместо этого перемещаются на <вышестоящую-ветку> (или <новую-основу>, если указано).

В настоящее время воссоздать коммиты слияния можно только с использованием стратегии слияния ort; другие стратегии слияния можно использовать только через явные команды exec git merge -s <стратегия> [...].

См. также ПЕРЕМЕЩЕНИЕ СЛИЯНИЙ и НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.

-x <команда>
--exec <команда>

Добавляет «exec <команда>» после каждой строки, создающей коммит в конечной истории. <команда> будет интерпретироваться как одна или несколько команд оболочки. Любая команда, которая завершится ошибкой, прервёт перемещение с кодом выхода 1.

Вы можете выполнить несколько команд, используя один экземпляр --exec с несколькими командами:

git rebase -i --exec "команда1 && команда2 && ..."

или указав более одного --exec:

git rebase -i --exec "команда1" --exec "команда2" --exec ...

Если используется --autosquash, строки exec не будут добавляться для промежуточных коммитов и будут появляться только в конце каждой серии объединения/исправления.

Это внутренне использует механизм --interactive, но может быть запущено без явного --interactive.

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

--root

Переместить все коммиты, достижимые из <ветки>, вместо ограничения их с помощью <вышестоящей-ветки>. Это позволяет вам переместить корневые коммиты в ветке.

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

--autosquash
--no-autosquash

Автоматически объединять коммиты со специально отформатированными сообщениями в предыдущие коммиты, которые перемещаются. Если сообщение коммита начинается с "squash! ", "fixup! " или "amend! ", остальная часть заголовка принимается как спецификатор коммита, который соответствует предыдущему коммиту, если он соответствует заголовку или хешу этого коммита. Если ни один коммит не соответствует полностью, рассматриваются соответствия спецификатора с началом заголовков коммитов.

В списке задач перемещения действия squash, fixup и amend для коммитов изменяются с pick на squash, fixup или fixup -C соответственно, и они перемещаются сразу после коммита, который они изменяют. Параметр --interactive можно использовать для просмотра и редактирования списка задач перед продолжением.

Рекомендуемый способ создания коммитов с маркерами объединения — использование параметров --squash, --fixup, --fixup=amend: или --fixup=reword: команды git-commit[1], которые принимают целевой коммит в качестве аргумента и автоматически заполняют заголовок нового коммита из него.

Установка переменной конфигурации rebase.autoSquash в true включает автоматическое объединение по умолчанию для интерактивного перемещения. Параметр --no-autosquash можно использовать для переопределения этой настройки.

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

--autostash
--no-autostash

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

--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 записывает сообщения об ошибках (например, "Your files would be overwritten…​") в stdout, в то время как механизм merge записывает их в stderr.

  • Каталоги состояния: Два механизма хранят своё состояние в разных каталогах внутри .git/

СТРАТЕГИИ СЛИЯНИЯ

Механизм слияния (команды git merge и git pull) позволяет выбирать внутренние стратегии слияния с помощью параметра -s. Некоторые стратегии также могут принимать свои собственные параметры, которые можно передать, указав аргументы -X<параметр> для git merge и/или git pull.

ort

Это стратегия слияния по умолчанию при получении или слиянии одной ветки. Эта стратегия может разрешить только две головы с использованием алгоритма трёхходового слияния. Когда существует более одного общего предка, который может быть использован для трёхходового слияния, она создаёт слитое дерево общих предков и использует его в качестве эталонного дерева для трёхходового слияния. Сообщается, что это приводит к уменьшению количества конфликтов слияния без неправильных слияний по результатам тестов, проведённых на реальных коммитах слияния из истории разработки ядра Linux 2.6. Кроме того, эта стратегия может обнаруживать и обрабатывать слияния, включающие переименования. Она не использует обнаруженные копии. Название этого алгоритма — аббревиатура ("Ostensibly Recursive’s Twin") и возникло из-за того, что он был написан как замена предыдущему алгоритму по умолчанию, recursive.

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

Стратегия ort может принимать следующие параметры:

ours

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

Это не следует путать со стратегией слияния ours, которая вообще даже не смотрит на то, что содержит другое дерево. Она отбрасывает всё, что сделало другое дерево, объявляя, что наша история содержит всё, что в нём произошло.

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.

  • Если их версия вносит только изменения пробелов в строку, используется наша версия;

  • Если наша версия вносит изменения пробелов, но их версия включает существенное изменение, используется их версия;

  • В противном случае слияние продолжается обычным образом.

renormalize

Это выполняет виртуальное переключение и фиксацию всех трёх стадий любого файла, которому требуется трёхходовое слияние. Этот параметр предназначен для использования при слиянии веток с разными фильтрами очистки или правилами нормализации концов строк. Подробности см. в разделе "Слияние веток с различными атрибутами фиксации/переключения" в gitattributes[5].

no-renormalize

Отключает параметр renormalize. Это переопределяет переменную конфигурации merge.renormalize.

find-renames[=<n>]

Включает обнаружение переименований, опционально устанавливая порог схожести. Это поведение по умолчанию. Это переопределяет переменную конфигурации merge.renames. См. также git-diff[1] --find-renames.

rename-threshold=<число>

Устаревший синоним для find-renames=<число>.

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[=<путь>]

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

recursive

Теперь это синоним для ort. Это была альтернативная реализация до v2.49.0, но в v2.50.0 была перенаправлена на ort. Предыдущая рекурсивная стратегия была стратегией по умолчанию для разрешения двух голов начиная с 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 для примера.

По завершении <ветка> станет текущей веткой.

ИНТЕРАКТИВНЫЙ РЕЖИМ

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

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

  1. есть замечательная идея

  2. взламывать код

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

  4. отправить

где пункт 2. состоит из нескольких экземпляров

a) обычное использование

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

  2. коммит

b) независимое исправление

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

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

  3. закоммитить это

Иногда исправление, сделанное в б.2., не может быть добавлено к не совсем идеальному коммиту, который оно исправляет, потому что этот коммит глубоко похоронен в серии патчей. Именно для этого и нужно интерактивное перемещение: используйте его после множества "а" и "б", переставляя и редактируя коммиты и объединяя несколько коммитов в один.

Начните его с последнего коммита, который вы хотите сохранить как есть:

git rebase -i <после-этого-коммита>

Будет запущен редактор со всеми коммитами в вашей текущей ветке (игнорируя коммиты слияния), которые идут после указанного коммита. Вы можете переупорядочить коммиты в этом списке по своему усмотрению и удалить их. Список выглядит примерно так:

pick deadbee Однострочное описание этого коммита
pick fa1afe1 Однострочное описание следующего коммита
...

Однострочные описания предназначены исключительно для вашего удобства; git rebase не будет смотреть на них, а на имена коммитов ("deadbee" и "fa1afe1" в этом примере), поэтому не удаляйте и не редактируйте имена.

Заменив команду «pick» командой «edit», вы можете указать git rebase остановиться после применения этого коммита, чтобы вы могли отредактировать файлы и/или сообщение коммита, исправить коммит и продолжить перемещение.

Чтобы прервать перемещение (как это сделала бы команда "edit", но без предварительного копирования какого-либо коммита), используйте команду "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 Реализовать функцию XXX
fixup f1a5c00 Исправление для функции XXX
exec make
pick c0ffeee Однострочное описание следующего коммита
edit deadbab Однострочное описание последующего коммита
exec cd подкаталог; make test
...

Интерактивное перемещение остановится, когда команда завершится ошибкой (т.е. завершится с ненулевым статусом), чтобы дать вам возможность исправить проблему. Вы можете продолжить с помощью git rebase --continue.

Команда "exec" запускает команду в оболочке (по умолчанию, обычно /bin/sh), поэтому вы можете использовать возможности оболочки (например, "cd", ">", ";" …​). Команда запускается из корня рабочего каталога.

$ git rebase -i --exec "make test"

Эта команда позволяет вам проверить, что промежуточные коммиты компилируются. Список задач становится таким:

pick 5928aea один
exec make test
pick 04d0fda два
exec make test
pick ba46169 три
exec make test
pick f4593f9 четыре
exec make test

РАЗДЕЛЕНИЕ КОММИТОВ

В интерактивном режиме вы можете помечать коммиты действием "edit". Однако это не обязательно означает, что git rebase ожидает, что результатом этого редактирования будет ровно один коммит. Действительно, вы можете отменить коммит или добавить другие коммиты. Это можно использовать для разделения коммита на два:

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

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

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

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

  • Зафиксируйте теперь текущий индекс с любым сообщением коммита, которое сейчас уместно.

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

  • Продолжите перемещение с помощью git rebase --continue.

Если вы не абсолютно уверены, что промежуточные редакции согласованы (они компилируются, проходят набор тестов и т.д.), вам следует использовать git stash, чтобы спрятать ещё не зафиксированные изменения после каждого коммита, протестировать и исправить коммит, если необходимы исправления.

ВОССТАНОВЛЕНИЕ ПОСЛЕ REBASE В ВЫШЕСТОЯЩЕМ РЕПОЗИТОРИИ

Перемещение (или любая другая форма переписывания) ветки, на которой другие основали свою работу, — плохая идея: любой, кто находится ниже по течению, вынужден вручную исправлять свою историю. В этом разделе объясняется, как выполнить исправление с точки зрения нижестоящего. Однако настоящее исправление состоит в том, чтобы вообще избегать перемещения вышестоящей ветки.

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

Лёгкий случай

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

Note
Хотя "восстановление в лёгком случае" иногда кажется успешным даже в сложном случае, оно может иметь непредвиденные последствия. Например, коммит, который был удалён с помощью 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}

Эффект ряди при восстановлении в "сложном случае" особенно плох: всем, кто находится ниже по течению от topic, теперь также придётся выполнять восстановление в "сложном случае"!

ПЕРЕМЕЩЕНИЕ СЛИЯНИЙ

Команда интерактивного перемещения изначально была разработана для обработки отдельных серий патчей. Как таковая, она исключает коммиты слияния из списка задач, поскольку разработчик мог слить тогдашний master во время работы над веткой, чтобы в конечном итоге переместить все коммиты на master (пропуская коммиты слияния).

Однако существуют законные причины, по которым разработчик может захотеть воссоздать коммиты слияния: чтобы сохранить структуру ветвления (или "топологию коммитов") при работе с несколькими взаимосвязанными ветками.

В следующем примере разработчик работает над тематической веткой, которая рефакторит способ определения кнопок, и над другой тематической веткой, которая использует этот рефакторинг для реализации кнопки "Сообщить об ошибке". Вывод git log --graph --format=%s -5 может выглядеть так:

*   Слияние ветки 'report-a-bug'
|\
| * Добавить кнопку обратной связи
* | Слияние ветки 'refactor-button'
|\ \
| |/
| * Использовать класс Button для всех кнопок
| * Извлечь общий класс Button из класса DownloadButton

Разработчик может захотеть переместить эти коммиты на более новый master, сохраняя топологию ветвления, например, когда ожидается, что первая тематическая ветка будет интегрирована в master намного раньше, чем вторая, скажем, для разрешения конфликтов слияния с изменениями в классе DownloadButton, которые попали в master.

Это перемещение может быть выполнено с использованием параметра --rebase-merges. Он сгенерирует список задач, выглядящий так:

label onto

# Ветка: refactor-button
reset onto
pick 123456 Извлечь общий класс Button из класса DownloadButton
pick 654321 Использовать класс Button для всех кнопок
label refactor-button

# Ветка: report-a-bug
reset refactor-button # Использовать класс Button для всех кнопок
pick abcdef Добавить кнопку обратной связи
label report-a-bug

reset onto
merge -C a1b2c3 refactor-button # Слияние 'refactor-button'
merge -C 6f5e4d report-a-bug # Слияние 'report-a-bug'

В отличие от обычного интерактивного перемещения, здесь есть команды label, reset и merge в дополнение к командам pick.

Команда label связывает метку с текущим HEAD, когда эта команда выполняется. Эти метки создаются как ссылки, локальные для рабочего каталога (refs/rewritten/<метка>), которые будут удалены после завершения перемещения. Таким образом, операции перемещения в нескольких рабочих каталогах, связанных с одним и тем же репозиторием, не мешают друг другу. Если команда label завершается ошибкой, она немедленно перепланируется с полезным сообщением о том, как продолжить.

Команда reset сбрасывает HEAD, индекс и рабочий каталог на указанную редакцию. Она похожа на exec git reset --hard <метка>, но отказывается перезаписывать неотслеживаемые файлы. Если команда reset завершается ошибкой, она немедленно перепланируется с полезным сообщением о том, как отредактировать список задач (обычно это происходит, когда команда reset была вставлена в список задач вручную и содержит опечатку).

Команда merge сольёт указанную(ые) редакцию(и) в то, что является HEAD в этот момент. С -C <исходный-коммит> будет использовано сообщение коммита указанного коммита слияния. Когда -C изменён на строчный -c, сообщение будет открыто в редакторе после успешного слияния, чтобы пользователь мог отредактировать сообщение.

Если команда merge завершается ошибкой по любой причине, кроме конфликтов слияния (т.е. когда операция слияния даже не начиналась), она немедленно перепланируется.

По умолчанию команда merge будет использовать стратегию слияния ort для обычных слияний и octopus для слияний-осьминогов. Можно указать стратегию по умолчанию для всех слияний, используя аргумент --strategy при вызове rebase, или можно переопределить конкретные слияния в интерактивном списке команд, используя команду exec для явного вызова git merge с аргументом --strategy. Обратите внимание, что при явном вызове git merge таким образом вы можете использовать тот факт, что метки являются ссылками, локальными для рабочего каталога (ссылка refs/rewritten/onto будет соответствовать метке onto, например), чтобы ссылаться на ветки, которые вы хотите слить.

Примечание: первая команда (label onto) помечает редакцию, на которую перемещаются коммиты; имя onto — это всего лишь соглашение, как намёк на параметр --onto.

Также можно ввести совершенно новые коммиты слияния с нуля, добавив команду вида merge <голова-слияния>. Эта форма сгенерирует предварительное сообщение коммита и всегда откроет редактор, чтобы пользователь мог его отредактировать. Это может быть полезно, например, когда тематическая ветка решает более одной задачи и её нужно разделить на две или даже более тематических веток. Рассмотрим этот список задач:

pick 192837 Переход с GNU Makefiles на CMake
pick 5a6c7e Документирование перехода на CMake
pick 918273 Исправление обнаружения OpenSSL в CMake
pick afbecd http: добавить поддержку TLS v1.3
pick fdbaec Исправление обнаружения cURL в CMake в Windows

Один коммит в этом списке, который не связан с CMake, вполне мог быть вызван работой над исправлением всех этих ошибок, вызванных переходом на CMake, но он решает другую задачу. Чтобы разделить эту ветку на две тематические ветки, список задач можно отредактировать следующим образом:

label onto

pick afbecd http: добавить поддержку TLS v1.3
label tlsv1.3

reset onto
pick 192837 Переход с GNU Makefiles на CMake
pick 918273 Исправление обнаружения OpenSSL в CMake
pick fdbaec Исправление обнаружения cURL в CMake в Windows
pick 5a6c7e Документирование перехода на CMake
label cmake

reset onto
merge tlsv1.3
merge cmake

КОНФИГУРАЦИЯ

Дальнейшее содержание этого раздела, повторяет то, что может быть найдено в git-config[1]:

rebase.backend

Внутренний механизм по умолчанию для перемещения (rebase). Возможные варианты: apply или merge. В будущем, если внутренний механизм слияния (merge backend) получит все оставшиеся возможности внутреннего механизма наложения (apply backend), этот параметр может перестать использоваться.

rebase.stat

Показывать ли diffstat того, что изменилось выше по течению (upstream) с момента последнего перемещения. По умолчанию false.

rebase.autoSquash

Если установлено в true, включить параметр --autosquash команды git-rebase[1] по умолчанию для интерактивного режима. Это можно переопределить с помощью параметра --no-autosquash.

rebase.autoStash

Если установлено в true, автоматически создаёт временную запись в тайнике (stash) перед началом операции и применяет её после завершения операции. Это означает, что вы можете выполнять перемещение на грязном рабочем каталоге. Однако используйте с осторожностью: финальное применение тайника после успешного перемещения может привести к нетривиальным конфликтам. Этот параметр может быть переопределён параметрами --no-autostash и --autostash команды git-rebase[1]. По умолчанию false.

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 Однострочное описание коммита
	p fa1afe1 Однострочное описание следующего коммита
	...

вместо:

	pick deadbee Однострочное описание коммита
	pick fa1afe1 Однострочное описание следующего коммита
	...

По умолчанию false.

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 для соответствующих непакованных (loose) ссылок).

sequence.editor

Текстовый редактор, используемый git rebase -i для редактирования файла инструкций перемещения. Значение должно интерпретироваться оболочкой при его использовании. Может быть переопределено переменной среды GIT_SEQUENCE_EDITOR. Если не настроено, вместо него используется редактор сообщений коммитов по умолчанию.

GIT

Является частью пакета git[1]