I am familiar with how Git creates SHA1 hashes for files (blobs), but not how they are created for tag objects. I assume they are, if I create an annotated tag, but what is the recipe? And how might I replicate it outside of Git (e.g., in Perl or Python)?
相关问题
- facebook error invalid key hash for some devices
- Why does recursive submodule update from github fa
- Extended message for commit via Visual Studio Code
- Emacs shell: save commit message
- Can I organize Git submodules in a flat hierarchy?
相关文章
- 请教Git如何克隆本地库?
- Bcrypt vs Hash in laravel
- GitHub:Enterprise post-receive hook
- Git Clone Fails: Server Certificate Verification F
- SSIS solution on GIT?
- Is there a version control system abstraction for
- ssh: Could not resolve hostname git: Name or servi
- Cannot commit changes with gitextensions
Reverse engineer the format from a minimal example
First we determine what the format for tags is:
outputs the tag sha:
so we do as explained at How to DEFLATE with a command line tool to extract a git object? :
which gives:
from which we deduce the format is:
From the
hd
we see that the full output is 0x326 == 806 bytes long which minus eight bytes from the prefix:tag 798.
makes the size798
.Analogous analysis for Git commit objects: What is the file format of a git commit object?
Minimal Python script that creates a tag object and gets its SHA
To ensure that we understood it correctly, here is a Python script that generates a working git repo from scratch, including a tag:
You can then
cd
into it and verify that all works normally withgit
commands.Tested on git 2.16.1, Ubuntu 18.04.
The content of a tag object is as follows:
Based on that text the SHA1 value is calculated.
Take a look at libgit2 and its various bindings.
The pattern is basically:
Where
data
is the output ofgit cat-file
. One can produce this by piping that output togit-hash-object
like so:And the equivalent a perl one-liner is:
It seems that one can do this same thing with any of the types objects simply by replacing
"tag "
with the proper object name:"blob "
,"tree "
, or"commit "
.It's pretty much the same, although the smallish header prepended to the commit object is different. You can use
git cat-file
to see the actual format.