13,8K подписчиков

Команда Git Rerere — автоматизируйте решения для устранения конфликтов слияния

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов).

Источник: Nuances of Programming

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов). С помощью этой команды Git запоминает, каким образом был разрешен конфликт, чтобы при возникновении подобного, разрешить его автоматически.

Рассмотрим сценарии, в которых может пригодиться эта функциональность.

Сценарии

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

Как это работает

Для запуска rerere введите следующую команду:

$ git config --global rerere.enabled true

Допустим, у нас есть файл с именем script.sh со следующим содержимым:

В главной ветке изменяем слово «Hello» на «Hola», а в ветке темы — «World» на «Git»:

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов).-2

При объединении двух ветвей возникает конфликт слияния:

Это обычный конфликт слияния, но с дополнительным оператором «Recorded preimage for ‘script.sh'» (сохранение пред-образа для ‘script.sh’). При запуске git rerere status вместо git status можно выяснить, записан ли pre-merge-статус или пред-образ:

$ git rerere status
script.sh

Ниже показана информация, полученная с помощью git rerere diff и git diff:

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов).-3

Rerere сохраняет запись решения в папке .git/rr-cache. Заглянув в репозиторий, вы обнаружите файл preimage:

$ tree .git/rr-cache
.git/rr-cache
└── 54db390f1318184c7fb941c7c688546bdec9590a
└── preimage

Запись исправления путем разрешения конфликта

Попробуем разрешить этот конфликт, объединив «Hola» в главной ветке и «Git» в ветке темы. В результате получаем «Hola Git». Запустите rerere diff еще раз, чтобы проверить сохраненную информацию:

Чтобы rerere запомнил разрешение конфликта, подготовьте файл и зафиксируйте изменение:

rerere сохранил разрешение для ‘script.sh’ или пост-образ. Представим изменение с помощью диаграммы:

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов).-4

Это исправление теперь находится в postimage:

Содержимое предобраза и постобраза.
Содержимое предобраза и постобраза.

Таким образом, мы выполнили запись разрешения с помощью git rerere.

Для каждого файла, содержащего конфликт, git создает новую директорию с хешем, в которой будут находиться «пред-образ» и «пост-образ».

  • Когда rerere видит конфликт, он создает «пред-образ», содержимое которого такое же, как при запуске команды git diff.
  • Соответственно, «пост-образ» — это то, как выглядит файл после разрешения конфликта.

Как работает rerere:

Когда rerere видит конфликт для script.sh, он просматривает соответствующую директорию rr-cache, находит «пред-образ», который соответствует конфликту, и изменяет файл в рабочей директории для соответствия «пост-образу».

Воспроизведение конфликта для автоматического разрешения

Проверим, решится ли конфликт автоматически. Отменяем слияние, а затем перемещаем ветку темы поверх главной с помощью команды git reset -—hard HEAD^:

$ git reset --hard HEAD^
HEAD is now at ca1bf2b Change Hello to Hola

Затем извлекаем ветку темы и перемещаем ее:

Возникает тот же конфликт, однако появляется строка Resolved ‘script.sh’ using previous resolution (Разрешение ‘script.sh’ с помощью предыдущего разрешения). Заглянув в файл, мы обнаружим, что проблема уже решена:

rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов).-6

git diff также показывает, как проблема была решена автоматически:

Процесс перемещения
Процесс перемещения

Добавив следующий код, мы завершаем процесс перемещения:

$ git add script.sh
$ git rebase --continue
Applying: Change World to Git

Еще одна настройка

Несмотря на то, что rerere автоматически разрешает конфликт, исправленные файлы остаются в состоянии unstaged. Это означает, что git add <file> необходимо выполнить вручную.

Чтобы rerere автоматически индексировал исправленные файлы, нужно воспользоваться следующей командой:

$ git config --global rerere.autoupdate true

Теперь rerere автоматически исправляет и индексирует файлы.

Продолжите перемещение для завершения:

$ git rebase --continue
Applying: Change World to Git

Заключение

Если вы выполняете множество повторных слияний, хотите поддерживать актуальность ветки темы с главной веткой или часто выполняете перемещение, то воспользуйтесь rerere. Просто включите его с помощью git config --global rerere.enabled true и предоставьте Git всю оставшуюся работу.

Читайте также:

Читайте нас в телеграмме и vk

Перевод статьи Minh Pham: The Git Rerere Command — Automate Solutions to Fix Merge Conflicts