在合并冲突期间,为什么git会将sql文件解释为二进制文件?

时间:2018-08-25 10:28:06

标签: sql git git-merge merge-conflict-resolution

我遇到了解决sql文件中合并冲突的问题。

MenkeTTA@909086 MINGW64 //FILE0019 (master)
$ git pull
remote: Microsoft (R) Visual Studio (R) Team Services
remote: Found 5 objects to send. (5 ms)
Unpacking objects: 100% (5/5), done.
From https://***
d58a69b..4830c58  master     -> origin/master
warning: Cannot merge binary files: example_StoredProcedure.sql (HEAD vs.    4830c5886d3e1eac5ac76d1d49496afb43f444c3)
Auto-merging WRR - example_StoredProcedure.sql
CONFLICT (content): Merge conflict in example_StoredProcedure.sql 
Automatic merge failed; fix conflicts and then commit the result.

在创建合并冲突时,git不会像通常的结构那样创建具有竞争性更改的预合并文件:

/ SQL文件/

<<<<<<< HEAD
competing change A
=======
competing change B
>>>>>>> branch-a

Git将两个文件都视为二进制文件-但仅适用于合并冲突操作(正常的无冲突合并有效)。我可以选择自己的文件版本或从遥控器中拉出的竞争文件作为下一次推送的新头。

我复制了与普通.txt文件的冲突。 Git正在处理合并冲突,然后按预期方式创建了一个包含两个相互竞争的更改/提交的预合并文件,在这里我可以手动修复所需的代码。

要使git将sql文件识别为我添加的文本

.sql diff
像描述here一样

.gitattributes文件。有谁知道在使用sql文件时,如何使git能够使用竞争提交的两个版本来创建普通的预合并文件?

1 个答案:

答案 0 :(得分:0)

首先,请注意:

  

要使git将sql文件识别为我添加的文本

.sql diff
     

到.gitattributes文件...

.gitattributes行应显示为*.sql diff(我已经修正了链接的答案,这是有关使git diff将文件视为文本的问题)。但是,如果文件确实是 文本,则可能需要甚至需要*.sql text

或者,也许更好:example_StoredProcedure.sql text,即不是全部 .sql个文件,而只是这个一个特定文件。我也很好奇,看看是否仅将其标记为diff就可以了!

(不同之处在于diff属性告诉Git如何在git diff输出中显示文件, 1 ,而text告诉Git而不是使用其内置的猜测算法,出于 all 的目的,应使用该设置来确定文件是否为文本。猜测算法包括扫描文件内容的初始块,以查看有多少“类似于“非文本”字符与“非文本”字符。可能在顶部对UTF-8字节顺序标记应留有特殊的余量,但there isn't。奇怪的是,在过滤期间,{{3 }}。


1 嗯,实际上它不仅仅是显示 所涉及的内容,但是我认为这是开始思考这些问题的好方法。请注意,您可以使用 driver 扩展diff设置。对我来说,目前尚不清楚低级文件合并如何与diff驱动程序交互,而我现在没有时间进行试验。


更长的解释

warning: Cannot merge binary files: example_StoredProcedure.sql (... vs ...)

告诉我们您是正确的,Git将example_StoredProcedure.sql的三个版本视为二进制。 (我看到您在最初的问题之后添加了此输出;这很重要,因为这是关键!)

但是当行继续说:

时,为什么还要说三个版本呢?
HEAD vs.    4830c5886d3e1eac5ac76d1d49496afb43f444c3

这里的Git有点懒:所有合并都涉及三个输入,而不仅仅是两个。其中之一就是您明确提供的代码-或者,在这种情况下,git pull运行了git merge,而 git pull本身提供了一个丑陋的哈希ID {{ 1}}。

第二个-或者也许我应该说第一-合并的输入始终是当前提交,也称为 4830c5886d3e1eac5ac76d1d49496afb43f444c3。通常,您首先需要在分支上进行操作:HEAD命名分支名称,分支名称标识提交,这是您希望进行最终合并提交的位置,因此非常适合在一起。

第三个输入是Git根据HEAD和其他或HEAD提交为您计算的输入:Git遍历了足够的提交图以查找最佳共同祖先提交。 1 这是第三个输入(共同祖先提交)确定哪些文件需要合并,如果文件确实需要合并,则内置合并驱动程序需要使用差异来合并文本更改。对于这两者和--theirs,Git都内置有there are explicit checks(从differencing engine修改)。

因此,Git实际上可以运行:

git diff

查看我们对每个文件做了什么,并且:

git diff --find-renames <merge base commit> HEAD

查看它们对我们每个文件的处理方式。然后:

  • 如果我们更改了文件却根本不触摸文件,则合并很容易:选择我们的文件。

  • 如果他们更改了文件但我们根本没有碰过它,则合并很容易:接受他们的文件。

  • 如果我们都更改了文件,但使新文件完全相同,则合并很容易:选择其中一个(我们确实是这样,因为它就位了)。

  • 否则,尝试合并更改

出于速度原因,Git使用哈希ID(用于文件内容的“ blob”哈希)来完成前三个项目符号点,而不必启动文件级差异。这可以并且确实可以合并无冲突的二进制文件更改。只是最后一个阶段,所有三个blob哈希都不同,这需要文本差异来组合更改。

很明显,如果Git无法对文件进行差异化,则它无法合并两个差异输出。但是,仅将文件标记为可文本扩散(git diff --find-renames <merge base commit> <other commit> 中的pattern diff)是否会使合并继续进行?如果设置了diff driver ,会发生什么情况,低级文件合并代码是否使用该驱动程序?它“希望”使用xdiff内部接口来找到帅哥。这比解释驱动程序的文本输出要容易得多;您可能必须定义合并驱动程序,以将检测到的二进制文件进行合并,即使您已将其标记为.gitattributes


1 在所有情况下,但特别是在存在多个最佳共同祖先的问题情况下,diff的行为实际上取决于您的策略选择。通常的git merge策略将合并合并基础,提交结果,然后使用该提交作为合并基础!其他合并策略的工作方式有所不同。