起因是我想把网站的主题,修改成以往的样式。总有访客吐槽新样式不好,说配色刺眼、布局混乱、字体太小,起初我还不以为意,觉得只是习惯问题,多看几眼总会顺眼。可日子一久,我自己每次打开后台,面对那套当初精心挑选却越看越陌生的设计,心里也泛起同样的别扭。终于有一天,我下定决心改回去,却发现自己已经彻底忘了旧样式究竟是怎么配置的——图片是什么、主色调的十六进制码是多少、导航栏的间距参数又调过哪些数值。那些曾经烂熟于心的细节,如今像褪色的笔记,只剩模糊的轮廓。还好我有 Git,从项目初始化那天起每一次提交都忠实地躺在仓库里,我可以顺着历史的脉络,从层层叠叠的修改中把过去的文件重新打捞出来。

不同于其它教程里大力推荐的 git reset,那会把当前工作区连同提交历史一并回退,动静太大,像推倒一堵墙只为了取一块砖。很明显 git show 更符合从历史复制文件的特性,它只是安静地摊开某一时刻的快照,把你想看的文件内容原样呈现在终端里,既不碰别的文件,也不改写提交记录。你需要做的,是先找到那次历史修改的哈希值,比如 c5b8851,这串看似随机的字符实际上锚定了你想要的某个瞬间。可以用 git log 翻阅历史注释,配合 --oneline--grep 缩小范围,直到在满屏的输出里锁定那个恰好的提交,那就按照这个格式:

1
git show c5b8851:path > path

前半段让 Git 展示那个文件在过去的模样,后半段用重定向把输出接住,写入当前的工作目录。其中 git show 的意义只是展示,像一面干净的镜子,反映出历史上该路径文件的内容,不会主动写入磁盘,也不会提醒你正在做的是一次恢复操作。后面的 > 本意是输出到文件,是 Shell 给你的权力,把本该流向屏幕的文字转存到硬盘上。你可以根据需求选用 > 或是 >>,前者覆盖写入,适合要一份完全一致的旧版;后者追加内容,适合把多份历史片段拼在一起。但我觉得直接使用 > 就足够好了,因为我只是要个过去的文件,一次性拿回来,不必担心新旧混杂。

而且只要不在 LFS 管理的二进制大文件,这个命令几乎都能用,文本文件、配置文件、样式表,统统可以从任意一次提交里抽出来,像从档案柜里抽出一张泛黄的纸,不多也不少。