钩子还是不钩子 - git

6
我们的定制 IDE 输出具有使其看起来像二进制文件的编码的 XML 文件。这些文件的差异和合并失败。
我们可以使用“tr”命令创建这些文件的 ASCII 版本。我希望在提交之前,这些文件总是自动转换为 ASCII。
我拿起了我的《Git 版本控制》一书,它完全警告我不要使用钩子,除非我真的需要。
我应该使用 hook 来实现这个目的吗?还是我可以做些其他的事情来确保文件在提交之前总是被转换?
Windows XP with msysgit 1.7.4
--= 更新 =--
感谢大家的帮助和耐心。参考此问题,我尝试了以下方法,但它不起作用:
echo "*.xrp    filter=xrp" > .git/info/attributes
git config --global filter.xrp.clean 'tr -cd '\''\11\12\15\40-\176'\'''
git config --global filter.xrp.smudge cat
git checkout --force

这个配置更改后,文件保持不变。即使我删除和重新检出它们。
tr命令配置为清除任务是有效的。证据:
$ head -n 1 cashflow/repo/C_GMM_CashflowRepo.xrp
ÿþ< ! - -   X M L   R e p o s i t o r y   f i l e   1 . 0   - - >

$ tr -cd '\''\11\12\15\40-\176'\' < cashflow/repo/C_GMM_CashflowRepo.xrp | head -n 1
<!-- XML Repository file 1.0 -->

有人能看出我的配置文件有什么问题吗?

一个失败的 diff 或 merge 会表现为什么?合并失败的方式是什么? - ralphtheninja
Diff 响应:“二进制文件不同”。不过这是个好问题,我只是假设合并失败是由于无法进行 diff。无论如何,拥有 diff 的能力会很好。 - Synesso
3个回答

6
一个问题是钩子不是分布式的。 .gitattributes有一些指令来管理文件的差异和内容,但另一个选择是在.gitattributes中使用属性过滤器,并且可以在提交时自动转换这些文件。
(如果清理脚本能够仅基于它们的内容检测这些文件
根据此次聊天讨论,原帖Synesso报告取得了成功。
.gitattributes:
*.xrp filter=xrp

~/.gitconfig:
[filter "xrp"]
clean = \"C:/Program Files/Git/bin/tr.exe\" -cd "\\''\\11\\12\\15\\40-\\176'\\'"
smudge = cat

然后我需要修改文件,添加、提交、删除、检出…然后问题就解决了。注意,对于任何不仅涉及单个用户而且潜在影响到克隆该repo的任何用户的修改,我更喜欢添加(并提交)一个额外的.gitattributes文件,在其中声明过滤器,而不是修改.git/info/attribute文件(它不会被克隆)。来自gitattributes手册页面:gitattributes
如果您希望仅影响单个存储库(即为该存储库中某个用户的工作流程分配属性),则应将属性放置在$GIT_DIR/info/attributes文件中。 应将应该进行版本控制并分发到其他存储库的属性(即所有用户感兴趣的属性)放入.gitattributes文件中。 应该影响单个用户的所有存储库的属性应放置在由core.attributesfile配置选项指定的文件中。 所有用户的属性应放置在$(prefix)/etc/gitattributes文件中。

http://git-scm.com/docs/gitattributes


phyatt在评论中添加了以下内容

我为sqlite3制作了一个类似的示例。
你可以通过两行代码将其添加到正确的文件中:

git config diff.sqlite3.textconv 'sqlite3 $1 .dump'
echo '*.db diff=sqlite3' >> $(git rev-parse --show-toplevel)/.gitattributes 

类似的行可以用于编写其他git配置路径。

我发现属性过滤器非常有用。最终我找到了这个问题:https://dev59.com/BXE95IYBdhLWcg3watU3#2318063 - 我尝试了一个解决方案,但它不起作用。问题已更新。 - Synesso
这让我感到困惑。那怎么可能行得通呢?我在.git/info/attributes中有必要的配置,但无法提交。如果我再次checkout,该配置将不会存在。 - Synesso
@Synesso:只需将.git目录复制到其他地方,然后执行git checkout yourBranch即可 ;) - VonC
这里有很多好的答案,但@VonC付出了很大的努力来帮忙。谢谢! - Synesso
感谢您发布这篇文章。我为sqlite3制作了一个类似的示例。您可以使用两行代码将其添加到正确的文件中:git config diff.sqlite3.textconv 'sqlite3 $1 .dump'; echo '*.db diff=sqlite3' >> $(git rev-parse --show-toplevel)/.gitattributes。类似的代码也可以用于编写其他git配置路径。 - phyatt
显示剩余7条评论

2
在它们的当前状态下(即它们只包含少量奇怪的字节但是其他部分是文本),diff是否有可能起作用呢?如果可以,你可以使用.gitattributes强制git将它们视为文本。如果不行,最好还是创建自定义的差异和合并脚本(将使用tr进行必要的转换),并告诉git使用它,同样使用.gitattributes。无论哪种情况,您都不会使用钩子(这些是用于运行特定操作的),而是使用文件特定的.gitattributes

这些文件是XML格式的,但是当我用hexdump查看它们时,每个字节都夹杂着00。因此,它们被diff视为二进制文件。你提供的解决方案听起来非常简单,我明天会试一下。 - Synesso

2
如果您偏爱使用ASCII格式进行编辑,并且只有构建需要二进制文件,我建议使用构建规则从首选源生成二进制版本,然后将其提交到存储库中。
考虑到您的IDE已经以二进制格式生成文件,我认为最好的方法是以该格式将它们存储在存储库中。
不要使用钩子,而是查看git帮助文件中的attributes,特别是diff和textconv,这样可以配置与某些模式匹配的文件以使用替代的差异方式。 您应该能够生成工作的ASCII差异,而无需妥协存储文件或编辑文件的方式。
根据您在其他地方的评论“每个字节之间都是0”,这表明该文件是UTF-16或UCS-2编码。请参阅此答案以了解可处理unicode的diff:Can I make git recognize a UTF-16 file as text?

谢谢。我应该明确指出IDE是一个水果蛋糕,当它们实际上不是时,会将文件写成二进制格式。它们是二进制的,没有任何好处。感谢您的有益回答! - Synesso
+1 表示按需生成 XML 文件,只提交生成 XML 的源文档。 - Dave Sherohman
@Synesso 根据您的评论,我添加了一个相关问题的链接。 - Ben Jackson
要明确的是,UTF-16文件是源文件。在转换为8字节格式后,IDE将愉快地再次读取它们。 - Synesso

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