Dev*_*v01 40 git version-control merge-conflict-resolution
我们是一些在同一个项目上工作的开发人员,我们在项目中使用git.如果我们中的两个或多个碰巧在同一个文件上工作,我们会收到难以处理的git冲突,有时一个开发人员在发生这些冲突时会发生更改.
他们如何在团队中使用git?为了避免git冲突,应该采取什么样的正确流程?
提前致谢.
Chr*_*her 49
在深入了解您的工作流程之前,在花费一些时间或一美元资金重建沟通流程之前,请向您的团队提出三个问题:
.sass或.scss文件,或即时构建XML配置?我们检查一下吗?经过多年的冲突并帮助其他人在集中式工作流程中解决冲突,我提出这三件事导致我们的绝大多数集体冲突痛苦:

在上图中,'!' slice表示合法的合并冲突.在广大大多数可怕合并的来自懒惰空白公约或过于激进的IDE(或偶尔过于refactory开发者).在执行任何其他操作之前,请标准化IDE设置和空白约定.然后让每个人在他们的本地存储库中发出此命令:
# Enable the repository's stock pre-commit hook
mv .git/hooks/pre-commit.sample .git/hooks/pre-commit
Run Code Online (Sandbox Code Playgroud)
每次发出时git commit,该预提交钩子将执行一系列检查,包括git diff --check检查您提交的更改是否引入空白错误的命令的版本.如果确实,将拒绝提交.如果你真的需要解决它,你可以发出git commit --no-verify,但不要:空格错误就像版本控制的未爆炸条例.他们的合并冲突等待发生.
如果要清理空格,重构文件以改进其缩进,或者进行大量纯格式更改,请在隔离的提交中执行,并警告团队首先检查其正在进行的冲突工作.
如果您进行代码审查,请将这些问题作为每个评论者提出的第一个问题:"这个更改设置是否触及了它不应该的任何内容?它是否清理了任何格式?它是否不必要地重构了一个方法?" 如果确实如此,则未通过审核.或者,如果您不能,请确保这些更改与逻辑更改(即在不同的提交中)充分隔离,以使您的历史记录有用.
如果签入生成的目标,则样式表语言,RequireJS和js minifiers也会导致冲突.这些技术创建的文件是构建工件.你不会签入WAR档案; 不要签入SASS编译的CSS文件.或者,如果您认为必须,请使用.gitattributes文件让git将它们视为二进制文件.
如果在完成所有这些操作之后,您仍然存在合并冲突,则会改进工作流程.Gary Fixler的回答是绝对正确的:合法的合并冲突的产生是因为团队不能或不能很好地沟通他们的项目范围.只需确保它的格式规则不是很难执行.
Gar*_*ler 13
嗯,说实话,正确的工作流程包括良好的沟通和管理.团队成员不应经常处理相同的事情并导致冲突.每天站立起来的事情,以及了解团队中每个成员所做的事情的细心经理 - 至少在一般情况下 - 在很多情况下都会有很长的路要走,以限制这一点.
当然,这取决于产品的确切性质,但这更像是一个组织问题,而不是一个git问题.事实上,冲突通常被视为"好"的东西,因为它们让人们从办公桌上站起来,或者互相打电话来讨论冲突的原因,以及未来应该做些什么.这是一个机会,可以确定一个人应该拥有一个区域或一组文件,或者至少是讨论该部分变更的联系人.
除了制定预先计划之外,没有办法避免git冲突,但这在任何版本控制系统中都是同样的问题.任何时候两个人改变相同的代码段,你必须弄清谁赢了.这就是为什么不适合寻找解决方案的版本,而是关注团队的方法和实践.两辆车不能同时通过一个交叉路口,但是发明可以相互穿越的汽车非常困难,所以我们发明了停车标志和交通信号的控制系统.这是一个类似的问题.我们无法真正对同一件事进行两次更改而不是冲突,因此我们必须控制我们如何使用这些文件.
你可以考虑允许锁定git的前端之一,但我不同意这个概念,在不可合并的文件类型之外.我认为最好找出一个更好的团队工作流程,同时,将其作为一个很好地合并文件的机会.我这样做了,现在经过几个月的努力,冲突对我来说并不是一件令人沮丧的事情.
避免冲突只有一种方法:不要让不同的人同时编辑同一个文件.基本上每个文件都有一个所有者,负责所有编辑,谁可以将所有权传递给另一个.只要所有权明确,就可以根据特定功能/分支或日常传递文件的所有权.
如果您发现无法为每个文件提供一个所有者,那么:
您还可以做一些其他事情,它们也可能有所帮助。如果分开贴会更清楚。
您在何处插入新内容将有助于确定您是否会产生冲突。
想象一个员工姓名列表
Andy,
Oliver,
Ivan,
Run Code Online (Sandbox Code Playgroud)
然后 Brad 和 Patrick 加入,他们的名字被添加到列表中。你加了布拉德,我加了帕特里克。我们都将名称添加到列表的底部,然后使用 git 合并我们的列表。结果对 git 用户来说很熟悉:-
Merge branch 'Patrick' into Brad
Conflicts:
names.txt
@@@ -1,4 -1,4 +1,8 @@@
Andy,
Oliver,
Ivan,
<<<<<<< HEAD
+Brad,
=======
+ Patrick,
>>>>>>> Patrick
Run Code Online (Sandbox Code Playgroud)
现在假设我们做了同样的事情,但在我们的列表上强加了一个简单的字母排序规则。现在,当我们合并两个分支时,结果会更令人愉悦:-
Andy,
Ivan,
Oliver,
Run Code Online (Sandbox Code Playgroud)
自己添加一个名称,然后将其他人的更改与 git 合并,以添加另一个名称。
Auto-merging names.txt
Merge made by the 'recursive' strategy.
names.txt | 1 +
1 file changed, 1 insertion(+)
Run Code Online (Sandbox Code Playgroud)
我们得到
Andy,
Brad,
Ivan,
Oliver,
Patrick,
Run Code Online (Sandbox Code Playgroud)
由于我们不知道接下来谁将加入公司,因此我们实际上是随机添加到列表中,并且通过在随机位置插入,文件中位置冲突的可能性较小。
在这样的软件中...
function chess()
{
while (!end_of_game)
{
make_move()
Run Code Online (Sandbox Code Playgroud)
以左大括号开头的行很容易与软件中由单个左大括号组成的其他行混淆。如果像这样编写相同的软件,则将块开始附加到前面的行......
function chess() {
while (!end_of_game) {
make_move()
Run Code Online (Sandbox Code Playgroud)
我个人不喜欢,但 Git 喜欢,有更少的行看起来与 Git 相似并且会被误认为彼此,即 Git 更有可能以与我们相同的方式感知编辑,从而使任何冲突更容易解决解决。
使用注释使相似的线条易于区分。
如果您编写大量 javascript 和 JSON,您可能会有很多看起来有点像这样的行。
}
}
}
)
Run Code Online (Sandbox Code Playgroud)
如果你对事物进行评论,那么它们就可以变得可区分。
}
}
}
) // end of weekdays()
Run Code Online (Sandbox Code Playgroud)
和
}
}
}
) // end of weekend()
Run Code Online (Sandbox Code Playgroud)
git 看起来不再一样了。这可以帮助 git 更好地理解你的更改。如果你添加一些东西,比如
function a()
{
...
} // end of a()
Run Code Online (Sandbox Code Playgroud)
git 更有可能将其视为一个更改单位,而不认为您添加了类似的内容
}
function a()
{
...
Run Code Online (Sandbox Code Playgroud)
就在其他函数结束之前。即使这不能防止冲突,如果 git 明智地看到并呈现您的更改(即我们在心理上看待它们的方式),那么您也许可以更轻松地解决冲突。一个描述性的标题注释了函数的作用、它们所采用的参数等,将进一步有助于防止 git 将相邻函数的内容混淆在一起。