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


83

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

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

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

редактировать: вариант 4. описание


6
Это не будет точный ответ, который вы ищете, но по той же причине, по которой я git fetchсначала делаю , а затем использую git difftool <file> FETCH_HEAD, поэтому я могу вручную применить изменение в удаленной ветке к локальному.
MHC

MHC: это хороший трюк (особенно если он сохраняется в скрипте для каждой параллельной ветки + в сочетании с предотвращением автоматического слияния файлов). Главный недостаток состоит в том, что в командном рабочем процессе есть вероятность, что кто-то забудет этот шаг и вместо этого просто выполнит обычное слияние.
Степан

2
Настройка -mergeне мешает вам объединять файлы, она просто заставляет вас делать это вручную, например, с помощью mergetool. Разве это не то, что тебе нужно?
CB Bailey,

Это 90% того, что я хочу. Я бы хотел, чтобы слияние выполнялось автоматически, но для этого конфиденциального файла слияние считается конфликтом, даже если его нет, поэтому ручная проверка выполняется каждый раз принудительно.
Степан

@Stepan У меня похожая ситуация, поэтому я хочу кое-что прояснить. Что вы говорите о том, что -mergein .gitatttributes git mergeничего не делает, и вся работа должна быть прекращена с помощью инструмента слияния? Итак, нет <<<<< ===== >>>> для использования инструмента слияния, верно? И решение Дэна это обеспечивает?
Nero gris

Ответы:


60

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

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

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

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

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

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

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

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

*.sensitive merge=verify

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


Большое спасибо за это подробное руководство!
Степан

13
Похоже, что драйвер слияния не вызывается в «очевидных» решениях. Например, если файл был изменен только в одной ветке, и вы выполняете слияние, «чувствительный» файл будет перезаписан, и драйвер слияния не будет вызван. Есть способ исправить это?
VitalyB 09

Будет ли это вести себя так, как предлагает @VitalyB? благодаря!
filippo 06

1
Это работает, но есть ли способ сделать это глобальным параметром для всех репозиториев на машине? Кроме того, есть ли способ вызвать его из командной строки? Я бы хотел, чтобы это было так просто, как изменение стратегии слияния в командной строке.
user1748155 01

4
добавление в комментарий @VitalyB. Слияние также не появляется, если обе ветви внесли одинаковые изменения в файл. Например, обе ветки увеличили версию на 1, а вы хотели бы увеличить на 2 при попытке слияния ... Очень практическая проблема, пока не
решенная

1

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

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)

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


Мне нравится идея «одноразового» решения (я только что столкнулся с таким случаем), однако у меня это не сработало. Git выполнил FF, что привело к неудачному слиянию (по сути, это было слияние и наше).
Nero gris

@Nerogris Действительно, это не будет работать для слияния с перемоткой вперед. Вы всегда можете добавить параметр --no-ff, но вторая команда не вызовет конфликта, так как нет изменений от общего предка в одной из двух ветвей слияния.
louisiuol

В моей глобальной конфигурации для ff установлено значение false. Когда я сказал, что это слияние FF, я имел в виду, что если бы я не сказал Git, чтобы он этого не делал, он бы сделал это.
Nero gris

0

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

git merge-fileможет использоваться, например, для РАСШИФРОВКИ (и повторного шифрования) файлов перед объединением (!)

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


2
Не могли бы вы подробнее рассказать о ссылке «драйвер слияния для файлов PO», потому что это, похоже, приводит к отказу в доступе для меня? Я надеюсь, что он даст ответ на вопрос stackoverflow.com/questions/16214067/…
Микко Ранталайнен

@MikkoRantalainen заблокирован на работе, поэтому я попробую сегодня вечером дома.
VonC

1
"Драйвер слияния PO-файлов" у меня тоже не работает :(

1
@sampablokuper Согласен: статья заблокирована для "неавторизованного" читателя. Я не знаю почему.
VonC

1
@sampablokuper У меня сейчас нет доступа к этому блогу. Я буду искать его содержание.
VonC
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.