Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

Git mktag: Construct Tag Objects with Validation

Construct annotated-tag objects from their canonical contents, understand the validation performed by git mktag, and distinguish tag objects from tag references.

Levels: Advanced ~25 min read

Advanced

A tag reference and a tag object are different things

A tag name such as `refs/tags/v1.0` is a reference. An annotated tag can point that reference at a separate tag object. The tag object stores the object being tagged, its object type, the tag name, tagger information, and the annotation message. `git mktag` works at the object layer: it reads the tag object's contents from standard input and writes the resulting tag object to the object database.

bash
# In a repository with at least one commit:
COMMIT=$(git rev-parse HEAD)
TIMESTAMP=$(git show -s --format=%ct HEAD)
printf 'object %s\ntype commit\ntag v-test\ntagger Test <test@example.com> %s +0000\n\nA manually constructed tag object.\n' "$COMMIT" "$TIMESTAMP" > tag.txt
git mktag < tag.txt

Quick check

What does `git mktag` create?

The input is the canonical tag-object content

The tag-object content identifies the target object with an `object` header, identifies its type with `type`, records the tag name with `tag`, and records the tagger with `tagger`. A blank line separates these headers from the annotation message. The exact bytes matter because Git hashes the complete object content when it creates the object ID.

bash
COMMIT=$(git rev-parse HEAD)
TIMESTAMP=$(git show -s --format=%ct HEAD)
cat > tag.txt <<EOF
object $COMMIT
type commit
tag v-test
tagger Test <test@example.com> $TIMESTAMP +0000

A manually constructed tag object.
EOF

git mktag < tag.txt

The example uses the current repository's HEAD and commit timestamp so the command is directly runnable. A tag object can target Git objects other than commits too; the `type` header identifies the target's object type.

Quick check

Why can two otherwise similar tag contents produce different object IDs?

`mktag` validates instead of merely hashing

`git mktag` is intentionally a validating constructor. It checks that the input has the structure required for a tag object and that the referenced object can be resolved. This distinguishes it from `git hash-object -t tag -w`, which can write bytes as a tag-typed object without providing the same tag-specific validation.

bash
# Valid tag object contents
git mktag < tag.txt

# A deliberately nonexistent target should be rejected.
printf '%s\n' \
  'object 0000000000000000000000000000000000000000' \
  'type commit' \
  'tag invalid' \
  "tagger Test <test@example.com> $TIMESTAMP +0000" \
  '' \
  'Bad target' | git mktag

Quick check

What is the important distinction between `git mktag` and `git hash-object -t tag -w`?

Strict validation and extra headers

`git mktag` enables the equivalent of `git fsck --strict` by default. The current official documentation also exposes `--strict` explicitly and `--no-strict` to disable that strict mode. Extra headers are errors by default, even though ordinary `git fsck` may treat some of them as warnings or ignore them.

bash
# Start from the valid tag.txt created above.
# Explicitly request the documented strict mode.
git mktag --strict < tag.txt

# Insert an extra header after the required tagger header.
{ head -n 4 tag.txt; printf '%s\n\n' 'extra-header value'; tail -n 1 tag.txt; } > tag-with-extra-header.txt

# Default strict validation rejects the extra header.
git mktag < tag-with-extra-header.txt

# Disable the strict mode for this deliberately nonstandard input.
git mktag --no-strict < tag-with-extra-header.txt

# The equivalent fsck configuration can also relax this particular check.
git -c fsck.extraHeaderEntry=ignore mktag < tag-with-extra-header.txt

Quick check

Which option disables the strict validation that `git mktag` enables by default?

The resulting object is a normal Git object

The object ID printed by `git mktag` can be inspected with the normal object-inspection commands. `git cat-file -t` reports its type, and `git cat-file -p` displays the stored tag contents. This lets you verify that the bytes accepted by `mktag` became a tag object in the object database.

bash
TAG_OBJECT=$(git mktag < tag.txt)
git cat-file -t "$TAG_OBJECT"
git cat-file -p "$TAG_OBJECT"

Quick check

Does `git mktag` create a `refs/tags/...` name for the new object?

Do not use `mktag` as a replacement for `git tag`

For normal annotated-tag workflows, `git tag -a`, `git tag -m`, or related porcelain commands are the appropriate interface because they create and manage the tag reference as part of the workflow. `git mktag` is a plumbing command for constructing and validating the tag object itself. The existing Foxipa tag lessons own tag-reference workflows and signature verification; this lesson owns the lower-level object-construction boundary.

Practice what you learned

Use the dedicated Git code-completion exercise for this lesson.

Was this page helpful?

Mark this learning resource complete to track your learning progress.