我正在努力对Git的Address:
文件中的某些文件强制执行特定的合并策略(Address:
)。
我一直在处理.git / config和.gitattributes文件,但均未成功,到目前为止,我所管理的工作并未考虑-s recursive -Xours
选项。
.gitattributes
.gitattributes
.git / config
-X
答案 0 :(得分:0)
在合并驱动程序中使用git merge-file
。在这里,您可以指定所需的选项。您要输入--ours
。请注意,这并不总是正确的。您甚至可能想要--union
,但要注意,这也不是很有效。有关尝试对XML文件使用这两种方法的问题,请参见Can git be made to mostly auto-merge XML order-insensitive files?和VS 2013 C# and Git: .csproj files don't merge upon pulling。
首先,让我们定义Git使用它们的方式:
策略 是您传递给-s
的{{1}}标志的参数:git merge
,git merge -s recursive
,{{1 }}或git merge -s resolve
。 (实际上,您永远不会显式地使用最后一个-而是,如果您要求Git合并多个头,则暗含该提示。)
换句话说,这是名称git merge -s ours
,git merge -s octopus
或ours
之一。从理论上讲,您也可以编写自己的Git合并策略,但这并不是很简单的(是如此之多,以至于我没有听说过有人这样做,尽管这可能并不意味着什么)。
一个策略选项您传递给recursive
标志的参数,例如resolve
或-X
。我觉得这是一个坏名字,因为很容易与 strategy 混淆。说话时尤其如此:您是说“策略”然后停止说话,但表示“策略选择”而您只是被打扰了,还是您说了“策略”并停止说话而实际上是“策略”?我喜欢称这些 extended options (扩展选项),它们与-X ours
标志配合使用,该标志则代表“ eXtended”。)
驱动程序是您在-X rename-threshold=<number>
文件中定义的。有几种风格(过滤器,差异和合并);在这里,我们关注合并驱动程序。合并驱动程序由策略 调用;从理论上讲,驾驶员可以至少使用某些扩展选项,但实际上却没有。 (Git应该定义-X
-扩展器,以提供它们,和/或在环境变量中提供它们;这将相对简单。)
牢记这些定义,很容易看出这一点:
我正在努力对Git的
.gitattributes
文件中的某些文件强制执行特定的合并策略(%
)。
实际上是不可能的。无论您在这里指的是 strategy 还是 strategy选项,这都是事实:两者都是在我们进入{{1 }}文件。
尽管并不一定全部丢失!
您特别提到了-s recursive -Xours
,为此您需要一个合并驱动程序(可以在.gitattributes
中定义的驱动程序),该合并驱动程序进行文本样式合并,但是如果发生冲突,则使用“我们的”, la扩展选项“我们的”。相反,您拥有的是一个合并驱动程序,它将执行“我们的” 策略合并:完全忽略合并库及其更改,仅获取文件的“我们”版本。
将尝试与Whats the Proper usage of .gitattributes with merge=ours处的答案进行比较:唯一的区别是驱动程序名称的拼写,在此情况下您使用.gitattributes
而不是pom.xml
。驱动程序的名称并不重要,只要它不是已知的魔术名称(.gitattributes
,recursive
和ours
)之一即可:Git将运行您的驱动程序而不是执行自己的文件级合并,当它确定要执行的文件级合并时。
The gitattributes documentation关于定义合并驱动程序的说法如下:
合并驱动程序的定义是在
text
文件中完成的,而不是在binary
文件中进行的,因此严格来说,本手册页是谈论它的错误位置。但是...要定义自定义合并驱动程序
union
,请向.git/config
文件(或gitattributes
文件)中添加一个部分,如下所示:filfre
(附带说明:“递归=二进制”不一定是个好建议,但让我们现在点击此处。)
$GIT_DIR/config
变量为驱动程序提供了易于理解的名称。
$HOME/.gitconfig
变量的值用于构造命令以运行以合并祖先的版本([merge "filfre"] name = feel-free merge driver driver = filfre %O %A %B %L %P recursive = binary
),当前版本(merge.*.name
)和其他分支的版本({{1 }}。在构建命令行时,这三个标记将替换为保存这些版本内容的临时文件的名称。此外,merge.*.driver
将替换为冲突标记大小(请参见下文)。
也就是说,%O
命名包含文件的基于合并版本的临时文件,而%A
和%B
命名包含%L
和{{ 1}}版本的文件。作为filter-driver-writer的工作是想出一条执行合并的命令:
期望合并驱动程序通过覆盖将合并结果保留在以
%O
命名的文件中;如果它能够干净地合并它们,则退出状态为零;如果存在冲突,则合并状态为非零。
已经执行了合并,您应该用结果将%A
命名的文件覆盖。由于以%B
命名的文件包含--ours
的内容,因此不执行任何操作但随后退出的驱动程序声明用于合并--theirs
与%A
和{{ 1}}是%A
中已经的任何东西。
换句话说,这就像我们的策略。这不像是在冲突情况下合并有利于我们,使用%A
策略加选项进行解决或递归。但是您根本不需要整个 strategy ,因为它可以处理整个提交。您需要单个文件操作。这是--ours
出现的地方。不过,让我们现在结束其余的描述:
%O
变量指定当有多个以上合并祖先之间的内部合并时,在调用合并驱动程序时要使用的其他合并驱动程序。如果未指定,则驱动程序本身将用于内部合并和最终合并。
这有点令人困惑,但是它仅将应用于递归策略,即使在%A
打印出多个哈希ID的情况下,也是如此。大多数时候,这里根本不需要任何特殊的东西。使用%B
等同于为此文件设置%A
的策略,因为-Xours
内部合并驱动程序仅采用git merge-file
版本,这意味着当{ {1}}反复合并合并基础,每次都只获得第一个合并基础版本。
多个合并基数很少见,并不总是知道如何处理它们,但是省略任何设置都会导致内部递归合并使用合并驱动程序,这在大多数情况下可能很好。您的驱动程序不会被递归调用 ;递归发生在调用驱动程序之外。如果您将递归视为一棵树,则实际上是将驱动程序称为后遍历。
合并驱动程序可以通过占位符
merge.*.recursive
了解合并结果将存储在其中的路径名。
更具体地说,将以git merge-base --all HEAD <theirs>
扩展为recursive = binary
,resolve
扩展为binary
和ours
扩展为{ {1}}。不管您是被调用来合并三份-s recursive
,三份%P
还是三份%A
,都是如此:临时文件名将为{{1 }}。
如果出于任何原因想要知道文件的“真实名称”是.mergetmpA12345
或%B
或其他任何内容,则{em> 1}}。不要立即使用该文件立即,它既不是输入也不是输出。这只是工作树文件的最终名称-一旦合并全部完成,它就是(或将是)(最终)名称。不过,目前,.mergetmpB12345
扩展到的名称(某些%O
)就是您应该使用的名称(您应该在其中传递合并的文件数据)。
.mergetmpO12345
The git merge-file
documentation告诉我们README.txt
的用法是:
git合并文件 [
main.py
[pom.xml
[.merge<something>
]]] [README.txt
|main.py
|%P
| [%A
|.merge<something>
| [git merge-file
|git merge-file
] [-L <current-name>
] [-L <base-name>
[-L <other-name>
]--ours
]--theirs
三个--union
选项是标签,-p
将放置在冲突的部分周围。 --stdout
选项设置-q
将放置在冲突部分周围的标记的大小。默认值与Git自己的内部合并非常相似,因此很多时候不需要这些默认值。对于您的情况,您将指定--quiet
,这意味着永远不会解决未解决的冲突,因此不需要--marker-size=<n>
和--
。>
no-
或diff3
或<current-file> <base-file> <other-file>
标志告诉-L
如何处理冲突。其中两个标志与扩展选项git merge-file
和--marker-size
相同;您会获得常规Git合并中不可用的第三个。
git merge-file
或--ours
选项再次影响显示冲突的方式:它们等效于分别将-L
设置为--marker-size
或--ours
。由于您不会有冲突,所以这些都是无关紧要的。
最后,您需要命名三个文件:一个包含当前(“我们的”)版本数据,一个包含合并的基本版本,另一个包含另一个(“其”)版本。 --theirs
完成后,它将使用合并的数据重写当前版本的文件。您的--union
方便地构建了三个这样的文件,并以这种方式完全使用它们,因此您只需要提供git merge-file
选项:
-X ours
和:
-X theirs
由于使用--diff3
选项,即使结果不是有效的XML,此合并也将始终成功(--no-diff3
将退出0)。