我可以'git承诺'一个文件并忽略其内容的变化?

我团队中的每个开发人员都有自己的本地配置。该配置信息存储在一个名为devtargets.rb的文件中,该文件用于rake构建任务。不过,我不希望开发人员互相破坏对方的devtargets文件。

我的第一个想法是把这个文件放在.gitignore列表中,这样它就不会被提交给git。

然后我开始思考:是否有可能提交文件,但忽略对文件的更改?所以,我会提交文件的默认版本,然后当开发人员在他们的本地机器上更改它时,git会忽略这些更改,当你执行git状态或git提交时,它不会显示在更改文件列表中。

这可能吗?这肯定是一个不错的功能……

98679 次浏览

通常的做法似乎是创建一个devtargets.default.rb并提交它,然后指示每个用户将该文件复制到devtargets.rb(在.gitignore列表中)。例如,CakePHP对它的数据库配置文件做了同样的事情,该文件在不同机器之间自然会发生变化。

当然,我经常这样做

git update-index --assume-unchanged [<file> ...]

要撤消并重新开始跟踪(如果你忘记了哪些文件被未跟踪,看这个问题):

git update-index --no-assume-unchanged [<file> ...]

相关的文档:

< p > ——不——assume-unchanged
指定此标志时,不会更新为路径记录的对象名称。相反,这个选项设置/取消“假定不变”;比特表示路径。当“assume unchanged"位打开时,用户承诺不修改文件,并允许Git假设工作树文件与索引中记录的文件匹配。如果您想要更改工作树文件,则需要取消设置位来告诉Git。当在具有非常慢的lstat(2)系统调用(例如cifs)的文件系统上处理一个大项目时,这有时是有用的

Git会失败(优雅地),如果它需要在索引中修改这个文件,例如在提交合并时;因此,如果假设未跟踪的文件在上游被更改,您将需要手动处理这种情况。

在这种情况下,失败优雅的意思是,如果在你进行拉取时,该文件上游有任何更改(合法更改等),它会说:

$ git pull
…
From https://github.com/x/y
72a914a..106a261  master     -> origin/master
Updating 72a914a..106a261
error: Your local changes to the following files would be overwritten by merge:
filename.ext
 

并且拒绝合并。

在这一点上,你可以通过恢复你的本地更改来克服这个问题,这里有一种方法:

 $ git checkout filename.ext

然后再次拉取并重新修改你的本地文件,或者可以设置–no-assume-unchanged,你可以在那时做正常的保存和合并等。

对于IntelliJ IDEA用户:如果你想忽略一个文件(或多个文件)的更改,你可以将它移动到不同的Change Set

  • 前往Local Changes (Cmd + 9)
  • 选择要忽略的文件
  • F6将它们移动到另一个Change Set

这样做的首选方法是使用git update-index --skip-worktree <file>,如在这个答案中所解释:

assume-unchanged是为检查成本高的情况而设计的 是否修改了一组文件;当你设置位的时候,少不更事的人 (当然)假设文件对应的那部分 索引在工作副本中未被修改。这样就避免了混乱 统计调用。只要文件的条目在索引中,这个位就会丢失 更改(因此,当文件在上游被更改时)

skip-worktree不止于此:即使git知道文件 已被修改(或需要通过重置修改-硬或 ),它将假装它没有,使用版本从 指数。

要撤消此操作,请使用git update-index --no-skip-worktree <file>

从git 2.25.1版本开始,这也不再是推荐的方式,引用如下:

用户经常尝试使用“假定不变”和“跳过工作树”来告诉Git忽略对所跟踪的文件的更改。这并不像预期的那样工作,因为Git在执行某些操作时仍然会根据索引检查工作树文件。通常,Git不提供忽略对跟踪文件的更改的方法,因此建议使用替代解决方案。

例如,如果您想要更改的文件是某种配置文件,那么存储库可以包含一个示例配置文件,然后可以将其复制到忽略的名称中并进行修改。存储库甚至可以包含一个脚本,将示例文件视为模板,自动修改和复制它。

使用Git不可能忽略对跟踪文件的更改。Git常见问题解答:

Git没有提供这样做的方法。原因是,如果Git需要覆盖这个文件,比如在签出期间,它不知道对文件的更改是宝贵的,应该保留,还是无关紧要,可以安全地销毁。因此,它必须采取安全的路线,始终保护它们。

尝试使用git update-index的某些特性是很有诱惑力的,即假设不变和跳过工作树位,但这些不能正常工作,不应该这样使用。

如果您的目标是使用配置文件,那么最好的方法是添加一个示例或模板文件,然后让用户将其复制到适当的位置,或者让脚本创建适当的文件。然后,您应该忽略实际配置文件的位置,只签入示例或模板。