.sass
或.scss
文件生成CSS规则,或者即时构建XML配置?我们会进行检查吗?# Enable the repository's stock pre-commit hook
mv .git/hooks/pre-commit.sample .git/hooks/pre-commit
这个 pre-commit 钩子将在每次执行 git commit
时进行一系列检查,包括一个版本的 git diff --check
命令,该命令检查您提交的更改是否引入了空格错误。如果有,则提交将被拒绝。如果您真的需要绕过它,可以发出 git commit --no-verify
命令,但不要这样做:空格错误就像版本控制中未爆炸的弹药一样。它们是等待发生合并冲突的问题。
如果您想清理空格、重构文件以改善其缩进或以其他方式进行大量纯格式更改,请在隔离的提交中执行此操作,并警告团队先检入他们的冲突工作。
如果您进行代码审查,请确保这些是每个审阅者首先问的问题:“这个变更集是否触及了任何它不应该触及的内容?它是否清理了任何格式?它是否不必要地重构了某个方法?”如果是这样,审核失败。或者,如果您无法这样做,请确保这些更改与逻辑更改足够隔离(即在不同的提交中),以使您的历史记录有用。
Stylesheet语言、RequireJS和js minifiers也会引起冲突,如果它们生成的目标被检入。这些技术创建的文件是构建工件。你不会检入一个WAR存档文件;不要检入SASS编译的CSS文件。或者,如果你觉得必须检入,请使用.gitattributes
文件让git将它们视为二进制文件。说实话,正确的工作流程需要良好的沟通和管理。团队成员不应该经常在同一件事情上工作,并引起冲突。每日站立会议和一个注意每个团队成员正在做什么 - 至少是大致了解 - 的细心经理,在许多情况下都可以限制这种情况。
当然,这取决于产品的确切性质,但这更多是组织问题而不是git问题。事实上,冲突通常被视为“好”的事情,因为它们能够让人们离开他们的桌子,或者互相打电话谈论为什么会有冲突,以及今后该怎么办。这是一个机会来确定一个人应该拥有一个区域、一组文件,或至少是讨论对该部分变更的联系点。
除了制定前期计划外,没有办法避免git冲突,但是这在任何版本控制系统中都是同样的问题。每当两个人更改代码的同一部分时,你必须找出谁胜利了。这就是为什么将目光投向版本控制器寻求解决方案并不真正合适,而要看看团队的方法和实践。两辆车无法同时通过十字路口,但很难发明可以互相穿过的汽车,因此我们发明了停止标志和交通信号控制系统。这是一个类似的问题。我们真的无法使对同一事物做两个更改不发生冲突,因此我们必须控制如何处理文件。
你可以考虑使用允许在git中锁定的前端之一,但我并不完全同意这个概念,除了非可合并的文件类型之外。我认为最好找出更好的团队工作流程,同时利用这个机会来真正擅长合并文件。我就是这样做的,现在几个月后,冲突对我来说已经不是令人沮丧的事情了。
避免冲突的唯一方法是:不要让不同的人同时编辑同一个文件。基本上,每个文件都有一个负责进行所有编辑并可以将所有权转移给其他人的所有者。文件的所有权可以基于特定的功能/分支或日常传递,只要所有权清楚。
如果您发现无法为每个文件指定一个所有者,则:
还有一些其他的事情可以帮助你。如果我将它们分开发布,那么它会更清晰。
插入新内容的位置将有助于确定是否创建冲突。
想象一下员工姓名列表
Andy,
Oliver,
Ivan,
然后 Brad 和 Patrick 加入,他们的名字被添加到列表中。 你添加 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
现在假设我们将相同的操作应用于列表,但对其进行了简单的按字母顺序排序。当我们合并两个分支时,结果会更加令人满意 :-
Andy,
Ivan,
Oliver,
在git中添加您的名称,然后与另一个人的更改合并,以添加另一个姓名。
Auto-merging names.txt
Merge made by the 'recursive' strategy.
names.txt | 1 +
1 file changed, 1 insertion(+)
我们得到了
Andy,
Brad,
Ivan,
Oliver,
Patrick,
由于我们不知道谁会加入公司,因此我们随机地添加到列表中,并通过在随机位置插入来减少文件位置冲突。
在像这样的软件中...
function chess()
{
while (!end_of_game)
{
make_move()
以左花括号开始的代码块容易被与只包含单个左花括号的代码混淆。若将代码修改为以下格式,将花括号放在前一行...
function chess() {
while (!end_of_game) {
make_move()
我个人不太喜欢,但Git却喜欢,在Git中有很多看起来相似的行,并且容易被误认为是同一行,因此Git更容易像我们一样感知编辑,从而使任何冲突更容易解决。
使用注释使相似的行区分开来。
如果你写很多JavaScript和JSON代码,你可能会有很多类似以下的行。
}
}
}
)
}
}
}
) // end of weekdays()
并且
}
}
}
) // end of weekend()
不再看起来像git。这可以帮助git更好地理解您的更改。如果您添加了一些内容,例如
function a()
{
...
} // end of a()
Git更可能将其视为变化的单位,而不认为您添加了类似以下内容的东西
}
function a()
{
...
在其他函数的末尾之前插入代码,即使这样做不能完全避免冲突,如果git能够合理地呈现您的更改(即我们在脑海中所看到的方式),那么您或许能够更轻松地解决冲突。对于函数的描述性标题、它们所接受的参数等,将进一步帮助防止git混淆相邻函数的内容。
许多版本的Git(据我所知,包括我使用过的每个版本)会将UTF-16文件视为二进制文件,因为典型的UTF-16文本文件中存在许多零字节。
一旦Git认为一个文件是二进制文件,即使它被更改,它也可能继续将该文件视为二进制文件。这意味着版本控制是通过存储完整版本的文件而不是它们之间的差异来完成的,因此版本控制系统的某些优势将会丧失。(编辑:不。我最近测试了一下,将一个UTF-16文件更改为UTF-8,提交它,编辑它并再次提交 - 一旦原始文件和编辑后的文件都是UTF-8,它就开始将更改视为文本更改。)
大多数现代编辑器都能识别文件的字符编码和行结束样式,并以相同的格式保存文件。一些编辑器(例如Babelpad)允许您选择是否将文件保存为UTF-8或UTF-16,并选择是否带有字节顺序标记等。
如果您要版本控制的文件(i)是UTF-16格式,且(ii)在UTF-8下同样有效——例如现代编译器的源程序——那么考虑将其转换为UTF-8。重复使用记录的解决方案!
减少冲突痛苦的另一种方法是在推送更改后通知同事。这样他们就可以拉取您的更改并在那里解决一些冲突。任何冲突可能是您最近的更改与他们正在处理的内容之间的冲突,这两者都还新鲜在他们的脑海中。
如果人们在完成大型开发之前不从主分支拉取更改,然后与许多人在同一区域进行的更改发生冲突,那么解决起来将更加困难。