Сначала короткое примечание:
Чтобы git распознал файлы sql как текст, я добавил
.sql diff
в файл .gitattributes ...
Строка .gitattributes
должна читаться как *.sql diff
(я исправил связанный ответ, который касается вопроса о том, как заставить git diff
обработать файл как текст).Однако, если файл действительно является текстом, вам может потребоваться или даже понадобиться *.sql text
.
Или, возможно, лучше: example_StoredProcedure.sql text
, т. Е. Не all .sql
файлов, только этот один конкретный файл.Мне также любопытно посмотреть, достаточно ли просто отметить его diff
!
(Разница в том, что атрибут diff
говорит Git, как показать файл в git diff
выводе, 1 , в то время как text
сообщает Git, что вместо использования встроенного алгоритма угадывания для всех целей следует использовать настройку, чтобы определить, является ли файл текстовым. Алгоритм угадывания состоит из сканированияначальный фрагмент содержимого файла, чтобы увидеть, сколько «текстоподобных» символов существует по сравнению с «нетекстовыми» символами. Вероятно, должно быть специальное значение для маркеров порядка байтов UTF-8 вверху, но нет . Любопытно, что во время фильтрации есть явные проверки .)
1 Ну, на самом деле это больше, чем просто показывает , но я думаю, что это хороший способ начать думать о проблемах.Обратите внимание, что вы можете увеличить настройку diff
с помощью драйвера .Мне не ясно, как слияние файлов низкого уровня взаимодействует с драйвером diff, и у меня нет времени экспериментировать с ним прямо сейчас.
Более подробное объяснение
warning: Cannot merge binary files: example_StoredProcedure.sql (... vs ...)
говорит нам, что вы правы, что Git рассматривает три версии example_StoredProcedure.sql
как двоичные.(Я вижу, вы добавили этот вывод после первоначального вопроса; хорошо, потому что это ключ!)
Но почему я сказал три версии, когда строка продолжает говорить:
HEAD vs. 4830c5886d3e1eac5ac76d1d49496afb43f444c3
Git немного ленив здесь: все слияния включают три входа, а не только два.Одним из них является тот, который вы предоставляете явно - или, как в этом случае, git pull
run git merge
и git pull
сам предоставили большой некрасивый хэш-идентификатор
4830c5886d3e1eac5ac76d1d49496afb43f444c3
.
Второй - или, может быть, я должен сказать первый - вход для слияния - это всегда текущий коммит , он же HEAD
.Обычно вы получаете это, находясь на ветке в первую очередь: HEAD
называет имя ветки, имя ветки идентифицирует коммит, и именно здесь вы хотите, чтобы завершился финальный коммит слияния, так что все это объединяется.
Третий ввод - это то, что Git вычисляет для вас, основываясь на HEAD
и других или --theirs
коммитах: Git просматривает достаточное количество графов коммитов, чтобы найти лучший общийКоммит ancestor. 1 Именно этот третий вход - коммит общего предка - определяет , какие файлы нужно объединить , и если файл нуждается в объединении, встроенный драйвер слияния должен использовать diffчтобы получить текстовые изменения для слияния.Как для этого, так и для git diff
, в Git встроен разностный движок (изменен с LibXDiff ).
Следовательно, Git, по сути, может работать:
git diff --find-renames <merge base commit> HEAD
чтобы увидеть, что мы сделали с каждым из наших файлов, и:
git diff --find-renames <merge base commit> <other commit>
, чтобы увидеть, что они сделали с каждым из наших файлов.Тогда:
Если мы изменили файл, а они его вообще не трогали, объединить легко: возьмите наш.
Если они изменили файл, а мы его вообще не трогали, объединить легко: взять их.
Если мы оба изменили файлно сделал новый файл точно таким же, объединение легко: взять любой (наш, действительно, так как он на месте).
В противном случае, попытка объединить изменения .
ДляИз соображений скорости Git использует хэш-идентификаторы (хэши «blob» для содержимого файла), чтобы выполнить первые три пункта без необходимости запуска различий на уровне файлов.Это может и делает, объединяет несконфликтные изменения двоичного файла.Это только последний этап, когда все три хэша BLOB-объектов отличаются друг от друга, и требуется текстовый дифференциал, чтобы объединить изменения.
Очевидно, что если Git не может преобразовать файл, он не может объединить два вывода diff.Но делает ли маркировка файла текстовым (<em>pattern</em> diff
в .gitattributes
) слияние?Что произойдет, если вы установите драйвер diff , использует ли этот код слияния низкоуровневый файл?Он «хочет» использовать внутренний интерфейс xdiff для поиска блоков;это намного проще, чем интерпретировать вывод текста из драйвера;вам, вероятно, придется определить драйвер слияния , чтобы получить обнаруженный как двоичный файл для слияния, даже если вы пометили его как diff
.
1 Во всех случаях, но особенно в проблемных случаях, когда существует более одного лучшего общего предка, поведение git merge
фактически зависит от выбранной вами стратегии .Обычная стратегия recursive
объединяет базы слияния, фиксирует результат, а затем использует этот коммит в качестве базы слияния!Другие стратегии слияния работают иначе.