从 Git 提交历史中「恢复」文件修改时间

简介: 几个月之前,我贪图部署方便,把博客的部署方式,从本地编译推送更新变成了借助 Github 和 Travis-CI 自动部署。 用了几个月一直相安无事,直到几天前我小小修改了一下主题,展示了文章的更新日期。 本地调试的时候一切正常,直到我把变更推到 Github,触发了自动部署。下图就是出乎意料的
+关注继续查看

几个月之前,我贪图部署方便,把博客的部署方式,从本地编译推送更新变成了借助 Github 和 Travis-CI 自动部署

用了几个月一直相安无事,直到几天前我小小修改了一下主题,展示了文章的更新日期。

本地调试的时候一切正常,直到我把变更推到 Github,触发了自动部署。下图就是出乎意料的上线效果。

逼死处女座

注意到所有的文章的更新日期都是同一天了吗?真是伤脑筋啊。没错,正如你猜测的那样,我的星座是人见人黑的处女座。

为什么会出现这种测试效果和上线效果不一致的情况呢?我们得从 Linux 系统中文件的几个时间属性说起。

在 POSIX 系统中,每个文件都有且仅有 3 个时间属性,最后访问时间,最后修改时间,最后状态变更时间。举个例子,这个文件的内容被访问了,比如用 cat 或者 less 读取内容,最后访问时间就会被更新;如果这个文件内容被修改了,比如用 vi 改了点东西然后保存,就会修改最后修改时间;如果用 chmod 改了权限什么的,更新的就是最后状态变更时间。

为什么没有「文件创建时间」?其实在一些现代的文件系统中,比如 ext4 或者 Btrfs 是保存了文件创建时间的,只不过由于默认的 POSIX 兼容性,我们一般都不去做特殊读取罢了,毕竟出于程序的可移植性考虑,我们不能把程序绑定在某几个文件系统上。

但是作为一个博客系统,Hexo 是需要知道文件的创建时间的。也许是出于上述原因,Hexo 没有依赖文件系统的特性去保存创建时间,而是直接把时间作为文章的元数据,放在文章开头的 YAML 区域里头了。

与此同时,Hexo 也提供了获取文章修改时间的 API,由于 POSIX 保证了能够问系统要到文件的最后修改时间,Hexo 就直接把这个功能交给系统代理,文件的最后修改时间就认为是文章的修改时间。

在博客的自动部署流程中,我们是把博客源码从 Github 上 clone 到 Travis-CI 的虚拟机里,然后使用 Hexo 编译出静态页面。显然这些 clone 出来的文件,它们的最后修改时间是这些文件在 Travis-CI 的虚拟机里的创建时间,而不是我当初修改并保存的时间。至于为什么 Git 不保存文件的修改时间,原因在这里

那么有没有什么办法恢复文件的修改时间呢?精确的恢复是不可能的,毕竟信息已经丢失了,丢失得很彻底。但是作为一个博客系统,对时间精确度的要求没那么高,近似一下,使用文件的 commit 时间作为修改时间,也是可以接受的。

Google 一下,神通广大的外国朋友已经给出了解决方案,当然我也不是啥都没做,我还是去掉了一些无用参数的!

git ls-files | while read file; do touch -d $(git log -1 --format="@%ct" "$file") "$file"; done

这个操作看起来也好理解,把当前 Git 仓库里正在跟踪的文件给列出来,然后依次「篡改」文件的最后修改时间。根据 git log 命令的文档%ct 是 committer date, UNIX timestamp 的占位符,代表提交时的时间戳,那么问题来了,为什么要在时间戳前面加上 @符号?

经过一番苦苦寻觅,我在 GNU Coreutils 的文档中找到了答案。原来从 Coreutils 5.3.0 开始,实用工具中只要是涉及时间的参数,都可以用 @+unix timestamp 的形式来替代,比如 touch -d 本来要带的参数是一个「人类可读」的时间描述,可以是 Sun, 29 Feb 2004 16:21:42 -0800 或者 2004-02-29 16:21:42,甚至 next Thursday 也行,但是我们还是可以任性地使用 @1078042902 作为时间输入。

于是最后的解决方案就是把上面这行代码添加到 .travis.yml中,在生成静态页面之前恢复一下文件的修改时间。

解救处女座

于是这个逼死处女座的问题总算解决了~

目录
相关文章
|
12月前
|
开发工具 git
关于 Git 重写历史的一些笔记
写在前面 今天和小伙伴们分享一些 Git 重写提交历史的笔记 提交代码遇到相关问题,这里整理笔记 博文为《Pro Git》读书笔记整理 感谢开源这本书的作者和把这本书翻译为中文的大佬们 理解不足小伙伴帮忙指正,书很不错,感兴趣小伙伴可以去拜读下
|
12月前
|
开发工具 git
Git 查看提交历史
Git 查看提交历史
|
12月前
|
存储 前端开发 Unix
Git的简介与历史 | 青训营笔记
众所周知,咱们不论是前端还是后端的开发工程师,会面临很多版本问题,事实上哪怕是运营岗或者一些文职也会经常遇到要改好几版的问题。手动地一个个保存文件并以不同地命名是个解决方案,但是很显然在面对大量版本迭代的时候就很低效,并且在发送文件给同事或者甲方爸爸时还得费眼睛去找某个文件。作为拒绝简单重复劳动的程序员,我们需要一个更加自动化、更加程序化的工具来便利我的版本迭代。
|
开发工具 git
git 撤回几个提交commit,并将提交历史清掉
git 撤回几个提交commit,并将提交历史清掉
|
开发工具 git
修改Git提交历史中的author,email和name等信息
在我们日常工作中,通常由于某种原因,需要更新历史提交的commit信息。一般会有如下几种场景: 修改当前分支最新 commit 的提交信息 修改当前分支某历史commit的提交信息 修改当前分支所有提交的commit信息
|
开发工具 git
git fatal: 拒绝合并无关的历史
记录一个git的错误, 以备以后查看
271 0
|
Web App开发 开发工具 git
GitHub 标星 11.5k 的一款开源工具,助你轻松查看 Git 历史
2019 年 2 月,一位名为 Rodrigo Pombo 的阿根廷帅哥在 GitHub 开源 git-history项目,至今已获得 Stars 11.5 k。
126 0
GitHub 标星 11.5k 的一款开源工具,助你轻松查看 Git 历史
|
Shell 开发工具 git
使用git将项目回退到某个指定的历史版本
使用git将项目回退到某个指定的历史版本
|
机器学习/深度学习 开发工具 vr&ar
Git 系列教程(6)- 查看 commit 提交历史
Git 系列教程(6)- 查看 commit 提交历史
509 0
Git 系列教程(6)- 查看 commit 提交历史
|
存储 Java 开发工具
Git清理历史大文件
Git清理历史大文件
219 0
相关产品
云迁移中心
相关实验场景
更多
推荐文章
更多