francesco
francesco

Reputation: 7539

git commit --amend with same hash

Suppose I have a program in a git repository. This program, among other things, writes in the output the an identifier of the git commit with which the program was compiled. This identifier is obtained with

git describe --abbrev=6 --dirty --always --tags

The repository contains also a sample of output of the program; this sample output contains then the git identifier.

When I commit a new version, I need to simultaneously update also the sample output inside the repository. Therefore I do as follows:

Because I compile the program in a "dirty" state, the version git identifier will contain the "-dirty" substring. This is not particularly useful to keep track of the "version" with which the sample output was obtained. Therefore I need to compile and run again the program, this time in a "clean" state, and save the sample output; this now contains the new identifier.

Clearly this is not optimal, as I have to do 2 commits for a single change.

I would like instead to have a sample output obtained from a program compiled in a "clean" repository, without an intermediate commit.

Is is possible to obtain something like that?

Notice that I cannot use git --amend because it will change the hash completely.

Upvotes: 0

Views: 357

Answers (1)

torek
torek

Reputation: 487715

You can't really get this perfectly, because a commit hash ID is affected by everything in the commit. This means that if the predicted describe output is wrong, the resulting commit will embed the wrong text. But: it is, or at least can be, easy to predict what your git describe output will be, given what you already know about how you plan to do your tagging and so on.

Hence, just run the git describe command you intend to run later. This will include the -dirty and other stuff. Now, use another program you write—such as a sed script or dinky Python or Perl script or whatever—to change this into what you predict you would get if you had actually committed this in a clean state. You will have to omit the commit's hash ID because predicting a future hash ID is literally impossible: even if you knew what it would be, adding the hash ID to the contents of the commit changes the contents of the commit, which changes the hash ID, so you have to predict what the hash ID of the commit containing the hash ID will be.1 But git describe output just has the tag name, as long as there's a tag for that commit.

Now, think about this for a moment, and then realize: you're going to have to tag the commit. Instead of predicting what git describe is going to use for a tag after you enter a tag for the commit, just predict what tag you're going to use by using the tag in the text, then using the tag later after you've built that commit.


1This requires either finding a fixed point in the hash function, which is really hard, or coming up with two commits that hash to the same hash ID, which is less hard but still really hard (see http://shattered.it/: you'll need a "junk space" area in the commit, perhaps in the form of an otherwise unused file, or invisible text in the commit message, or something).

Upvotes: 1

Related Questions