git:如何更改样式(空格)而不改变所有权/归咎?

47

我们有一个庞大、古老的代码库,需要进行大量清理。我们一直有编码标准,每个人都尽力遵循它们,但是它们并没有得到执行,所以随着时间的推移,很多违规行为已经悄悄出现了。其中许多只是空格问题,比如使用制表符代替空格,或者不应该有空格的地方却有空格,或者应该有空格的地方缺少空格。我们将开始积极执行我们的编码标准,以确保不会出现更多的违规行为,但是仅对更改进行自动执行编码标准是困难的,因此清理这些旧文件是很好的。

有一些工具可以自动修复这些问题,但是如果我这样做,责任归属将显示我是这些代码行的所有者,而实际上我甚至可能从未看过它们。我知道有一种设置可以使责任归属忽略空白更改,但我无法让每个人都以相同的方式使用责任归属,包括其他视觉工具和像gitstats这样的东西。在理想的情况下,应该有某种方法来重写历史记录,使违规行为似乎从未被引入过,而不掩盖实际引入代码的人,但我找不到任何类似的方法。


4
改写历史有点棘手 - 一旦您更改提交,其他人将不得不接手这些更改。这不是理想工作流程的一部分。您可能希望考虑使用挂钩来强制执行编码规范。您可以使用更新挂钩在推送到中央存储库时进行最终强制执行,并为开发人员提供预提交挂钩来执行相同的验证,甚至在安全的情况下自动修复问题。如果您想修复已经存在的内容,我建议只使用一个提交 - 没有必要经历整个历史记录重写的痛苦。 - Cascabel
3
可能是 Git commit that doesn't override original authors in git blame 的重复问题。 - CB Bailey
3
我不认为这完全是那个问题的重复。在我的问题中,我明确指出仅仅改变责备标记是不够的,而那个问题的被接受答案正是这样做的。 - Jay Paroline
5个回答

40

如果你想使用 blame 寻找一个根本原因问题,不要忘记使用 -w 标志来忽略所有的空白或缩进更改。这样你就可以得到代码中最后的真正更改,而不仅仅是缩进或去掉尾随空格。

git blame -w app/to/file.rb

或者你可以直接使用git slap命令。

git config alias.slap "blame -w";
git slap app/path/to/file.rb

有相同的结果 :D


5
@ErikAllik 我不确定你的意思,但是在使用git slap之前,它被定义为git blame -w的别名。 - blinry
2
“-w” 空格参数的缺点之一是它不考虑重构方法顺序、删除松散注释等许多其他事情。 - Joseph Casey

23

在理想的世界中,有一种方法可以重写历史,使违规行为看起来从未存在过。

git filter-branch 就是这么做的。

http://git-scm.com/docs/git-filter-branch

和所有重写历史的命令一样,它会导致所有克隆的存储库失效。


谢谢,我现在正在研究这个! - Jay Paroline
8
明白了!git filter-branch --tree-filter 'git diff-tree --name-only --diff-filter=AM -r --no-commit-id $GIT_COMMIT | php cleanup.php' HEAD 已经可以运行了。 - Jay Paroline
11
你的cleanup.php长什么样子? - Cybot
1
如果我的空格清理无法通过脚本完成怎么办?(例如,空格缩进使用不一致。) - Timmmm

14

Mario's answer的基础上,我建议使用git shame作为全局git别名:

git config --global alias.shame 'blame -w -M'

...使用它来替代git-blame:

git shame path/to/file

解释一下:

  • -w 忽略空格变化,以免责怪重新缩进代码的人
  • -M 检测移动或复制的行,并归咎于原始作者

编辑:

有人认为-M是误导性的,责怪了错误的人
(即:如果有人重新排列我写的东西,请不要责怪我)。
如果你有同感,请使用最初的建议:git slap


1
我向TextMate git Bundle提交了一个pull request,将这个“-w”参数默认设置为“Browse Annotated File (Blame)”命令。感谢Mario Zaizar,你让我的一天。
diff --git a/Support/lib/git.rb b/Support/lib/git.rb
index 5e8de13..5192953 100644
--- a/Support/lib/git.rb
+++ b/Support/lib/git.rb
@@ -307,6 +307,9 @@ module SCM
       file = make_local_path(file_path)
       args = [file]
       args << revision unless revision.nil? || revision.empty?
+      # Ignore whitespace when comparing the parent's version and
+      # the child's to find where the lines came from.
+      args << '-w'
       output = command("annotate", *args)
       if output.match(/^fatal:/)
         puts output 

0

对于那些在JetBrains IDE中使用VCS注释功能查看git blame输出的人,您可以设置以下-w(忽略空格),-M(检测文件内移动或复制的行)和-C(检测文件间移动或复制的行)标志:

配置注释选项

  • 右键单击注释区域,从上下文菜单中选择选项

来源:IntelliJ文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接