Skip to content

mktag Git Command Guide

The git mktag command reads a tag’s contents from standard input and creates a tag object with additional validation. It performs stricter checks than git hash-object, ensuring tag integrity and compliance with Git standards before writing the tag object.

Terminal window
git mktag
ParameterDescription
<tag-content>Tag content read from standard input
object <commit-sha>
type commit
tag <tag-name>
tagger <name> <email> <timestamp> <timezone>
<tag-message>
<optional-signature>
object: SHA-1 of the object being tagged
type: Object type (commit, tree, blob, tag)
tag: Tag name (e.g., v1.0.0)
tagger: Person creating the tag with timestamp
message: Tag description and release notes
object 1a2b3c4d5e6f7890abcdef1234567890abcdef12
type commit
tag v2.1.0
tagger John Doe <john@example.com> 1640995200 +0000
Release v2.1.0
- Added new authentication features
- Fixed security vulnerabilities
- Improved performance
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAABAgAGBQJgHn8EAAoJEGEJZQyWkVzJ8fQH/2wZGQ8...
-----END PGP SIGNATURE-----
Terminal window
# Create annotated tag from content
cat > tag-content.txt << EOF
object 9fceb02d0ae598e95dc970b74767f19372d61af8
type commit
tag v1.0.0
tagger John Doe <john@example.com> 1609459200 +0000
Release v1.0.0
This is the first stable release.
EOF
git mktag < tag-content.txt
# Output: 9fceb02d0ae598e95dc970b74767f19372d61af8
Terminal window
# Create GPG-signed tag content
cat > signed-tag.txt << EOF
object 1a2b3c4d5e6f7890abcdef1234567890abcdef12
type commit
tag v2.0.0
tagger Alice Developer <alice@example.com> 1640995200 +0000
Release v2.0.0
Major release with new features.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAABAgAGBQJgHn8EAAoJEGEJZQyWkVzJ8fQH/2wZGQ8...
-----END PGP SIGNATURE-----
EOF
git mktag < signed-tag.txt
Terminal window
# Create tag and verify it exists
TAG_SHA=$(git mktag < tag-content.txt)
echo "Created tag: $TAG_SHA"
# Verify tag object
git cat-file -t "$TAG_SHA" # Should output: tag
git cat-file -p "$TAG_SHA" # Show tag content
#!/bin/bash
# Generate release tags programmatically
create_release_tag() {
local version="$1"
local commit_sha="$2"
local release_notes="$3"
local tagger_name="${4:-$(git config user.name)}"
local tagger_email="${5:-$(git config user.email)}"
# Generate timestamp
local timestamp=$(date +%s)
local timezone=$(date +%z)
# Create tag content
cat > "/tmp/tag-$version.txt" << EOF
object $commit_sha
type commit
tag v$version
tagger $tagger_name <$tagger_email> $timestamp $timezone
Release v$version
$release_notes
Generated by automated release script.
EOF
# Create tag object
local tag_sha=$(git mktag < "/tmp/tag-$version.txt")
echo "Created tag v$version: $tag_sha"
# Update refs/tags
git update-ref "refs/tags/v$version" "$tag_sha"
# Clean up
rm "/tmp/tag-$version.txt"
echo "$tag_sha"
}
# Usage
create_release_tag "3.2.1" "abc123..." "Bug fixes and performance improvements"
Terminal window
# Create signed tag with GPG
create_signed_tag() {
local tag_name="$1"
local commit_sha="$2"
local message="$3"
local key_id="$4"
# Create unsigned tag content
local temp_file=$(mktemp)
cat > "$temp_file" << EOF
object $commit_sha
type commit
tag $tag_name
tagger $(git config user.name) <$(git config user.email)> $(date +%s) $(date +%z)
$message
EOF
# Sign the content
local signature=$(gpg --detach-sign --armor --local-user "$key_id" "$temp_file" 2>/dev/null | grep -v "^-----")
# Add signature to tag content
cat >> "$temp_file" << EOF
-----BEGIN PGP SIGNATURE-----
$signature
-----END PGP SIGNATURE-----
EOF
# Create signed tag
local tag_sha=$(git mktag < "$temp_file")
echo "Created signed tag: $tag_sha"
rm "$temp_file"
echo "$tag_sha"
}
# Usage
create_signed_tag "v1.0.0" "abc123..." "Release notes..." "your-key-id"
Terminal window
# Test tag creation without committing
validate_tag_content() {
local tag_file="$1"
echo "Validating tag content..."
# Test mktag creation
if tag_sha=$(git mktag < "$tag_file" 2>/dev/null); then
echo "✓ Tag syntax is valid: $tag_sha"
# Verify tag content
git cat-file -p "$tag_sha" > /dev/null
# Additional validation
if git fsck --unreachable "$tag_sha" 2>/dev/null; then
echo "✓ Tag passes fsck validation"
return 0
else
echo "✗ Tag fails fsck validation"
return 1
fi
else
echo "✗ Invalid tag syntax"
return 1
fi
}
# Usage
validate_tag_content "proposed-tag.txt"
#!/bin/bash
# Complete release tagging workflow
perform_release() {
local version="$1"
local branch="${2:-main}"
echo "=== Release v$version ==="
# Switch to release branch
git checkout "$branch"
git pull origin "$branch"
# Get current commit
local commit_sha=$(git rev-parse HEAD)
# Generate release notes
local release_notes=$(generate_release_notes "$version")
# Create tag content
local tag_content=$(mktemp)
cat > "$tag_content" << EOF
object $commit_sha
type commit
tag v$version
tagger $(git config user.name) <$(git config user.email)> $(date +%s) $(date +%z)
Release v$version
$release_notes
This tag was created using git mktag for enhanced validation.
EOF
# Validate tag
if validate_tag_content "$tag_content"; then
# Create tag object
local tag_sha=$(git mktag < "$tag_content")
# Update tag reference
git update-ref "refs/tags/v$version" "$tag_sha"
# Push tag
git push origin "refs/tags/v$version"
echo "✓ Release v$version tagged successfully: $tag_sha"
else
echo "✗ Tag validation failed"
exit 1
fi
rm "$tag_content"
}
generate_release_notes() {
local version="$1"
# Implementation for generating release notes
echo "Release notes for v$version..."
}
# Usage
perform_release "2.1.0" "main"
Terminal window
# CI/CD tag signing workflow
sign_release_tag() {
local version="$1"
local commit_sha="$2"
local gpg_key_id="$3"
echo "Signing release tag v$version..."
# Create tag content
local tag_file=$(mktemp)
cat > "$tag_file" << EOF
object $commit_sha
type commit
tag v$version
tagger CI Bot <ci@example.com> $(date +%s) +0000
Release v$version
Automated release build.
EOF
# Sign tag content
gpg --detach-sign --armor --local-user "$gpg_key_id" "$tag_file" >> "$tag_file"
# Create signed tag object
local tag_sha=$(git mktag < "$tag_file")
# Update tag reference
git update-ref "refs/tags/v$version" "$tag_sha"
echo "Created signed tag: $tag_sha"
rm "$tag_file"
# Verify signature
if git verify-tag "v$version" 2>/dev/null; then
echo "✓ Tag signature verified"
else
echo "✗ Tag signature verification failed"
return 1
fi
}
# Usage in CI
sign_release_tag "1.5.0" "$(git rev-parse HEAD)" "release-key-id"
Terminal window
# Import tags from external systems
import_external_tags() {
local tag_data_file="$1"
echo "Importing tags from external system..."
while IFS='|' read -r tag_name commit_sha tagger_name tagger_email timestamp message; do
# Create tag content
local tag_content=$(mktemp)
cat > "$tag_content" << EOF
object $commit_sha
type commit
tag $tag_name
tagger $tagger_name <$tagger_email> $timestamp +0000
$message
Imported from external system.
EOF
# Create tag object
local tag_sha=$(git mktag < "$tag_content")
# Update tag reference
git update-ref "refs/tags/$tag_name" "$tag_sha"
echo "Imported tag $tag_name: $tag_sha"
rm "$tag_content"
done < "$tag_data_file"
}
# Usage
import_external_tags "external-tags.csv"
Terminal window
# Configure GPG for tag signing
git config user.signingkey "your-gpg-key-id"
git config commit.gpgsign true # Also sign commits
# List available GPG keys
gpg --list-secret-keys --keyid-format LONG
# Test GPG signing
echo "test" | gpg --detach-sign --armor - > /dev/null
Terminal window
# Custom tag validation script
validate_tag_format() {
local tag_content="$1"
# Check required fields
grep -q "^object " "$tag_content" || { echo "Missing object field"; return 1; }
grep -q "^type " "$tag_content" || { echo "Missing type field"; return 1; }
grep -q "^tag " "$tag_content" || { echo "Missing tag field"; return 1; }
grep -q "^tagger " "$tag_content" || { echo "Missing tagger field"; return 1; }
# Validate object SHA
local object_sha=$(grep "^object " "$tag_content" | cut -d' ' -f2)
git cat-file -e "$object_sha" 2>/dev/null || { echo "Invalid object SHA"; return 1; }
# Validate tag name format
local tag_name=$(grep "^tag " "$tag_content" | cut -d' ' -f2)
[[ "$tag_name" =~ ^[a-zA-Z0-9._-]+$ ]] || { echo "Invalid tag name format"; return 1; }
echo "Tag format validation passed"
return 0
}
# Usage
validate_tag_format "tag-content.txt"
Terminal window
# Optimize for large repositories
git config core.packedGitLimit 128m
git config core.packedGitWindowSize 16m
# Cache GPG operations
gpgconf --reload gpg-agent
# Parallel tag operations
create_tags_parallel() {
local tag_list="$1"
# Process tags in parallel
cat "$tag_list" | xargs -n 1 -P 4 -I {} bash -c '
tag_file="$1"
tag_sha=$(git mktag < "$tag_file")
echo "Created: $tag_sha from $tag_file"
' _ {}
}
# Usage
create_tags_parallel "tag-files.list"
Terminal window
# Debug mktag failures
GIT_TRACE=1 git mktag < tag-content.txt
# Check tag content format
cat tag-content.txt | head -10
# Validate individual fields
grep "^object " tag-content.txt
grep "^type " tag-content.txt
grep "^tag " tag-content.txt
grep "^tagger " tag-content.txt
Terminal window
# Check GPG key availability
gpg --list-secret-keys
# Test GPG signing
echo "test" | gpg --detach-sign --armor -
# Check GPG agent
gpgconf --list-options gpg-agent
# Restart GPG agent if needed
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent
Terminal window
# Verify object exists
git cat-file -t <object-sha>
# Check object is reachable
git fsck --unreachable | grep <object-sha>
# Find object in repository
git log --all --oneline | grep <object-sha>
Terminal window
# Check repository permissions
ls -la .git/
# Verify write access
touch .git/test-write && rm .git/test-write
# Check disk space
df -h .
#!/bin/bash
# Enterprise tag creation with compliance
enterprise_tag_creation() {
local version="$1"
local approval_ticket="$2"
local security_scan_id="$3"
echo "=== Enterprise Tag Creation: v$version ==="
echo "Approval Ticket: $approval_ticket"
echo "Security Scan: $security_scan_id"
# Validate prerequisites
if ! security_scan_passed "$security_scan_id"; then
echo "✗ Security scan failed - cannot create tag"
exit 1
fi
if ! approval_granted "$approval_ticket"; then
echo "✗ Approval not granted - cannot create tag"
exit 1
fi
# Get release commit
local release_commit=$(get_release_commit "$version")
# Create compliant tag content
local tag_content=$(mktemp)
cat > "$tag_content" << EOF
object $release_commit
type commit
tag v$version
tagger $(git config user.name) <$(git config user.email)> $(date +%s) $(date +%z)
Enterprise Release v$version
Approval Ticket: $approval_ticket
Security Scan: $security_scan_id
Compliance Status: VERIFIED
Release Notes:
$(get_release_notes "$version")
Created with git mktag for enhanced validation.
EOF
# Sign with enterprise key
gpg_sign_content "$tag_content" "enterprise-release-key"
# Create tag with validation
local tag_sha=$(git mktag < "$tag_content")
# Compliance logging
log_compliance_event "TAG_CREATED" "$tag_sha" "$approval_ticket"
# Update tag reference
git update-ref "refs/tags/v$version" "$tag_sha"
echo "✓ Enterprise tag v$version created: $tag_sha"
rm "$tag_content"
}
# Helper functions (implement based on enterprise systems)
security_scan_passed() { return 0; } # Mock implementation
approval_granted() { return 0; } # Mock implementation
get_release_commit() { git rev-parse HEAD; }
get_release_notes() { echo "Release notes for $1"; }
gpg_sign_content() { echo "Mock signing"; }
log_compliance_event() { echo "Logged: $1 $2 $3"; }
# Usage
enterprise_tag_creation "5.1.0" "TICKET-12345" "SCAN-67890"
Terminal window
# Automated tag lifecycle management
manage_tag_lifecycle() {
local action="$1"
local tag_pattern="$2"
case "$action" in
"create")
# Create tags for all release branches
git branch -r | grep "origin/release/" | while read branch; do
local version=$(echo "$branch" | sed 's|origin/release/||')
local commit_sha=$(git rev-parse "$branch")
create_release_tag "$version" "$commit_sha"
done
;;
"verify")
# Verify all tags pass validation
git tag | grep "$tag_pattern" | while read tag; do
local tag_sha=$(git rev-parse "refs/tags/$tag")
if git fsck "$tag_sha" >/dev/null 2>&1; then
echo "✓ Tag $tag is valid"
else
echo "✗ Tag $tag is invalid"
fi
done
;;
"cleanup")
# Remove old development tags
git tag | grep "$tag_pattern" | xargs git tag -d
;;
esac
}
# Usage
manage_tag_lifecycle "verify" "v[0-9]+\.[0-9]+\.[0-9]+"
Terminal window
# Sync tags between repositories
sync_repository_tags() {
local source_repo="$1"
local target_repo="$2"
echo "Syncing tags from $source_repo to $target_repo..."
# Get all tags from source
git ls-remote --tags "$source_repo" | while read sha ref; do
local tag_name=$(echo "$ref" | sed 's|refs/tags/||')
# Check if tag exists in target
if ! git ls-remote --tags "$target_repo" | grep -q "$ref"; then
echo "Syncing tag: $tag_name"
# Get tag object from source
git cat-file -p "$sha" > tag-content.tmp
# Create tag in target repository
cd "$target_repo"
local new_sha=$(git mktag < ../tag-content.tmp)
git update-ref "$ref" "$new_sha"
cd - >/dev/null
fi
done
rm -f tag-content.tmp
echo "Tag synchronization complete"
}
# Usage
sync_repository_tags "/path/to/source" "/path/to/target"

What’s the difference between git mktag and git tag?

Section titled “What’s the difference between git mktag and git tag?”

git tag creates tags through Git’s porcelain interface with user interaction; git mktag creates tag objects directly from content with stricter validation, useful for automation and custom workflows.

Create tag content with message, then use GPG to sign it and append the signature block. The signature must follow the -----BEGIN PGP SIGNATURE----- format for Git to recognize it.

No, mktag only creates annotated tag objects. Lightweight tags are just references and don’t have their own objects. Use git update-ref for lightweight tags.

What’s the validation difference between mktag and hash-object?

Section titled “What’s the validation difference between mktag and hash-object?”

mktag performs fsck validation (stricter than default) and promotes warnings to errors for tag-specific issues like missing tagger lines. hash-object only validates basic object format.

Check tag content format, ensure all required fields are present, verify object SHA exists, and test with git fsck. Use GIT_TRACE=1 for detailed debugging output.

Can mktag work with tag objects pointing to other tags?

Section titled “Can mktag work with tag objects pointing to other tags?”

Yes, set type to “tag” and object to another tag’s SHA. This creates tag chains useful for maintaining tag hierarchies.

What’s the performance impact of mktag validation?

Section titled “What’s the performance impact of mktag validation?”

Minimal for individual tags. The fsck validation adds small overhead but ensures tag integrity. Performance scales with repository size for object validation.

How do I integrate mktag with CI/CD pipelines?

Section titled “How do I integrate mktag with CI/CD pipelines?”

Use mktag in scripts for automated tag creation, combine with GPG signing for secure releases, validate tags before pushing to prevent invalid tag propagation.

Can mktag create tags for different object types?

Section titled “Can mktag create tags for different object types?”

Yes, supports commits, trees, blobs, and other tags. Set the “type” field accordingly and ensure the object SHA matches the specified type.

What’s the relationship between mktag and git update-ref?

Section titled “What’s the relationship between mktag and git update-ref?”

mktag creates the tag object; git update-ref creates the reference pointing to it. Both are needed to create a complete tag in the repository.

How do I handle mktag in bare repositories?

Section titled “How do I handle mktag in bare repositories?”

Works normally since it operates on objects, not working directory. Useful for server-side tag creation and validation.

No, mktag only creates new tags. Use git fsck or git cat-file to validate existing tags.

What’s the storage impact of using mktag?

Section titled “What’s the storage impact of using mktag?”

Each tag object adds minimal storage (header + content). Annotated tags are preferred over lightweight for better metadata and validation.

  1. Automated Release Tagging: Create validated release tags in CI/CD pipelines with enhanced security checks
  2. Tag Signing and Verification: Generate cryptographically signed tags for secure software distribution
  3. Custom Tag Workflows: Implement specialized tagging processes with programmatic validation
  4. Repository Migration: Migrate tags between repositories with content validation and integrity checking
  5. Enterprise Compliance: Support regulated environments requiring strict tag validation and audit trails
  6. Tag Automation: Enable scripted tag creation with custom metadata and validation rules