Expanding Git SHA1 information into a checkin without archiving?
Asked Answered
A

5

5

Is there a way to include git commit hashes inside a file everytime I commit? I can only find out how to do this during archiving but I haven't been able to find out how to do this for every commit.

I'm doing scientific programming with git as revision control, so this kind of functionality would be very helpful for reproducibility reasons (i.e., have the git hash automatically included in all result files and figures).

Alben answered 17/5, 2010 at 22:1 Comment(0)
U
2

You can easily put SHA-1 of file (to be more exact SHA-1 of blob, i.e. SHA-1 of contents of the file) by using $Id$ keywork and ident gitattribute.

If you want to put SHA-1 of commit, there is no out-of-the-box solution, but you can use clean and smudge commands of filter gitattribute. Note that would badly affect performance, as after commit each file would have to be modified to reflect new commit made.


Although as said in other answers to this question, you would do better on embedding version number in generated files when building, like e.g. Linux kernel and git project itself do it.

Unilobed answered 18/5, 2010 at 12:57 Comment(0)
I
2

Greg explained in his answer why this would be impossible

ident

When the attribute ident is set for a path, git replaces $Id$ in the blob object with $Id:, followed by the 40-character hexadecimal blob object name, followed by a dollar sign $ upon checkout.
Any byte sequence that begins with $Id: and ends with $ in the worktree file is replaced with $Id$ upon check-in.

That means the usual workaround is, through some kind of build process, to include the information you need in a versioned but separate file.
In your case, a file with the list of all other files and their SHA1 value.
Such files might be generated at each commit (amending the commit which just took place) for instance.


As an example of a separate file, Jefromi points out the VERSION file of Git itself, build by this script

elif test -d .git -o -f .git &&
         VN=$(git describe --match "v[0-9]*" --abbrev=4 HEAD 2>/dev/null) &&
         case "$VN" in
         *$LF*) (exit 1) ;;
         v[0-9]*)
                 git update-index -q --refresh
                 test -z "$(git diff-index --name-only HEAD --)" ||
                 VN="$VN-dirty" ;;
         esac
then
Intense answered 18/5, 2010 at 4:4 Comment(1)
Git itself provides an example of this - if you build from its git repository, it'll include the abbreviated commit has in the version number. Good proof it's (one of the) right way(s) to go. Here's the (tracked) script which generates the version number: git.kernel.org/?p=git/…Koblick
U
2

You can easily put SHA-1 of file (to be more exact SHA-1 of blob, i.e. SHA-1 of contents of the file) by using $Id$ keywork and ident gitattribute.

If you want to put SHA-1 of commit, there is no out-of-the-box solution, but you can use clean and smudge commands of filter gitattribute. Note that would badly affect performance, as after commit each file would have to be modified to reflect new commit made.


Although as said in other answers to this question, you would do better on embedding version number in generated files when building, like e.g. Linux kernel and git project itself do it.

Unilobed answered 18/5, 2010 at 12:57 Comment(0)
G
1

Including the commit hash inside files included in the commit would necessarily change the hash. In order to provide repository integrity through the SHA1 hash mechanism, Git doesn't (and cannot) support such a feature.

Gagnon answered 17/5, 2010 at 22:6 Comment(2)
Is it possible then to have a workaround of this? The goal is just to be able to refer to the code used to generate computed results using the SHA1.Alben
@Tim Lin: One approach might be to build in the hash a part of your compile process (rather than actually checking it in to Git). See #1705407 for a number of good tips.Gagnon
O
0

have the git hash automatically included in all result files and figures.

You can pass the hash as an input to the program somehow (e.g. as an environment variable).

This alone doesn't guarantee that you're passing the right hash though.

Maybe you can write a script that checks-out a specific commit (by hash or ref) to a special (or temporary) directory, does an automated build, then runs the program and passes the commit hash as an input to the program.

This way you'll have more confidence that you're getting the right hash.

But still, someone can totally pass any bogus hash and create misleading figures.

Overprize answered 18/5, 2010 at 0:3 Comment(0)
W
0

you can simply use the following bash script (save it to .git/hooks/post-commit)

#!/bin/bash

# break self-recursiveness
git log | head -n6 | grep -q 'version.h update' && exit 0

commit_id=`git log | head -n3 | grep commit`
v_date=`git log | head -n3 | grep -i date | sed 's|[dD]ate:\s*\(.*\)|\1|'`

sed -i "s|#define COMMIT.*|#define COMMIT \"${commit_id}\"|" server/version.h
sed -i "s|#define V_DATE.*|#define V_DATE \"${v_date}\"|" server/version.h

git commit -m"version.h update" server/version.h
exit 0

for reference, server/version.h should look like this and it will get updated after every commit:

#ifndef __version_h__
#define __version_h__

#define COMMIT "commit 2e44e754a9002c99bbf4c09e7827f307d5f0d6f9"
#define V_DATE "Sat Aug 20 19:35:47 2016 +0300"

#endif
Watersoak answered 20/8, 2016 at 16:38 Comment(1)
I copied the contents of the bash script to a file named post-commit.sh and put it at .git/hooks. Then I copied the contents of server/version.sh to a file version.h and put in a git project. Next I ran git add and git commit commands git push origin commands to push the version.h. The commit happened successfully but the version.h did not get updated with the latest commit.Freud

© 2022 - 2024 — McMap. All rights reserved.