git-rerere
Имя
git-rerere — повторное использование записанных решений конфликтов слияния
Синтаксис
git rerere [clear | forget <pathspec>… | diff | status | remaining | gc]
Описание
При работе с ветками темы, которые существуют сравнительно долго, разработчику иногда приходится неоднократно разрешать одни и те же конфликты, пока ветки темы не завершены (либо они сливаются с веткой «выпуск», либо отправляются и принимаются в upstream).
Эта команда помогает разработчику в этом процессе, записывая результаты автоматического слияния с конфликтами и результаты ручного разрешения в исходном ручном слиянии, и применяя ранее записанные ручные решения к соответствующим результатам автоматического слияния.
| Примечание | Вам необходимо установить переменную конфигурации rerere.enabled для активации этой команды. |
Команды
Обычно команда git rerere выполняется без аргументов или вмешательства пользователя. Однако она имеет несколько команд, которые позволяют ей взаимодействовать со своим рабочим состоянием.
- clear
-
Сбросить метаданные, используемые rerere, если требуется прервать разрешение слияния. Вызов
git am [--skip|--abort]илиgit rebase [--skip|--abort]автоматически вызовет эту команду. - forget <pathspec>
-
Сбросить решения конфликтов, которые rerere записала для текущего конфликта в <pathspec>.
- diff
-
Отобразить различия текущего состояния разрешения. Это полезно для отслеживания изменений, происходящих во время разрешения конфликтов. Дополнительные аргументы передаются непосредственно команде системы
diff, установленной в PATH. - status
-
Вывести пути с конфликтами, чье разрешение слияния rerere запишет.
- remaining
-
Вывести пути с конфликтами, которые не были автоматически решены rerere. Это включает пути, чьи решения не могут быть отслежены rerere, такие как конфликтующие подмодули.
- gc
-
Обрезать записи о слияниях с конфликтами, которые произошли давно. По умолчанию удаляются неразрешенные конфликты старше 15 дней и разрешенные конфликты старше 60 дней. Эти значения по умолчанию контролируются переменными конфигурации
gc.rerereUnresolvedиgc.rerereResolvedсоответственно.
Обсуждение
Когда ваша ветка темы изменяет перекрывающуюся область, которую ваша ветка master (или upstream) затронула с момента разветвления вашей ветки темы, вы можете захотеть проверить ее с последней версией master, даже прежде чем ваша ветка темы будет готова к отправке в upstream:
o---*---o topic
/
o---o---o---*---o---o master Для такого теста вам нужно как-то слить master и тему. Один из способов сделать это — получить master в ветку темы:
$ git switch topic
$ git merge master
o---*---o---+ topic
/ /
o---o---o---*---o---o master Коммиты, помеченные *, затрагивают одну и ту же область в одном и том же файле; вам нужно разрешить конфликты при создании коммита, помеченного +. Затем вы можете проверить результат, чтобы убедиться, что ваша текущая работа по-прежнему работает с последней версией master.
После этого тестового слияния существует два способа продолжения работы над темой. Самый простой — продолжить работу на основе коммита тестового слияния +, а когда ваша работа в ветке темы будет готова, получить ветку темы в master и/или попросить upstream получить из вашей ветки. Однако к этому времени master или upstream могут быть обновлены с момента тестового слияния +, в этом случае итоговая схема коммитов будет выглядеть так:
$ git switch topic
$ git merge master
$ ... work on both topic and master branches
$ git switch master
$ git merge topic
o---*---o---+---o---o topic
/ / \
o---o---o---*---o---o---o---o---+ master Однако, если ваша ветка темы долгоживущая, в ней будет много таких коммитов «слияния с master», что излишне захламляет историю разработки. Читатели списка рассылки Linux kernel могут помнить, что Линус жаловался на такие слишком частые тестовые слияния, когда участник подсистемы просил получить из ветки, полной «бесполезных слияний».
В качестве альтернативы, чтобы сохранить ветку темы чистой от тестовых слияний, вы можете удалить тестовое слияние и продолжить разработку на основе вершины до тестового слияния:
$ git switch topic
$ git merge master
$ git reset --hard HEAD^ ;# rewind the test merge
$ ... work on both topic and master branches
$ git switch master
$ git merge topic
o---*---o-------o---o topic
/ \
o---o---o---*---o---o---o---o---+ master Это оставит только один коммит слияния, когда ваша ветка темы будет окончательно готова и слита с веткой master. Для этого слияния вам нужно будет разрешить конфликт, внесенный коммитами, помеченными *. Однако этот конфликт часто является тем же конфликтом, который вы разрешили при создании тестового слияния, которое вы удалили. git rerere помогает вам разрешить этот окончательный конфликтный merge, используя информацию из вашего предыдущего ручного разрешения.
Выполнение команды git rerere сразу после автоматического слияния с конфликтом записывает файлы рабочей области с конфликтами с обычными маркерами конфликтов <<<<<<<, =======, и >>>>>>> в них. Позже, после того, как вы закончите разрешение конфликтов, повторное выполнение git rerere запишет разрешенное состояние этих файлов. Предположим, вы сделали это при создании тестового слияния master в ветку темы.
В следующий раз, после обнаружения того же автоматического слияния с конфликтом, выполнение git rerere выполнит трехстороннее слияние между предыдущим автоматическим слиянием с конфликтом, предыдущим ручным разрешением и текущим автоматическим слиянием с конфликтом. Если это трехстороннее слияние разрешается без проблем, результат записывается в файл вашей рабочей области, поэтому вам не нужно разрешать его вручную. Обратите внимание, что git rerere оставляет файл индекса в покое, поэтому вам все равно нужно выполнить окончательную проверку с git diff (или git diff -c) и git add, когда вы удовлетворены.
Для удобства git merge автоматически вызывает git rerere при выходе с ошибкой автоматического слияния и git rerere записывает ручное разрешение, когда это новый конфликт, или повторно использует ранее ручное разрешение, когда это не новый. git commit также вызывает git rerere при коммировании результата слияния. Это означает, что вам не нужно делать ничего особенного (кроме включения переменной конфигурации rerere.enabled).
В нашем примере, когда вы делаете тестовое слияние, ручное решение записывается и будет повторно использовано, когда вы выполните фактическое слияние позже с обновленной веткой master и веткой темы, если записанное решение по-прежнему применимо.
Информация, которую git rerere записывает, также используется при выполнении git rebase. После удаления тестового слияния и продолжения разработки в ветке темы:
o---*---o-------o---o topic
/
o---o---o---*---o---o---o---o master
$ git rebase master topic
o---*---o-------o---o topic
/
o---o---o---*---o---o---o---o master вы можете выполнить git rebase master topic, чтобы привести себя в актуальное состояние перед отправкой вашей ветки в upstream. Это приведет к возврату к трехстороннему слиянию, и оно столкнется с тем же конфликтом, что и тестовое слияние, которое вы ранее разрешили. git rerere будет вызвано git rebase для помощи в разрешении этого конфликта.
[ПРИМЕЧАНИЕ] git rerere полагается на маркеры конфликтов в файле для обнаружения конфликта. Если файл уже содержит строки, которые выглядят так же, как строки с маркерами конфликтов, git rerere может не записать разрешение конфликта. Чтобы обойти эту проблему, можно использовать настройку conflict-marker-size в gitattributes[5].
rerere
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-rerere