VS 2013 C#和Git:.csproj文件在拉动时不合并

我和一个朋友正在使用带有Git的VS 2013 Express( 而不是 VS Git插件)来编写一个用C#编写的项目,请注意,我们遇到了问题。 我们的工作流程设置如下:我们有一个中央存储库,我们每个都有自己的存储库分支,我们单独处理。 当我们的个人工作完成后,我们将推送到中央存储库。 当我们想要与中央存储库同步时,我们拉。

问题是,当我们拉,csproj文件随机更新。 有时它们会正确更新,并且自上次拉取后添加的文件正确显示在VS中,有时csproj文件完全不受影响。

这很奇怪,因为csproj在其他任何地方都得到了正确的更新,包括中央存储库,当我们拉动它时,它有时不能正确更新。

在我们的.gitattributes文件中,我们将.csproj设置为merge=union

我们在拉动时执行的命令是git pull upstream ,其中upstream只是指向我们中央存储库的远程。

有任何想法吗?

我将根据Edward Thomson的评论将其作为答案,其中包含此链接到csproj文件中的合并冲突(haacked.com/archive/2014/04/16/csproj-merge-conflicts) 。 请注意,我对Visual Studios,C#或Windows一无所知,但我确实知道git。 🙂

问题是,当我们拉,csproj文件随机更新。 有时它们会正确更新,并且自上次拉取后添加的文件正确显示在VS中,有时csproj文件完全不受影响。

首先,我们来做一些简短的评论说明:

  1. git pull只是git fetch然后是git merge 。 你可以告诉Git做一个rebase 。 根据您的开发流程,这可能是一个好主意,但不会改变这个特定问题,因为……
  2. Git中没有其他任何东西可以进行合并提交 ,但……
  3. 其他几个命令,包括git rebase ,使用合并机制
  4. 推送( git push永远不会进行任何合并,所以你只会在“我和其他人做过某些事情之后让我得到新东西”的情况下看到问题。 即使这样,你是否看到问题在很大程度上取决于你和别人做了什么。 这是因为git mergegit rebase使用的合并机制并不那么聪明。

现在让我们看看底层问题,它(基于链接)是这些*.csproj文件包含XML :结构化数据,git的内置面向文本的合并操作无法正确合并。

当在git diff输出中,两个不同的开发线(合并的分支或提交)对单个文件的同一区域进行不同的更改时,更改发生冲突。 当两个编辑者无法就拼写达成一致时,一个典型的例子出现在文件中。 例如,我之前做了这个改变:

 diff --git a/plates.tex b/plates.tex index 09939ca..3dfc610 100644 --- a/plates.tex +++ b/plates.tex @@ -15,7 +15,7 @@ that I took on a trip to parts of Australia in February of 2010 \end{plate*} The kangaroo is probably the most widely known marsupial. There are actually four species of large kangaroo: -the red, the eastern and western gray, and the antilopine. +the red, the eastern and western grey, and the antilopine. There are also smaller tree-kangaroos and rat-kangaroos. \begin{plate*}[h] 

如果我将这个与其他对diff中显示的任何一行进行不同更改的其他人合并,但是留下字母a拼写的“灰色”,我会发生冲突。 例如,如果我的编辑要坚持拼写“kangaru”这个词,那么这些变化就会发生冲突:

 Auto-merging plates.tex CONFLICT (content): Merge conflict in plates.tex Automatic merge failed; fix conflicts and then commit the result. 

当git遇到相互冲突的变化时,通常的反应是简单地声明存在冲突并停止。 它会给你留下一个工作树版本的文件,其中包含冲突标记<<<<<<< ======= >>>>>>>围绕冲突的两边(以及

| 当且仅当你将merge.conflictstyle设置为diff3

|高于基本版本:

 \end{plate*} <<<<<<< HEAD The kangaru is probably the most widely known marsupial. There are actually four species of large kangaru: the red, the eastern and western gray, and the antilopine. There are also smaller tree-kangarus and rat-kangarus. 

| merged common ancestors The kangaroo is probably the most widely known marsupial. There are actually four species of large kangaroo: the red, the eastern and western gray, and the antilopine. There are also smaller tree-kangaroos and rat-kangaroos. ======= The kangaroo is probably the most widely known marsupial. There are actually four species of large kangaroo: the red, the eastern and western grey, and the antilopine. There are also smaller tree-kangaroos and rat-kangaroos. >>>>>>> master \begin{plate*}[h]

但是,这是默认行为。 您可以通过命令行开关.gitattributes文件更改默认值。

你选择了union merge, git文档有所改进 :

union

对文本文件运行3向文件级别合并,但从两个版本中获取行,而不是留下冲突标记。 这往往会以随机顺序在结果文件中保留添加的行, 用户应该validation结果。 如果您不理解其含义,请不要使用此function。

(我的粗体)。 不过,这里的简短版本是git会相信合并成功(好吧,它确实成功了)但是会通过生成无效的XML文件来实现。 在链接的haacked.com页面上有一些关于*.csproj文件出错的确切方法的例子,但这通常适用于任何联合合并:它不够聪明,无法获得正确的结果,并且几乎没有它的位置合理的司机。 在某些情况下手动调用它是有道理的,然后查看文件并手动进行任何修正,但由于它只是成功并让合并继续进行,所以你必须非常小心地将它放在.gitattributes

理想情况下,我们希望有一个合并驱动程序,它可以理解XML格式 .csproj文件的意图(单独的XML格式化是不够的,因为标记的语义与语法无关)。 由于我不在Windows上使用VS,我只能再次引用haacked.com文章:

另一种方法是为Git编写一个合适的XML合并驱动程序,但这是一个相当大的挑战,因为我的同事Markus Olsson可以certificate这一点。 如果它很容易,甚至是中等难度,那就已经完成了。 虽然我想知道我们是否将它限制为常见.csproj问题我们可以编写一个不完美但足以处理常见合并冲突的问题吗? 也许。

如果内容像示例XML一样简单,我认为这样的驱动程序不会太难,所以我怀疑它们变得更复杂。