Git - как принудительно слить конфликт слияния и вручную слить на выбранный файл

Мы поддерживаем веб-приложение, имеющее общую основную ветвь и множество параллельных ветвей, по одной для каждой установки, каждая из которых имеет несколько конкретных изменений. Исходный код управляется в git, и это потрясающий инструмент, когда нам нужны функции переноса и исправления от ведущей ветки к параллельной. Но мало файлов, которые чувствительны и автоматическое слияние, обычно дают плохие результаты. Таким образом, слияние было бы намного проще, если бы их можно было каким-то образом маркировать, и каждое слияние привело бы к конфликту, требующему ручного слияния.

Я искал ответ:

  1. Я использую опции -no-commit и --no-ff merge, но это не то же самое.
  2. Здесь и здесь кто-то задает один и тот же вопрос, но без решения.
  3. Похоже, что подобный случай заключается в предотвращении объединения файлов с использованием.gitattributes, содержащих: somefile.php merge = ours. Я попытался найти некоторый параметр слияния, который мог бы вызвать конфликт или принудительное ручное слияние, но пока ничего не нашел.
  4. .gitattributes, содержащий: somefile.php -merge, никогда не сливается автоматически и, следовательно, принуждает ручное слияние. Это 90% -ное решение, но я пытаюсь попробовать автоматическое слияние и отмечать его как конфликт, независимо от того, успешно он или нет. Но это так близко к решению. (... спасибо Чарльзу Бейли за разъяснение...)
  5. Кто-то предлагает написать пользовательский драйвер слияния (1, 2), но как это сделать, мне далеко не ясно.

изменить: вариант 4. описание

Ответ 1

Вариант 5, пользовательский драйвер слияния, вероятно, является способом приблизиться к тому, что вы хотите. Это удивительно легко сделать. Ниже приведен пример того, который, я думаю, должен сделать вас очень близким к поведению, которое вы желаете.

Сначала создайте драйвер слияния script под названием merge-and-verify-driver. Сделайте его исполняемым и поместите в подходящее место (возможно, вы захотите проверить этот script на репо, даже, поскольку файл конфигурации репо будет зависеть от него). Git собирается выполнить эту оболочку script для выполнения слияния чувствительных файлов:

#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

Это просто поведение по умолчанию, которое обычно выполняет Git. Главное отличие состоит в том, что script всегда возвращает ненулевое значение (чтобы указать, что конфликт был, даже если слияние было разрешено без конфликтов).

Затем вам нужно сообщить Git о существовании вашего пользовательского драйвера слияния. Вы делаете это в конфигурационном файле repo (.git/config):

[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

В этом примере я поместил merge-and-verify-driver в каталог верхнего уровня репо (./). Вам нужно будет указать путь к script соответственно.

Теперь вам просто нужно предоставить конфиденциальным файлам нужные атрибуты, чтобы при объединении этих файлов использовался пользовательский драйвер слияния. Добавьте это в свой .gitattributes файл:

*.sensitive merge=verify

Здесь я сказал Git, что любой файл с именем, соответствующим шаблону *.sensitive, должен использовать пользовательский драйвер слияния. Очевидно, вам нужно использовать шаблон, подходящий для вашего файла (ов).

Ответ 2

Примечание: в этой статье Написание драйвера слияния git для файлов PO" иллюстрирует виды манипуляций, которые вы можете выполнять при ручном слиянии файл: вы можете предварительно обработать его, чтобы ваше ручное слияние имело определенные данные.

git merge-file можно использовать, например, для DECRYPT ( и повторно зашифровать) файлы перед слиянием (!)

В вашем случае выход из вашего слияния с условием non-0 гарантирует, что слияние будет ручной.

Ответ 3

Кажется, что эти две команды имеют тот же эффект, что и пользовательский драйвер слияния:

git merge --no-commit your_target_branch
git checkout --conflict merge .   (do not forget the . and run it in the top dir of the repository)

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