Most git servers capture a "Push" action with the authenticated user who made the push and which commits were included in that. That is hard to fake, unless you have admin permissions on the server or access to the server's storage.
On the client when a commit is made the commit metadata is captured, but there is no guarantee the data is correct. Even when a user signs the commit, that signature can be made on the wrong date. GPG/PGP does not user an external time server authority to sign the time into the signature. It will prevent a user from changing commits (and their timing) made by other users though.
A solution that will satisfy all your requirements is to use SMIME signing against a timeserver. To do this each of your developers will need a code signing certificate and for them to configure it and a timeserver to authenticate both the person signing and the time of signing.
A pre-commit hook on the client can prevent accidental commit issues where the time is set incorrectly, but since the hook needs to be installed afte each clone (and can easily be removed) it provides little security against an adversary.
A pre-receive hook on the server can prevent accidental pushes to the central server that contain "old" commits, but may cause issues when you're importing repositories from another location (fork, mirror, etc).
Neither will prevent pushes where the local repo had changed times to within the safe time window of the server.
Your best approach here is to trust the "Pushes" metadata on the server for accurate timing of when data entered your organization and when old data was force pushed in. Possibly in combination with signing off commits with SMIME certificates and a timeserver.
See: https://www.glennwatson.net/posts/code-signing-github
GitHub setup
I am going to assume you want to use S/MIME signing for all your repositories. There are other options in the GitHub guide. We are going to generate a batch file to run smimesign due to a ongoing issue with timestamp authorities.
- Install S/MIME sign.
- Create a batch file that is in your path to smimesign. For windows the batch file sample (which you could name sign.cmd)
Copy to clipboard@echo off
smimesign.exe --timestamp-authority http://timestamp.digicert.com %*
- Tell git to use smimesign. From the command line run:
git config --global gpg.x509.program c:/path/to/sign.cmd
git config --global gpg.format x509
git config --global commit.gpgsign true
- Find the key you want to sign with. Run
smimesign --list-keys
and find the serial number of the key you wish to sign with. Copy the serial number of the key so you can paste it into the next command. Make sure you use the serial number not the ID.
- From the command line set the key to use
git config --global user.signingkey a2dfa7e8c9c4d1616f1009c988bb70f
Now each time you commit it will ask you for a passcode that you set earlier.
See also: Sign git commit with x509 certificate in corporate environment