Recover and Verify a Commit ID from a Git Tar Archive
You will finish with a small, reproducible check that extracts the commit ID embedded in a tar archive made by git archive. This is useful when a release tarball has arrived without its repository metadata and you need to compare it with a known Git object.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need Git installed and a tar stream to inspect. The examples were checked with Git 2.43.0 from Ubuntu package git 1:2.43.0-1ubuntu7.3 and git-man 1:2.43.0-1ubuntu7.3. The command reads standard input, so it does not need elevated privileges. Do not use sudo unless a separate file-permission problem actually requires it.
1. Confirm the installed command
Check the version and the command's built-in synopsis. These are ordinary read-only commands:
$ git --version
git version 2.43.0
$ git get-tar-commit-id --help
GIT-GET-TAR-COMMIT-ID(1) Git Manual GIT-GET-TAR-COMMIT-ID(1)
NAME
git-get-tar-commit-id - Extract commit ID from an archive created using
git-archive
The complete invocation is simply git get-tar-commit-id. It takes no archive filename and no commit argument. The archive must be piped to its standard input.
Checkpoint
If you have a file rather than a stream, make sure it is the archive you intend to inspect before piping it. The command will not modify that file.
2. Extract an ID from a Git-created tar archive
From a Git repository, pipe a commit-based tar archive directly into the command:
$ git archive --format=tar HEAD | git get-tar-commit-id
f4423bb9c051d35165bef811cda2a53d611140b3
Your hexadecimal value will differ. It is the ID of HEAD at the time the archive was created. Store the value if a later comparison needs an explicit expected object:
$ expected=$(git rev-parse HEAD)
$ actual=$(git archive --format=tar HEAD | git get-tar-commit-id)
$ test "$actual" = "$expected" && echo 'archive matches HEAD'
archive matches HEAD
This comparison tests the archive's embedded identity, not just the names and contents that happen to be present in it. A later commit can have similar files while still producing a different ID.
3. Inspect an existing archive file
For an uncompressed tar file, redirect it into standard input:
$ git get-tar-commit-id < release.tar
f4423bb9c051d35165bef811cda2a53d611140b3
To verify the value against a known commit, compare it with git rev-parse:
$ archive_id=$(git get-tar-commit-id < release.tar)
$ expected_id=$(git rev-parse RELEASE_COMMIT)
$ if [ "$archive_id" = "$expected_id" ]; then
> echo 'release archive verified'
> else
> printf 'expected %s, got %s\n' "$expected_id" "$archive_id" >&2
> exit 1
> fi
release archive verified
Replace RELEASE_COMMIT with a real commit or tag that you trust. Do not paste an unverified value into a deployment script simply because the command returned a syntactically valid-looking string.
4. Handle compressed tarballs at the right boundary
git get-tar-commit-id reads a tar archive, not a gzip or zip container. Decompress a gzip-compressed tar stream first:
$ gzip -dc release.tar.gz | git get-tar-commit-id
f4423bb9c051d35165bef811cda2a53d611140b3
Equivalently, create a compressed archive and inspect it through the matching decompressor:
$ git archive --format=tar.gz HEAD | gzip -dc | git get-tar-commit-id
f4423bb9c051d35165bef811cda2a53d611140b3
A zip archive stores Git's commit ID in a file comment rather than in a tar header. Passing zip bytes to this command is the wrong format and can produce an error such as EOF before reading tar header. Use the archive format's own metadata tools instead of trying alternate flags: this command has no format-selection option.
5. Read the exit status, not only the output
A successful extraction returns status 0 and writes the ID to standard output. A valid tar archive without Git's embedded commit ID returns status 1 and writes nothing. One common cause is archiving a tree ID rather than a commit or tag:
$ tree_id=$(git rev-parse HEAD^{tree})
$ git archive --format=tar "$tree_id" | git get-tar-commit-id
$ printf 'status: %s\n' "$?"
status: 1
That archive can still contain perfectly usable files. Status 1 means this particular identity check cannot recover a commit ID from it; it does not mean that extracting the tar archive will fail.
Malformed or empty input is different from a valid tar with no embedded ID. On Git 2.43.0, an empty stream reports a fatal tar-header error and returns status 128. Treat any status other than 0 as a failed verification, then investigate the input format and the way the archive was created.
Checkpoint
A script should capture the status immediately, before another command overwrites $?:
git get-tar-commit-id < release.tar > archive-id
status=$?
if [ "$status" -ne 0 ]; then
printf 'no Git commit ID recovered, status %s\n' "$status" >&2
exit "$status"
fi
printf 'archive commit: %s\n' "$(cat archive-id)"
6. Know what the command can and cannot prove
The command reads only the first 1024 bytes of input, so its running time is largely independent of the archive's total size. It does not unpack files, inspect their contents, validate a signature, or prove that an archive came from a trusted person. The embedded ID is useful evidence for identifying the Git object, but authenticity still requires a separate trust check, such as verifying a signed tag or a published checksum through a trusted channel.
Git records the commit ID in a global extended POSIX pax header when git archive creates a tar archive from a commit or tag. A tree ID has no commit object to record, so it deliberately omits that identity. This is why changing the first argument to HEAD^{tree} changes the result even though the file snapshot may be the same.
No example here changes repository state, files or services, so there is nothing to undo. If your verification script is going to gate a release, keep the archive and the captured ID until the release record has been written; deleting them is an operational choice outside this command.
Done means
- You confirmed the installed Git version and used the standard-input interface.
- A commit-based tar archive returned the expected hexadecimal object ID and status 0.
- You decompressed
.tar.gzinput before passing it to the command. - You distinguish status 1 for a valid tar without a commit ID from malformed-input errors.
- You understand that extraction identifies an object but does not authenticate the release.