我有两个文件,file1
和file2
。我修改了file1
,没有碰file2
.提交后,CI 开始检查file1
和file2
的修改日期。如果file2
较旧,则生成工具会从file1
生成自己的file2
版本,并比较结果(生成file2
和file2
存储库中的结果(。如果没有匹配项,则会生成错误。
我不想修改file2
,也无法修改构建管道。问题是,如何仅提交file2
的时间戳修改,以便 CI 不会触及它?我想让file2
比file1
更新.
请不要问为什么以这种方式配置CI。这是一个有很多贡献者的大项目。
Git 不存储文件时间戳。
Git 中的存储单元是提交。提交(作为一个整体(有一个时间戳。 实际上,每个提交都有两个时间戳,即作者时间戳和提交者时间戳。 这两个时间戳是提交元数据的一部分。 当然,提交会存储所有文件的快照。 但那是您的所有文件,没有时间戳。
这意味着标题中问题的答案是响亮的否定。即使 Git 本身在文件上设置了时间戳(它没有(,你也无法让它在file2
上设置 timetsamp,而不同时在file1
上设置时间戳(因为要么你设置了作者或提交者时间戳中所有文件的所有时间戳,要么——正如 Git 今天实际工作的那样——你不会在任何文件上设置它们(。 提交中只有两个时间戳,如果您要应用它们,您如何知道哪个文件应该获取它们?
底层操作系统在工作树中查看文件时间戳更新的方式是这样的:当你的 Git 执行git checkout
或git switch
,从你现在拥有的任何提交移动到你想要的任何其他提交时,你的 Git 观察到这需要替换一些文件的内容(也许删除一些文件并创建一些文件(。 因此,Git 会替换这些文件的内容,和/或根据需要删除和/或创建一些文件。 此操作会导致操作系统更改这些文件的时间戳。
CI 构建系统的工作方式可能相同,也可能不同。 某些 CI 系统可能会保留一个充满以前构建的文件的工作树;1在任何情况下,您都无法让Git像这样设置日期戳。阿拉伯数字您将不得不找到其他方法来处理您的 CI 系统。
(如果您的 CI 系统具有标准工作树,您可以通过以下方式更新其file2
的工作树副本......更改file2
以便 Git 在更改提交时必须提取它。 但这是你说你不想要的。
1在这些构建系统中,不保留工作树,而是运行一个git diff
来比较以前构建但早已删除的工作树中的文件内容与已提取到新工作树的建议新构建中的文件内容似乎很常见。 如果特定文件的文件内容已更改,则会重新生成这些文件。 例如,一些 Jenkins 设置手动执行此操作。 Bazel 显然通过计算哈希校验和并比较校验和来形式化这一点:如果校验和与以前的构建匹配,它只是重用以前构建的工件。
2人们编写了各种 Git 钩子,这些钩子会通过并打击文件所有权和/或权限,例如,基于已提交文件的内容。 此技术还可用于设置操作系统的时间戳。 但这样的脚本通常只是 CI 系统的一部分。
我给你2个方法:
第一个是以下内容,清晰安全:
git rm --cached <file>
git add <file>
这应该将新文件放入索引中,而不管以前有什么。
第二个是以下(但请注意,这只是一种解决方法(:
touch file.dat
git add file.dat
基本上,强制 Git 识别文件可能被更改,以便它直接检查它是否真的被更改了。