Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
-
2.54.0
2026-04-20
-
2.53.0
2026-02-02
-
2.52.0
2025-11-17
- 2.50.1 → 2.51.2 no changes
-
2.50.0
2025-06-16
- 2.49.1 no changes
-
2.49.0
2025-03-14
- 2.46.2 → 2.48.2 no changes
-
2.46.1
2024-09-13
- 2.45.1 → 2.46.0 no changes
-
2.45.0
2024-04-29
- 2.44.1 → 2.44.4 no changes
-
2.44.0
2024-02-23
- 2.43.3 → 2.43.7 no changes
-
2.43.2
2024-02-13
-
2.43.1
2024-02-09
-
2.43.0
2023-11-20
- 2.42.2 → 2.42.4 no changes
-
2.42.1
2023-11-02
- 2.41.1 → 2.42.0 no changes
-
2.41.0
2023-06-01
- 2.40.1 → 2.40.4 no changes
-
2.40.0
2023-03-12
- 2.39.4 → 2.39.5 no changes
-
2.39.3
2023-04-17
- 2.39.1 → 2.39.2 no changes
-
2.39.0
2022-12-12
- 2.38.1 → 2.38.5 no changes
-
2.38.0
2022-10-02
- 2.37.3 → 2.37.7 no changes
-
2.37.2
2022-08-11
- 2.36.3 → 2.37.1 no changes
-
2.36.2
2022-06-23
- 2.35.1 → 2.36.1 no changes
-
2.35.0
2022-01-24
- 2.34.1 → 2.34.8 no changes
-
2.34.0
2021-11-15
- 2.33.2 → 2.33.8 no changes
-
2.33.1
2021-10-12
- 2.32.1 → 2.33.0 no changes
-
2.32.0
2021-06-06
- 2.31.1 → 2.31.8 no changes
-
2.31.0
2021-03-15
- 2.30.1 → 2.30.9 no changes
-
2.30.0
2020-12-27
- 2.29.1 → 2.29.3 no changes
-
2.29.0
2020-10-19
- 2.28.1 no changes
-
2.28.0
2020-07-27
- 2.27.1 no changes
-
2.27.0
2020-06-01
- 2.26.1 → 2.26.3 no changes
-
2.26.0
2020-03-22
- 2.25.1 → 2.25.5 no changes
-
2.25.0
2020-01-13
- 2.24.1 → 2.24.4 no changes
-
2.24.0
2019-11-04
- 2.23.1 → 2.23.4 no changes
-
2.23.0
2019-08-16
- 2.22.1 → 2.22.5 no changes
-
2.22.0
2019-06-07
- 2.21.1 → 2.21.4 no changes
-
2.21.0
2019-02-24
- 2.20.1 → 2.20.5 no changes
-
2.20.0
2018-12-09
- 2.19.3 → 2.19.6 no changes
-
2.19.2
2018-11-21
- 2.19.1 no changes
-
2.19.0
2018-09-10
- 2.18.1 → 2.18.5 no changes
-
2.18.0
2018-06-21
- 2.17.1 → 2.17.6 no changes
-
2.17.0
2018-04-02
-
2.16.6
2019-12-06
-
2.15.4
2019-12-06
-
2.14.6
2019-12-06
-
2.13.7
2018-05-22
-
2.12.5
2017-09-22
- 2.10.5 → 2.11.4 no changes
-
2.9.5
2017-07-30
-
2.8.6
2017-07-30
- 2.7.6 no changes
-
2.6.7
2017-05-05
- 2.5.6 no changes
-
2.4.12
2017-05-05
-
2.3.10
2015-09-28
-
2.2.3
2015-09-04
-
2.1.4
2014-12-17
-
2.0.5
2014-12-17
ОБЗОР
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 остановится на первом проблемном коммите и оставит маркеры конфликта. Если это произошло, вы можете сделать одно из следующих действий:
-
Разрешить конфликт. Вы можете использовать
gitdiff, чтобы найти маркеры (<<<<<<) и внести правки для разрешения конфликта. Для каждого файла, который вы редактируете, вы должны сообщить Git, что конфликт разрешён. Вы можете пометить конфликт как разрешённый с помощьюgitadd<имя-файла>. После разрешения всех конфликтов вы можете продолжить процесс перемещения с помощьюgit rebase --continue
-
Остановить
gitrebaseи вернуть вашу ветку в исходное состояние с помощьюgit rebase --abort
-
Пропустить коммит, вызвавший конфликт слияния, с помощью
git rebase --skip
Если вы не указываете <вышестоящую-ветку> для перемещения на неё, будет использоваться вышестоящая ветка, настроенная в параметрах branch.<имя>.remote и branch.<имя>.merge (подробности см. в git-config[1]), и предполагается параметр --fork-point. Если вы в настоящее время не находитесь ни на какой ветке или если текущая ветка не имеет настроенной вышестоящей, перемещение будет прервано.
Вот упрощённое описание того, что делает git rebase <вышестоящая-ветка>:
-
Составить список всех коммитов в вашей текущей ветке с момента её ответвления от <вышестоящей-ветки>, которые не имеют эквивалентного коммита в <вышестоящей-ветке>.
-
Переключить <вышестоящую-ветку> с помощью эквивалента
gitcheckout--detach<вышестоящая-ветка>. -
Воспроизвести коммиты один за другим по порядку. Это похоже на выполнение
gitcherry-pick<коммит> для каждого коммита. См. ПЕРЕМЕЩЕНИЕ СЛИЯНИЙ о том, как обрабатываются слияния. -
Обновить вашу ветку, чтобы она указывала на конечный коммит, с помощью эквивалента
gitcheckout-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
-
Показать текущий патч при интерактивном перемещении или когда перемещение остановлено из-за конфликтов. Это эквивалентно
gitshowREBASE_HEAD.
ПАРАМЕТРЫ
- --onto <новая-основа>
-
Начальная точка, в которой будут созданы новые коммиты. Если параметр
--ontoне указан, начальной точкой является <вышестоящая-ветка>. Может быть любым допустимым коммитом, а не только именем существующей ветки.В качестве особого случая вы можете использовать "A...B" как краткую форму для основы слияния A и B, если существует ровно одна основа слияния. Вы можете опустить не более одного из A и B, и в этом случае по умолчанию используется HEAD.
Примеры см. в разделе ПЕРЕСАДКА ТЕМАТИЧЕСКОЙ ВЕТКИ С ПОМОЩЬЮ --ONTO выше.
- --keep-base
-
Установить начальную точку, в которой создаются новые коммиты, на основу слияния <вышестоящей-ветки> и <ветки>. Выполнение
gitrebase--keep-base<вышестоящая-ветка> <ветка> эквивалентно выполнениюgitrebase--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), а коммиты, которые являются чистыми копиями (как определеноgitlog--cherry-mark...), обнаруживаются и удаляются в качестве предварительного шага (если не переданы--reapply-cherry-picksили--keep-base).См. также НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
-
- --no-keep-empty
- --keep-empty
-
Не сохранять в результате коммиты, которые изначально пусты до перемещения (т.е. которые ничего не меняют относительно своего родителя). По умолчанию сохраняются коммиты, которые изначально пусты, поскольку создание таких коммитов требует передачи флага переопределения
--allow-emptyвgitcommit, что означает, что пользователь очень намеренно создаёт такой коммит и, следовательно, хочет его сохранить.Использование этого флага, вероятно, будет редким, поскольку вы можете избавиться от коммитов, которые изначально пусты, просто запустив интерактивное перемещение и удалив строки, соответствующие ненужным коммитам. Этот флаг существует как удобное сокращение, например, для случаев, когда внешние инструменты генерируют много пустых коммитов, и вы хотите удалить их все.
Для коммитов, которые не являются изначально пустыми, но становятся пустыми после перемещения, см. флаг
--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.Поскольку
gitrebaseвоспроизводит каждый коммит из рабочей ветки поверх ветки <вышестоящая-ветка>, используя указанную стратегию, использование стратегииoursпросто очищает все патчи из <ветки>, что не имеет особого смысла.См. также НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
- -X <параметр-стратегии>
- --strategy-option=<strategy-option>
-
Передать <параметр-стратегии> стратегии слияния. Это подразумевает
--mergeи, если стратегия не была указана,-sort. Обратите внимание на перемену мест ours и theirs, как отмечено выше для параметра-m.См. также НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
-
--rerere-autoupdate -
--no-rerere-autoupdate -
После того как механизм rerere повторно использует записанное ранее разрешение на текущем конфликте для обновления файлов в рабочем каталоге, разрешить также обновить индекс, применив к нему результат разрешения. Параметр
--no-rerere-autoupdateможно использовать как удобный способ дважды проверить результат работы git-rerere[1] и поймать потенциальные ошибки слияния до того, как зафиксировать результат в индексе с помощью отдельной команды git-add[1].
- -S[<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 является результатом командыgitmerge-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>
-
Этот флаг передаётся программе
gitapply(см. 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; другие стратегии слияния можно использовать только через явные командыexecgitmerge-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).Этот параметр применяется после запуска перемещения. Он сохраняется для всего перемещения на основе (в порядке приоритета) параметра командной строки, предоставленного начальному
gitrebase, конфигурацииrebase.rescheduleFailedExec(см. git-config[1] или раздел "КОНФИГУРАЦИЯ" ниже) или по умолчанию равен false.Запись этого параметра для всего перемещения является удобной функцией. В противном случае явный
--no-reschedule-failed-execв начале был бы переопределён наличием конфигурацииrebase.rescheduleFailedExec=trueпри вызовеgitrebase--continue. В настоящее время вы не можете передать--[no-]reschedule-failed-execвgitrebase--continue. - --update-refs
- --no-update-refs
-
Автоматически принудительно обновлять любые ветки, которые указывают на коммиты, перемещаемые в данный момент. Любые ветки, которые переключены в рабочем каталоге, не обновляются таким образом.
Если установлена переменная конфигурации
rebase.updateRefs, то этот параметр можно использовать для переопределения и отключения этой настройки.См. также НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ ниже.
НЕСОВМЕСТИМЫЕ ПАРАМЕТРЫ
Следующие параметры:
-
--apply
-
--whitespace
-
-C
несовместимы со следующими параметрами:
-
--merge
-
--strategy
-
--strategy-option
-
--autosquash
-
--rebase-merges
-
--interactive
-
--exec
-
--no-keep-empty
-
--empty=
-
--[no-]reapply-cherry-picks при использовании без --keep-base
-
--update-refs
-
--root при использовании без --onto
-
--trailer
Кроме того, следующие пары параметров несовместимы:
-
--keep-base и --onto
-
--keep-base и --root
-
--fork-point и --root
РАЗЛИЧИЯ В ПОВЕДЕНИИ
git rebase имеет два основных внутренних механизма: apply и merge. (Механизм apply ранее был известен как механизм am, но это название вызывало путаницу, поскольку оно выглядит как глагол, а не существительное. Кроме того, механизм merge ранее был известен как интерактивный механизм, но теперь он также используется для неинтерактивных случаев. Оба были переименованы на основе низкоуровневой функциональности, лежащей в основе каждого.) Существуют некоторые тонкие различия в поведении этих двух внутренних механизмов:
Пустые коммиты
К сожалению, механизм apply удаляет намеренно пустые коммиты, т.е. коммиты, которые изначально были пусты, хотя на практике они встречаются редко. Он также удаляет коммиты, которые становятся пустыми, и не имеет параметра для управления этим поведением.
Механизм merge по умолчанию сохраняет намеренно пустые коммиты (хотя с -i они помечаются как пустые в редакторе списка задач, или они могут быть автоматически удалены с помощью --no-keep-empty).
Подобно механизму apply, по умолчанию механизм merge удаляет коммиты, которые становятся пустыми, если не указан -i/--interactive (в этом случае он останавливается и спрашивает пользователя, что делать). Механизм merge также имеет параметр --empty=(drop|keep|stop) для изменения поведения обработки коммитов, которые становятся пустыми.
Обнаружение переименований каталогов
Из-за отсутствия точной информации о дереве (возникающей из-за создания фальшивых предков с ограниченной информацией, доступной в патчах), обнаружение переименований каталогов отключено в механизме apply. Отключённое обнаружение переименований каталогов означает, что если одна сторона истории переименовывает каталог, а другая добавляет новые файлы в старый каталог, то новые файлы останутся в старом каталоге без какого-либо предупреждения во время перемещения о том, что вы, возможно, захотите переместить эти файлы в новый каталог.
Обнаружение переименований каталогов работает с механизмом merge, чтобы предоставлять вам предупреждения в таких случаях.
Контекст
Механизм apply работает путём создания последовательности патчей (внутренне вызывая format-patch), а затем последовательного применения патчей (внутренне вызывая am). Патчи состоят из нескольких частей, каждая с номерами строк, областью контекста и фактическими изменениями. Номера строк должны быть взяты с некоторым смещением, поскольку другая сторона, вероятно, вставила или удалила строки ранее в файле. Область контекста предназначена для того, чтобы помочь определить, как скорректировать номера строк, чтобы применить изменения к правильным строкам. Однако если несколько областей кода имеют одинаковые окружающие строки контекста, может быть выбрана неправильная. Существуют реальные случаи, когда это приводило к неправильному повторному применению коммитов без сообщения о конфликтах. Установка diff.context в большее значение может предотвратить такие типы проблем, но увеличивает шанс ложных конфликтов (поскольку для применения потребуется больше совпадающих строк контекста).
Механизм merge работает с полной копией каждого соответствующего файла, что изолирует его от таких типов проблем.
Маркировка маркеров конфликтов
Когда возникают конфликты содержимого, механизм слияния пытается аннотировать маркеры конфликта каждой стороны коммитами, из которых поступило содержимое. Поскольку механизм apply отбрасывает исходную информацию о перемещаемых коммитах и их родителях (и вместо этого генерирует новые фальшивые коммиты на основе ограниченной информации в сгенерированных патчах), эти коммиты не могут быть идентифицированы; вместо этого он вынужден возвращаться к сводке коммита. Кроме того, когда merge.conflictStyle установлен в diff3 или zdiff3, механизм apply будет использовать «сконструированную основу слияния» для маркировки содержимого из основы слияния и, таким образом, не предоставит никакой информации о коммите основы слияния.
Механизм merge работает с полными коммитами с обеих сторон истории и, таким образом, не имеет таких ограничений.
Перехватчики
Механизм apply традиционно не вызывал перехватчик post-commit, в то время как механизм merge вызывал. Оба вызывали перехватчик post-checkout, хотя механизм merge подавлял его вывод. Кроме того, оба механизма вызывают перехватчик post-checkout только с начальным коммитом перемещения, а не с промежуточными коммитами и не с конечным коммитом. В каждом случае вызов этих перехватчиков был случайностью реализации, а не дизайном (оба механизма изначально были реализованы как сценарии оболочки и случайно вызывали другие команды, такие как git checkout или git commit, которые вызывали перехватчики). Оба механизма должны иметь одинаковое поведение, хотя не совсем ясно, какое из них, если таковое имеется, является правильным. Вероятно, в будущем мы заставим rebase перестать вызывать любой из этих перехватчиков.
Прерываемость
Механизм apply имеет проблемы с безопасностью при несвоевременном прерывании; если пользователь нажимает Ctrl-C в неподходящее время, пытаясь прервать перемещение, перемещение может перейти в состояние, в котором его нельзя будет прервать последующим git rebase --abort. Механизм merge, по-видимому, не страдает от того же недостатка. (Подробности см. на https://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/.)
Переформулирование коммита
Когда во время перемещения возникает конфликт, перемещение останавливается и просит пользователя разрешить его. Поскольку пользователю может потребоваться внести существенные изменения при разрешении конфликтов, после того как конфликты разрешены и пользователь выполнил git rebase --continue, перемещение должно открыть редактор и попросить пользователя обновить сообщение коммита. Механизм merge делает это, в то время как механизм apply слепо применяет исходное сообщение коммита.
Прочие различия
Есть ещё несколько различий в поведении, которые большинство людей, вероятно, сочтут несущественными, но которые упоминаются для полноты:
-
Журнал ссылок: Два механизма будут использовать разные формулировки при описании изменений, внесённых в журнал ссылок, хотя оба будут использовать слово "rebase".
-
Сообщения о ходе выполнения, информационные сообщения и сообщения об ошибках: Два механизма предоставляют немного разные сообщения о ходе выполнения и информационные сообщения. Кроме того, механизм apply записывает сообщения об ошибках (например, "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 для примера.
По завершении <ветка> станет текущей веткой.
ИНТЕРАКТИВНЫЙ РЕЖИМ
Интерактивное перемещение означает, что у вас есть возможность редактировать коммиты, которые перемещаются. Вы можете переупорядочить коммиты и удалить их (отсеивая плохие или иным образом нежелательные патчи).
Интерактивный режим предназначен для такого типа рабочего процесса:
-
есть замечательная идея
-
взламывать код
-
подготовить серию для отправки
-
отправить
где пункт 2. состоит из нескольких экземпляров
a) обычное использование
-
закончить что-то достойное коммита
-
коммит
b) независимое исправление
-
осознать, что что-то не работает
-
исправить это
-
закоммитить это
Иногда исправление, сделанное в б.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 ожидает, что результатом этого редактирования будет ровно один коммит. Действительно, вы можете отменить коммит или добавить другие коммиты. Это можно использовать для разделения коммита на два:
-
Начните интерактивное перемещение с
gitrebase-i<коммит>^, где <коммит> — это коммит, который вы хотите разделить. Фактически, подойдёт любой диапазон коммитов, если он содержит этот коммит. -
Отметьте коммит, который хотите разделить, действием "edit".
-
Когда дело дойдёт до редактирования этого коммита, выполните
gitresetHEAD^. Эффект заключается в том, чтоHEADперематывается на один шаг назад, и индекс делает то же самое. Однако рабочий каталог остаётся прежним. -
Теперь добавьте в индекс изменения, которые вы хотите видеть в первом коммите. Вы можете использовать
gitadd(возможно, интерактивно) илиgitgui(или оба) для этого. -
Зафиксируйте теперь текущий индекс с любым сообщением коммита, которое сейчас уместно.
-
Повторяйте последние два шага, пока ваш рабочий каталог не станет чистым.
-
Продолжите перемещение с помощью
gitrebase--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: после
gitfetchстарая верхушка 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,
gitrebaseбудет использовать сокращённые имена команд в списке задач, что приведёт к чему-то вроде этого: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
-
Текстовый редактор, используемый
gitrebase-iдля редактирования файла инструкций перемещения. Значение должно интерпретироваться оболочкой при его использовании. Может быть переопределено переменной средыGIT_SEQUENCE_EDITOR. Если не настроено, вместо него используется редактор сообщений коммитов по умолчанию.
GIT
Является частью пакета git[1]