24

我有一个小型脚本项目,它在一个名为“Droid XX-XX-XX”的目录中包含五个不同的源文件。每次创建源目录的新备份副本时,我都会将日期放在 X 中。所以大约有 15 个不同日期的不同版本。我想从最早开始将这些中的每一个添加到我的新 Git 存储库中。

但是我遇到了几个问题。

  1. 一个问题是一些文件使用制表符进行缩进,而另一些文件使用空格——但即使唯一的区别是制表符与空格问题,Git 也会将整行视为不同。如何让 Git 忽略缩进格式?

  2. 另一个问题是一些文件名没有空格,而另一些文件名之间有空格——但 Git 将它们视为不同的文件。更糟糕的是,有时文件名无故更改为不同的名称(例如“PatrolPlan”更改为“Patrol”)。当我添加一组新文件时,我如何告诉 Git 即使文件名不同,它实际上只是某个旧文件的新版本?或者更好的是,我可以将其设置为在发生这种情况时自动检测吗?

  3. 最后一个问题是,在开发过程中的某些时候,我们将两个源文件合并为一个,或者将一个源文件拆分为两个——但 Git 不会自动检测相似之处并推断发生了什么。我如何告诉 Git 发生了什么?或者更好的是,如何将其设置为自动检测两个源文件何时合并或一个源文件何时拆分?

我意识到问题(2)和(3)是高度相关的。感谢您的帮助!

4

3 回答 3

39

听起来您需要对开发过程进行更多控制和标准化。提交更改的人应该是修改文件的人。或者至少提交者应该确切地知道发生了什么变化。

仔细检查 的输出git diff,并使用-w标志忽略空格。还有一些选项可以显示一行内的差异。请参阅下面一行内的差异

请注意,您将无法告诉 git 在提交时跳过空间更改。我建议使用 GitX(我更喜欢“brotherbard”fork),它允许您在提交之前以交互方式丢弃大块。

提交时使用描述性消息。例如,如果一个文件被拆分,就这么说。让你的提交变小。如果您发现自己编写了很长的提交消息,请将提交分解为更小的部分。这样,当您在很长一段时间后检查日志时,更改的内容会更有意义。

一行内的差异

Git 具有在一行中显示“单词”差异的能力。最简单的方法是只使用git diff --color-words.

但是,我喜欢使用配置自定义“单词”的含义diff.wordRegex。我也喜欢plainword-diff 格式,因为它更清楚地显示了差异所在(除了使用颜色之外,还在更改周围插入括号)。

命令:

git diff --word-diff=plain

连同我的配置中的这个:

[diff]
        wordRegex = [[:alnum:]_]+|[^[:alnum:]_[:space:]]+

此正则表达式将这些视为“单词”:

  • 连续的字母数字和下划线字符串
  • 非字母数字、非下划线和非空格的连续字符串(适用于检测运算符)

您必须拥有最新版本git才能使用wordRegex. 查看您的git-config手册页以查看是否列出了该选项。

更新

如果您使用git mv重命名文件(这比使用其他工具或操作系统重命名更可取),您可以看到 git 检测重命名。我强烈建议独立于对文件内容的任何编辑提交重命名。那是因为 git 实际上并没有存储您重命名的事实 - 它使用基于文件更改量的启发式来猜测它是否是同一个文件。在重命名提交期间更改它的次数越少越好。

如果您确实稍微更改了文件内容,您可以使用-C参数来git diffgit log努力地检测副本和重命名。添加一个百分比(例如-C75%)以使 git 对差异更加宽容。百分比表示内容必须有多相似才能被视为匹配。

于 2012-09-14T16:26:43.930 回答
3

现在我对 Git 有了更多的了解,我可以回答我自己的问题了。

  1. 最好使用正则表达式进行全局搜索替换,以标准化项目不同版本中所有文件之间的空白,这样当它们按顺序提交时,空白更改不需要提交。话虽如此,Atlassian SourceTree 的差异工具允许您隐藏空白更改,因此至少您不会看到这些更改。

  2. 处理文件名更改的关键是在只有文件名更改的地方进行提交(不要暂存任何其他更改)。然后在其内容更改的地方进行提交。这样,不做大量启发式和深度挖掘的普通差异工具就可以理解所发生的事情。问题在于,如果对文件进行了太多更改,例如名称和大量内容,那么大多数 diff 工具会将其视为摘要删除和新文件。(如正确答案中所述)

  3. 这是一个更难的问题,没有真正好的解决方法。如果你将一个文件分成两个,或者合并两个,它在差异中只会很丑。尽量不要在进行拆分的同时进行大量更改,这样拆分是一回事,后续的更改将是另一回事。

于 2016-03-09T01:54:55.380 回答
2
  1. 您将无法让 git 忽略制表符/空格,因为 git 创建每个文件的哈希值,如果哈希值不同,则文件被视为不同。

  2. Git 将树(目录)视为文件;如果它们的内容发生变化,那么它们就是不同的树。

不过,我不认为这些变化有什么可担心的。它们发生在任何开发过程中。我认为对您来说最好的方法是使用 git重播您的开发。换句话说,从您的初始版本开始,然后进行必要的更改(就像您最初所做的那样),git 会记住您在做什么。

可选:如果您想将更改的日期/时间大致记录为最初所做的更改,则可以使用--date命令行选项git commit告诉 git 何时进行这些更改。

于 2012-09-14T15:49:19.667 回答