【问题标题】:How to ignore/revert changes of case in file-content?如何忽略/还原文件内容中大小写的变化?
【发布时间】:2020-11-13 22:46:17
【问题描述】:

我正在对 Microsoft Access VBA 代码进行版本控制,通常不区分大小写。然而,变量名的大小写在那时时不时发生变化(由 Access 编译器或开发人员)。这通常会导致我的 git 工作区发生巨大的变化。

如何还原或忽略仅涉及文件内容的大写或小写的更改?

一个例子:

git init
echo "public sub example()\nend sub" > mdlExample.ACM
#                ^-- lower e
git add --all
git commit --all --message "Initial Commit"
echo "public sub Example()\nend sub" > mdlExample.ACM
#                ^-- upper E

我会喜欢这样的:

git restore --only-case-changes # not working

然后:

git status
> On branch master
> nothing to commit, working tree clean

【问题讨论】:

  • @Jay 大多数用户只关心文件名。就我而言,文件内容是相关的。
  • 啊,我的错。感谢您的快速回复。

标签: bash git git-bash case-insensitive


【解决方案1】:

您是否考虑过这个 StackOverflow 问题的答案:

How to perform case insensitive diff in Git

也许您可以编写一个脚本来为每个提交进行差异比较,然后将这些提交添加到您的分支。它可能不像您喜欢的那么简单,但也许它会简化更改的显示,让您更快地进行不区分大小写的更改?

【讨论】:

  • 我还没有考虑difftool。但在为我的问题构建脚本解决方案时,它可能会有所帮助。
【解决方案2】:

您不必git restore 任何东西:您可以设置clean content filter driver as illustrated here,它会自动转换git diff/git commit 上的这些情况。
这意味着:

  • 你甚至不会看到有差异
  • 由于该内容过滤器驱动程序,您不会添加 /commit 任何内容。

图片来自“ProGit book”的“Keyword Expansion”部分

这是通过以下方式完成的:

  • .gitattributes filter declaration,这意味着您只能将其关联到某些文件(例如,通过它们的扩展名)
    *.ACM filter=ignoreCase
    
  • 一个本地的git config filter.<driver>.clean 来声明实际的脚本(应该在你的PATH 中)
    git config filter.ignoreCase.clean ignoreCase.sh
    
    # that give a .git/config file with:
    
    [filter "ignoreCase"]
      clean = ignoreCase.sh
    

诀窍是:

您能否编写一个脚本,将 ACM 文件的内容作为输入并生成相同的 ACM 文件作为输出,但其字符串已转换?
您可以使用filename in those scripts,这样您就可以进行比较并检测是否必须调整所述差异,但您仍然需要编写正确的命令,以便在 ACM 文件中的大小写更改时仅替换“xxx”字符串。

注意:jthill 建议 in the comments 设置 merge.renormalize 配置设置以告诉 Git 存储库中文件的规范表示已随着时间而改变。

【讨论】:

  • 您还需要设置merge.renormalize。对于规范化过滤器,flex for 可能是最快合理安全地实现的。
  • @jthill 谢谢。好点子。我已将您的评论包含在答案中以提高知名度。
【解决方案3】:

考虑将example="example" 更改为Example="Example"。你如何建议 Git 可以决定在这里忽略哪种情况变化?现在考虑 cmets 中的代码 sn-ps,或存储为代码生成器的字符串。我希望 Git 能够消除烦人的琐事,但我认为如果你试着想象告诉 Git 你想要什么,你会更好地理解你的问题的上下文。

如何还原或忽略仅涉及文件内容的大写或小写的更改

当您想要暂时忽略更改时,当您想要在没有看到这些更改的情况下进行差异或责备时,您可以使用“textconv”过滤器来规范化您差异的文本。我用这些来做一些事情,比如在差异时从生成的 html 中去除嵌入的时间戳,最快的 atm 是

[diff "doc-html"]
    textconv = "sed  's,<span class=\"version\">Factorio [0-9.]*</span>,,;s,<[^/>][^>]*>,\\n&,g'"
    wordRegex = "<[^>]*\\>|[^< \\t\\n]*"

.git/config,和

doc-html/*.html diff=doc-html
*.cfg -diff

.git/info/attributes.

所以我更改的差异不会显示我不关心的东西。

如果您想查看 diff 忽略大小写的结果,请尝试

[diff "nocase"]
        textconv="tr A-Z a-z"

并将* diff=nocase(或*.vba diff=nocase)放入.git/info/attributes。完成后,将其取出。

但是对于合并,我的前导示例应该让你相信 Git 自动且默默地在 repo 内容中进行大小写更改,即使只是在看起来像标识符的文本中,也是一个坏主意。当发生冲突时,不仅仅是单方面的变化,而是两种不同的变化,仍然需要一些人为的判断来决定结果应该是什么。幸运的是,使用任何体面的合并工具,解决简单冲突的时间都在亚秒级左右。

【讨论】:

  • 一个差异驱动程序。当然。那也可以。赞成。
  • 使用textconv = "sed 's,.,\\L&amp;,g'",您的解决方案适用于git diff。但是git status 仍然会列出所有文件。
  • 您将需要一个比sed 更智能的转换器:一个能够区分“代码中的名称”与“字符串或 cmets”的词法分析器可能就足够了;和@VonC 建议的内容过滤器,以便此过滤器适用于存储在 git 中的实际内容。
猜你喜欢
  • 2014-05-17
  • 1970-01-01
  • 2019-12-31
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
  • 2011-08-26
相关资源
最近更新 更多