Use Git hook to automatically change the submission time of the last Commit

Posted by jfgreco915 on Wed, 23 Feb 2022 13:33:22 +0100

Demand background

Sometimes you want to submit the commit information according to the regular time. For example, Virgo may want the time of each commit to be an integer time. For example, if the local time is inaccurate, you want to submit it according to the network time 1 There are other reasons..

However, Git submits the commit information according to the local time by default. Of course, free Git has methods to customize the submission time:

SET GIT_COMMITTER_DATE=%C_TIME% && git commit --amend --no-edit --date=%A_TIME%

Note that the time that can be set is divided into Author Date and committee date 2 . Manual modification is certainly possible, but isn't it troublesome every time? If you forget once and have to rebase later, you'll be in big trouble.

I've heard a lot about the hook function of Git, which can assist in completing various automatic operations. I learned about the hook and realized the method of automatically switching commit to a specified time.

Client Hooks

Git's client hooks only affect their local repository. There are several types of client hooks 3 : workflow hooks, workflow hooks, and other clients.

Submit workflow hook

The commit operation has four hooks that are used to handle the submission process. Their trigger time sequence is as follows:
pre-commit,prepare-commit-msg,commit-msg,post-commit.

post-commit

The post commit hook runs after the whole submission process is completed. It does not receive any parameters, but it can simply run git log to obtain the final submission information.

Open ~ \ git\hooks directory, create a post commit file (note that there is no suffix), the content is as follows:

#!/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)) if stamp else 'None'

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 * 5 + (stamp - monday) * 0.4

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 ''
    return cmd

at1 = int(popen('git log -1 HEAD --format=%at'))
ct1 = int(popen('git log -1 HEAD --format=%ct'))
at2 = convert(at1)
ct2 = convert(ct1)
cmd = amend(at2, ct2)

print('at:', show(at1), '->', show(at2))
print('ct:', show(ct1), '->', show(ct2))
print(cmd)
print(popen(cmd))

After a simple script implements commit, obtain the last submission time according to git log, convert the timestamp in the convert function, and then submit commit --amend again to modify the last submission time.

In this example, the time from Monday to Friday is mapped to the weekend, so that the submission of all working days will be automatically changed and recorded as the submission time of the weekend (note that it will not work if there is shift adjustment on holidays).

Provide a test method to test whether these functions operate normally:

def test():
    print('\ntime offset test:')
    p1 = time.mktime(time.strptime('2000-01-01', '%Y-%m-%d'))
    p2 = time.mktime(time.strptime('2012-12-21', '%Y-%m-%d'))
    print(show(p1), '->', show(convert(p1)))
    print(show(p2), '->', show(convert(p2)))

    print('\namend cmd test:')
    print(amend())
    print(amend(at='%A_TIME%'))
    print(amend(ct='%C_TIME%'))
    print(amend('%A_TIME%', '%C_TIME%'))

    print('\ntest finish.\n')

matters needing attention

1. The essence of modifying the submission time is to run commit --amend again after the commit command, so all operations can still be seen in the reference record. If there are ways to avoid this step, it is worth improving;

2. commit --amend itself is actually a commit, so the post commit hook will be triggered again after this commit. Therefore, it is necessary to design reasonable logic to make the submission after amend no longer comply with the rules in the post commit script, and commit - amend submission will not be carried out again, otherwise recursion may occur. Of course, unless recursion itself is what you expect.

  1. Developing pre commit hook based on Python to control Git submission time ↩︎

  2. Why is git AuthorDate different from CommitDate? ↩︎

  3. Introduction and use of GitHook tool ↩︎

Topics: Python git