Источник: Nuances of Programming
rerere — сокращение от «reuse recorded resolution» (повторное использование сохраненных разрешений конфликтов). С помощью этой команды Git запоминает, каким образом был разрешен конфликт, чтобы при возникновении подобного, разрешить его автоматически.
Рассмотрим сценарии, в которых может пригодиться эта функциональность.
Сценарии
- Допустим, у вас есть ветка темы, которую вы объединяете с главной для поддержания актуального состояния. При этом необходимо избежать засорения истории множеством промежуточных коммитов. С помощью rerere можно периодически выполнять слияние, разрешать конфликты, а затем прерывать слияние. При завершении ветки темы можно выполнить финальное слияние, а rerere разрешит все проблемы автоматически.
- Допустим, вы объединяете множество изменений ветки темы с тестовой веткой. При возникновении ошибки в тестовой ветке можно отменить слияние, исправить ошибку и выполнить повторное слияние без повторного разрешения конфликтов.
Как это работает
Для запуска rerere введите следующую команду:
$ git config --global rerere.enabled true
Допустим, у нас есть файл с именем script.sh со следующим содержимым:
В главной ветке изменяем слово «Hello» на «Hola», а в ветке темы — «World» на «Git»:
При объединении двух ветвей возникает конфликт слияния:
Это обычный конфликт слияния, но с дополнительным оператором «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 сохраняет запись решения в папке .git/rr-cache. Заглянув в репозиторий, вы обнаружите файл preimage:
$ tree .git/rr-cache
.git/rr-cache
└── 54db390f1318184c7fb941c7c688546bdec9590a
└── preimage
Запись исправления путем разрешения конфликта
Попробуем разрешить этот конфликт, объединив «Hola» в главной ветке и «Git» в ветке темы. В результате получаем «Hola Git». Запустите rerere diff еще раз, чтобы проверить сохраненную информацию:
Чтобы rerere запомнил разрешение конфликта, подготовьте файл и зафиксируйте изменение:
rerere сохранил разрешение для ‘script.sh’ или пост-образ. Представим изменение с помощью диаграммы:
Это исправление теперь находится в 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’ с помощью предыдущего разрешения). Заглянув в файл, мы обнаружим, что проблема уже решена:
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