In Git, how can I write the current hash hash to a file in the same commit

I'm trying to make fancy stuff here with git hooks, but I really don't know how to do this (or if possible).

What I need to do: in each commit, I want to take a hash, and then update the file in commit with this hash.

Any ideas?

+83
git hook
Aug 09 '10 at 18:15
source share
6 answers

I would recommend doing something similar to what you have in mind: placing SHA1 in a raw file generated as part of the build / install / deploy process. This is obviously easy to do ( git rev-parse HEAD > filename or maybe git describe [--tags] > filename ) and it avoids doing something crazy, like ending up with a file other than what git tracks .

Your code can then reference this file when it needs a version number, or the build process can include information in the final product. The latter is actually how git itself gets its version numbers - the build process captures the version number from the repo and then creates it in an executable file.

+57
Aug 09 '10 at 19:30
source share

Someone pointed me to the "man gitattributes" section on an identifier that has the following:

ident

When the attribute identifier is set for the path, git replaces $ Id $ in the blob with $ Id :, then the 40-character hexadecimal name of the blob object, followed by the dollar sign $ at checkout. Any sequence of bytes that starts with $ Id: and ends with $ in the worktree file, $ Id $ is replaced during registration.

If you think about it, this is what CVS, Subversion, etc. do. If you look at the repository, you will see that the file in the repository always contains, for example, $ Id $. It never contains an extension of this. This is only when checking that the text is expanded.

+12
Jan 25 '13 at 2:33
source share

It is not possible to write the current commit hash: if you manage to pre-calculate the future hash commit, it will change as soon as you modify any file.

However, there are three options:

  • Use a script to increase the "commit id" and enable it somewhere. Nasty
  • The .gitignore file in which you are going to store the hash. Not very comfortable
  • In pre-commit save the previous pre-commit hash :). You do not change / insert commits in 99.99% of cases, so this work will work. In the worst case, you can still identify the original version.

I am working on a hook script, will output it here โ€œwhen it will beโ€, but still - before Duke Nukem Forever is released :))

UPD : code for .git/hooks/pre-commit :

 #!/usr/bin/env bash set -e #=== 'prev-commit' solution by o_O Tync #commit_hash=$(git rev-parse --verify HEAD) commit=$(git log -1 --pretty="%H%n%ci") # hash \n date commit_hash=$(echo "$commit" | head -1) commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300 branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487 branch_name=${branch_name##refs/heads/} branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation # Write it echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py 

Now we only need a tool that converts the prev_commit,branch pair into a real commit hash :)

I do not know if this approach can say that the merger is merging. Check it out soon

+10
Dec 28 '10 at 14:27
source share

This can be achieved using the filter attribute in gitattributes . You will need to provide the smudge command, which inserts the commit identifier, and the clean command, which removes it, so that the file into which it is inserted does not change just because of the commit identifier.

Thus, the commit identifier is never stored in the file block; it just expanded in your working copy. (In fact, inserting the commit identifier into blob will be an infinitely recursive task.) Anyone who clones this tree will need to configure the attributes for themselves.

+8
Aug 09 '10 at 18:29
source share

I donโ€™t think you really want to do this, because when the file in the commit changes, the commit hash also changes.

+2
Aug 09 '10 at 18:30
source share

Let me tell you why this is a tricky issue using git internals. You can get sha1 of the current commit with

 #!/bin/bash commit=$(git cat-file commit HEAD) # sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum)) echo ${sha1[0]} 

Essentially, you run the sha1 checksum in the message returned by git cat-file commit HEAD . Two things immediately jump out due to a problem while viewing this post. One of them is the sha1 tree, and the second is the commit time.

Now the fixation time can be easily taken care of by changing the message and guessing how long it will take for the fixation or planning to fix it at a specific time. The real problem is the sha1 tree, which you can get from git ls-tree $(git write-tree) | git mktree git ls-tree $(git write-tree) | git mktree . Essentially, you execute the sha1 checksum in a message from ls-tree, which is a list of all files and their sha1 checksum.

Therefore, your checksum sha1 depends on your checksum sha1 of the tree, which directly depends on the checksum sha1 files, which completes the circle and depends on commit sha1. So you have a circular problem with the methods available to me.

With less secure checksums, it has been shown that it is possible to write a file checksum to a file directly using brute force; however, I do not know any work that accomplished this task with sha1. This is not impossible, but almost impossible with our current understanding (but who knows, maybe in a couple of years it will be trivial). However, this is even more difficult for brute force, since you need to write the checksum (commit) of the checksum (tree) of the checksum (blob) to the file.

0
Sep 29 '17 at 0:37
source share



All Articles