需求背景
有些时候希望按照规则的时间提交commit信息,比如强迫症可能希望每一次commit的时间都是整数时间、比如本地时间不准确,希望按照网络时间来提交1、还有一些其他的原因。。
但是Git默认是按照本地的时间来提交commit信息,当然自由的Git有方法可以自定义提交的时间:
SET GIT_COMMITTER_DATE=%C_TIME% && git commit --amend --no-edit --date=%A_TIME%
需要注意可以设定的时间分为Author Date
和Committer Date
2。手动修改当然可以,但是每次修改岂不麻烦?要是有一次忘记了,后面还要rebase
,那就麻烦大了。
久闻Git有的钩子(hook)功能,可以辅助完成各种自动化的操作,学习了一下钩子实现了自动切换commit到指定时间的方法。
客户端Hooks
Git的客户端钩子只影响它们所在的本地仓库。客户端挂钩主要分为几种类型3:提交工作流挂钩、电子邮件工作流挂钩、以及其他客户端挂钩。
提交工作流挂钩
commit
操作有4个挂钩被用来处理提交的过程,它他们的触发时间顺序如下:
pre-commit
、prepare-commit-msg
、commit-msg
、post-commit
。
post-commit
post-commit
挂钩在整个提交过程完成后运行,它不会接收任何参数,但可以很简单地运行git log
来获得最后的提交信息。
打开~\.git\hooks
目录,创建post-commit
文件(注意没有后缀名),内容如下:
#!/usr/bin/env python
import os
import time
popen = lambda cmd: os.popen(cmd).read()
show = lambda stamp: time.strftime('%Y-%m-%d %H:%M:%S (%a)', time.localtime(stamp))
def convert(stamp):
day = time.localtime(stamp)
wday = day.tm_wday
monday = time.mktime(day[:3] + (0,) * 6) - 86400 * wday
if wday < 5:
return monday - 86400 * 2 + (stamp - monday) * 0.4
return stamp
def amend(at=None, ct=None):
cmd_ct = 'set GIT_COMMITTER_DATE=%s && ' % ct if ct else ''
cmd_at = ' --date=%s' % at if at else ''
cmd = cmd_ct + 'git commit --amend --no-edit' + cmd_at if (at or ct) else ''
popen(cmd)
at1 = int(popen('git log -1 --format=%at'))
ct1 = int(popen('git log -1 --format=%ct'))
at2 = convert(at1)
if not at2 == at1 == ct1:
amend(at2, at2)
一个简单的脚本实现commit
之后,根据git log
获取最后一次提交时间,在convert
函数中对时间戳进行转换,然后再次提交一次commit --amend
,修改最后一次提交的时间。
本例中将周一到周五的时间映射到了周末,这样所有工作日的提交就会自动变更记录为周末的提交时间(注意如果遇到节假日的调班就不行了哦)。
如果只是希望提交日期和作者日期对齐的话,可以不用调用Python,用git自身支持的bash就可以完成:
#!/bin/sh
export GIT_COMMITTER_DATE=$(git log -1 --format=%at)
if [ $GIT_COMMITTER_DATE != $(git log -1 --format=%ct) ]; then
git commit --amend --no-edit
fi
需要注意的是,赋值和判断语句附近的空格都不能去掉,否则会有语法错误。
或者还可以用数组赋值的方法:
#!/bin/sh
t=($(git log -1 --format="%at %ct"))
if [ ${t[0]} != ${t[1]} ]; then
GIT_COMMITTER_DATE=${t[0]} git commit --amend --no-edit
fi
注意事项
1、修改提交时间的本质是在commit
命令之后再次运行一次commit --amend
,所以在引用记录里仍然能够看到所有的操作。如果有方法能够将这一步也能避免,这是值得改进的;
2、commit --amend
本身实际上也是一次commit
,所以在这次commit
之后会再次触发post-commit
挂钩。所以需要设计合理的逻辑让amend
之后的提交不再符合post-commit
脚本里的规则,不会再次进行commit --amend
提交,否则可能产生递归。当然,除非递归本身就是你预期的效果。