Skip to content

verify-pack Git Command Guide

The git verify-pack command validates pack files for corruption and displays detailed information about their contents, including object types, sizes, and deltas. It’s essential for diagnosing repository issues, optimizing storage, and ensuring data integrity.

Terminal window
git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx
git verify-pack --stdin [-v | --verbose] [-s | --stat-only] [--fix-thin] < <pack>
OptionDescription
-v, --verboseShow objects contained in pack
-s, --stat-onlyShow statistics only (no object list)
--fix-thinStream complete objects for thin packs
--stdinRead pack from stdin instead of file
ParameterDescription
<pack>.idxPack index file to verify
<pack>Pack file (when using —stdin)
Git Pack File Components:
├── Pack File (.pack): Compressed object data
├── Pack Index (.idx): Lookup table for objects
├── Object Types: Commits, trees, blobs, tags, deltas
├── Delta Chains: Space-efficient object storage
├── Checksums: SHA-1 integrity verification
└── Metadata: Object offsets and types
Pack File Verification Steps:
├── Header Validation: Check pack signature and version
├── Checksum Verification: Validate SHA-1 integrity
├── Object Parsing: Ensure all objects are valid
├── Delta Resolution: Verify delta chains are correct
├── Cross-Reference Check: Validate internal references
└── Index Consistency: Verify index matches pack content
Pack Object Information:
├── Object SHA-1: Unique identifier
├── Object Type: commit, tree, blob, tag
├── Object Size: Compressed and uncompressed sizes
├── Delta Base: Reference for delta-compressed objects
├── Chain Length: Delta chain depth
└── Offset: Position in pack file
Terminal window
# Verify specific pack file
git verify-pack .git/objects/pack/pack-abc123.idx
# Verify all pack files
for idx in .git/objects/pack/*.idx; do
echo "Verifying $idx..."
git verify-pack "$idx" || echo "Failed: $idx"
done
# Verify pack from stdin
cat pack-file.pack | git verify-pack --stdin
Terminal window
# Show pack statistics only
git verify-pack --stat-only .git/objects/pack/pack-abc123.idx
# Show detailed object information
git verify-pack -v .git/objects/pack/pack-abc123.idx
Terminal window
# List all objects in pack
git verify-pack -v .git/objects/pack/pack-abc123.idx | head -20
# Count objects by type
git verify-pack -v .git/objects/pack/pack-abc123.idx | awk '
/blob/ {blobs++}
/tree/ {trees++}
/commit/ {commits++}
/tag/ {tags++}
END {print "Blobs:", blobs, "Trees:", trees, "Commits:", commits, "Tags:", tags}
'
# Find largest objects
git verify-pack -v .git/objects/pack/pack-abc123.idx | sort -k3 -nr | head -10
Terminal window
# Analyze repository pack health
analyze_pack_health() {
echo "=== Repository Pack Health Analysis ==="
# Check all pack files
total_objects=0
total_size=0
for idx in .git/objects/pack/*.idx; do
echo "Analyzing $(basename "$idx")..."
# Get pack statistics
stats=$(git verify-pack --stat-only "$idx")
objects=$(echo "$stats" | grep "objects" | cut -d' ' -f1)
size=$(echo "$stats" | grep "pack-sz" | cut -d' ' -f1)
echo " Objects: $objects"
echo " Size: $size bytes"
total_objects=$((total_objects + objects))
total_size=$((total_size + size))
done
echo "Total objects: $total_objects"
echo "Total pack size: $total_size bytes"
echo "Average object size: $((total_size / total_objects)) bytes"
}
# Find unreachable objects
find_unreachable_objects() {
echo "Finding unreachable objects in packs..."
# Get all packed objects
git verify-pack -v .git/objects/pack/*.idx | cut -d' ' -f1 | sort > packed_objects.txt
# Get all reachable objects
git rev-list --all --objects | cut -d' ' -f1 | sort > reachable_objects.txt
# Find unreachable objects
comm -23 packed_objects.txt reachable_objects.txt > unreachable.txt
unreachable_count=$(wc -l < unreachable.txt)
echo "Found $unreachable_count unreachable objects"
if [ "$unreachable_count" -gt 0 ]; then
echo "Unreachable objects:"
head -10 unreachable.txt
echo "..."
fi
# Cleanup
rm packed_objects.txt reachable_objects.txt unreachable.txt
}
Terminal window
# Analyze pack efficiency
analyze_pack_efficiency() {
echo "=== Pack File Efficiency Analysis ==="
for idx in .git/objects/pack/*.idx; do
echo "Pack: $(basename "$idx")"
# Get detailed object info
git verify-pack -v "$idx" | while read -r sha type size offset; do
# Analyze delta chains
if [[ "$type" == *"delta"* ]]; then
chain_length=$(git verify-pack -v "$idx" | grep -c "^$sha")
echo "Delta object: $sha, chain length: $chain_length"
fi
done
# Calculate compression ratio
pack_size=$(stat -f%z "${idx%.idx}.pack" 2>/dev/null || stat -c%s "${idx%.idx}.pack")
object_sizes=$(git verify-pack -v "$idx" | awk '{sum += $3} END {print sum}')
ratio=$((object_sizes / pack_size))
echo "Compression ratio: ${ratio}:1"
echo
done
}
# Repack for better compression
optimize_packs() {
echo "Optimizing pack files..."
# Unpack all objects
temp_dir=$(mktemp -d)
for pack in .git/objects/pack/*.pack; do
git unpack-objects < "$pack" 2>/dev/null
done
# Remove old packs
rm -f .git/objects/pack/*.pack .git/objects/pack/*.idx
# Repack with optimal settings
git config pack.window 250
git config pack.depth 250
git config pack.compression 9
git repack -a -d --depth=250 --window=250
# Cleanup temp directory
rm -rf "$temp_dir"
echo "Pack optimization complete"
}
Terminal window
# Detect pack file corruption
detect_corruption() {
echo "Detecting pack file corruption..."
corrupted_packs=()
for idx in .git/objects/pack/*.idx; do
pack_file="${idx%.idx}.pack"
echo "Checking $(basename "$idx")..."
# Verify pack integrity
if ! git verify-pack "$idx" >/dev/null 2>&1; then
echo "✗ Corrupted: $(basename "$idx")"
corrupted_packs+=("$idx")
else
echo "✓ Valid: $(basename "$idx")"
fi
done
if [ ${#corrupted_packs[@]} -gt 0 ]; then
echo "Found ${#corrupted_packs[@]} corrupted pack(s)"
echo "Consider running: git fsck --full"
else
echo "All pack files are valid"
fi
}
# Recover from pack corruption
recover_from_corruption() {
echo "Attempting recovery from pack corruption..."
# Create backup
cp -r .git .git.backup
# Try to recover valid objects
for pack in .git/objects/pack/*.pack; do
echo "Attempting to recover from $(basename "$pack")..."
# Use strict verification to extract valid objects
if git unpack-objects --strict < "$pack" 2>/dev/null; then
echo "✓ Recovered objects from $(basename "$pack")"
else
echo "✗ Could not recover from $(basename "$pack")"
fi
done
# Clean up corrupted packs
rm -f .git/objects/pack/*.pack .git/objects/pack/*.idx
# Rebuild repository
git fsck --full
git gc --aggressive
echo "Recovery attempt complete"
echo "Original repository backed up in .git.backup"
}
Terminal window
# Configure pack verification behavior
git config pack.verifyObjects true # Verify objects during packing
git config transfer.fsckObjects true # Verify objects during transfer
# Configure pack creation
git config pack.window 10 # Delta window size
git config pack.depth 50 # Delta depth
git config pack.compression 6 # Compression level
# Configure pack maintenance
git config gc.auto 670 # Objects before auto-GC
git config gc.autopacklimit 50 # Packs before auto-repack
Terminal window
# Safe pack verification with error handling
safe_verify_pack() {
local pack_idx="$1"
if [ ! -f "$pack_idx" ]; then
echo "Error: Pack index file not found: $pack_idx"
return 1
fi
echo "Verifying pack: $(basename "$pack_idx")"
# Attempt verification
if git verify-pack "$pack_idx" >/dev/null 2>&1; then
echo "✓ Pack file is valid"
return 0
else
echo "✗ Pack file verification failed"
return 1
fi
}
# Batch verification with progress
batch_verify_packs() {
local pack_count
pack_count=$(ls -1 .git/objects/pack/*.idx 2>/dev/null | wc -l)
local current=0
echo "Batch verifying $pack_count pack files..."
for idx in .git/objects/pack/*.idx; do
((current++))
echo -n "[$current/$pack_count] Checking $(basename "$idx")... "
if safe_verify_pack "$idx" >/dev/null 2>&1; then
echo ""
else
echo ""
fi
done
echo "Batch verification complete"
}
# Usage
batch_verify_packs
Terminal window
# Optimize pack verification performance
fast_pack_verification() {
local pack_idx="$1"
echo "Fast verifying pack: $(basename "$pack_idx")"
# Use parallel verification if available
export GIT_VERIFY_PACK_THREADS=$(nproc 2>/dev/null || echo 4)
# Disable unnecessary checks for speed
time git verify-pack --stat-only "$pack_idx" >/dev/null
}
# Memory-efficient verification
memory_efficient_verify() {
local pack_idx="$1"
echo "Memory-efficient pack verification..."
# Reduce memory usage
ulimit -v 1048576 # 1GB limit
# Process in chunks
git verify-pack -v "$pack_idx" | head -1000 | while read -r line; do
# Process objects in batches
echo "$line" >/dev/null
done
echo "Memory-efficient verification complete"
}
#!/bin/bash
# Automated pack file maintenance
automated_pack_maintenance() {
echo "=== Automated Pack File Maintenance ==="
# Daily pack verification
daily_pack_check() {
echo "Performing daily pack verification..."
log_file="/var/log/git-pack-maintenance.log"
{
echo "=== Daily Pack Check $(date) ==="
# Verify all packs
batch_verify_packs
# Check pack efficiency
analyze_pack_health
# Clean up old packs if needed
if [ $(ls .git/objects/pack/*.pack 2>/dev/null | wc -l) -gt 10 ]; then
echo "Consolidating pack files..."
git repack -a -d
fi
echo "Daily pack check complete"
} >> "$log_file" 2>&1
}
# Weekly pack optimization
weekly_pack_optimization() {
echo "Performing weekly pack optimization..."
# Aggressive optimization
git config pack.window 250
git config pack.depth 250
git config pack.compression 9
git repack -a -d --depth=250 --window=250
git gc --aggressive --prune=now
echo "Weekly pack optimization complete"
}
# Setup automated maintenance
setup_automated_maintenance() {
echo "Setting up automated pack maintenance..."
# Daily verification
(crontab -l ; echo "0 2 * * * $(pwd)/automated-pack-maintenance.sh daily") | crontab -
# Weekly optimization (Sundays at 3 AM)
(crontab -l ; echo "0 3 * * 0 $(pwd)/automated-pack-maintenance.sh weekly") | crontab -
echo "Automated maintenance scheduled"
}
# Interactive maintenance
case "${1:-}" in
"daily")
daily_pack_check
;;
"weekly")
weekly_pack_optimization
;;
"setup")
setup_automated_maintenance
;;
*)
echo "Usage: $0 {daily|weekly|setup}"
echo " daily - Daily pack verification"
echo " weekly - Weekly pack optimization"
echo " setup - Setup automated maintenance"
;;
esac
}
# Usage
automated_pack_maintenance "$@"
Terminal window
# Pack verification in CI/CD pipelines
ci_pack_verification() {
echo "=== CI/CD Pack File Verification ==="
# Pre-deployment pack validation
validate_deployment_packs() {
echo "Validating deployment pack files..."
# Find pack files in build artifacts
find build/ -name "*.pack" | while read -r pack_file; do
echo "Validating $pack_file..."
# Verify pack integrity
if git verify-pack --stdin < "$pack_file" >/dev/null 2>&1; then
echo "✓ Pack file valid: $(basename "$pack_file")"
# Get pack statistics
stats=$(git verify-pack --stat-only --stdin < "$pack_file")
echo " Statistics: $stats"
else
echo "✗ Pack file corrupted: $(basename "$pack_file")"
return 1
fi
done
echo "All pack files validated"
}
# Generate pack file report
generate_pack_report() {
echo "Generating pack file report..."
cat > pack-report.md << EOF
# Pack File Analysis Report
Generated: $(date)
Repository: $(basename "$(pwd)")
Build: ${CI_BUILD_ID:-unknown}
## Pack File Statistics
EOF
# Analyze each pack file
find .git/objects/pack/ -name "*.idx" | while read -r idx_file; do
pack_name=$(basename "${idx_file%.idx}")
echo "### Pack: $pack_name" >> pack-report.md
stats=$(git verify-pack --stat-only "$idx_file")
echo "\`\`\`" >> pack-report.md
echo "$stats" >> pack-report.md
echo "\`\`\`" >> pack-report.md
echo "" >> pack-report.md
done
echo "Pack report generated: pack-report.md"
}
# Performance benchmarking
benchmark_pack_operations() {
echo "Benchmarking pack operations..."
# Measure verification time
start_time=$(date +%s.%3N)
git verify-pack .git/objects/pack/*.idx >/dev/null 2>&1
end_time=$(date +%s.%3N)
verify_time=$(echo "$end_time - $start_time" | bc)
echo "Pack verification time: ${verify_time}s"
# Measure pack access time
start_time=$(date +%s.%3N)
git log --oneline -100 >/dev/null 2>&1
end_time=$(date +%s.%3N)
access_time=$(echo "$end_time - $start_time" | bc)
echo "Pack access time (100 commits): ${access_time}s"
}
# Run CI/CD pack operations
validate_deployment_packs
generate_pack_report
benchmark_pack_operations
}
# Usage in CI
ci_pack_verification
Terminal window
# Advanced repository analysis using verify-pack
repository_pack_analysis() {
echo "=== Repository Pack Analysis ==="
# Analyze object distribution
analyze_object_distribution() {
echo "Analyzing object type distribution..."
git verify-pack -v .git/objects/pack/*.idx | awk '
/ blob / {blobs += $3; blob_count++}
/ tree / {trees += $3; tree_count++}
/ commit / {commits += $3; commit_count++}
/ tag / {tags += $3; tag_count++}
END {
total = blobs + trees + commits + tags
print "Object Type Distribution:"
print " Blobs: " blob_count " objects, " blobs " bytes (" int(blobs*100/total) "%)"
print " Trees: " tree_count " objects, " trees " bytes (" int(trees*100/total) "%)"
print " Commits: " commit_count " objects, " commits " bytes (" int(commits*100/total) "%)"
print " Tags: " tag_count " objects, " tags " bytes (" int(tags*100/total) "%)"
print "Total: " (blob_count + tree_count + commit_count + tag_count) " objects, " total " bytes"
}
'
}
# Find duplicate objects
find_duplicate_objects() {
echo "Finding duplicate objects across packs..."
# Extract all object hashes
git verify-pack -v .git/objects/pack/*.idx | cut -d' ' -f1 | sort | uniq -d > duplicates.txt
duplicate_count=$(wc -l < duplicates.txt)
echo "Found $duplicate_count duplicate objects"
if [ "$duplicate_count" -gt 0 ]; then
echo "Duplicate objects:"
head -10 duplicates.txt
echo "..."
# Suggest repack
echo "Consider running: git repack -a -d"
fi
rm -f duplicates.txt
}
# Analyze delta chains
analyze_delta_chains() {
echo "Analyzing delta compression chains..."
max_chain=0
total_chains=0
git verify-pack -v .git/objects/pack/*.idx | while read -r sha type size offset; do
if [[ "$type" == *"delta"* ]]; then
# Count chain length (simplified)
chain_length=1
current_sha="$sha"
# This is a simplified analysis
# Real delta chain analysis is more complex
while [[ "$type" == *"delta"* ]]; do
((chain_length++))
# In practice, you would follow the delta base
done
((total_chains++))
[ "$chain_length" -gt "$max_chain" ] && max_chain="$chain_length"
fi
done
echo "Delta chain analysis:"
echo " Total delta chains: $total_chains"
echo " Maximum chain length: $max_chain"
if [ "$max_chain" -gt 50 ]; then
echo "⚠ Long delta chains detected, consider repacking"
fi
}
# Generate comprehensive report
generate_comprehensive_report() {
echo "Generating comprehensive pack analysis report..."
cat > pack-analysis-report.md << EOF
# Repository Pack Analysis Report
Generated: $(date)
Repository: $(basename "$(pwd)")
## Repository Statistics
- Total Objects: $(git rev-list --all --count)
- Pack Files: $(ls .git/objects/pack/*.pack 2>/dev/null | wc -l)
- Loose Objects: $(find .git/objects -type f | grep -v pack | wc -l)
## Pack File Details
EOF
# Add pack details
for idx in .git/objects/pack/*.idx; do
pack_name=$(basename "${idx%.idx}")
echo "### $pack_name" >> pack-analysis-report.md
echo "\`\`\`" >> pack-analysis-report.md
git verify-pack --stat-only "$idx" >> pack-analysis-report.md
echo "\`\`\`" >> pack-analysis-report.md
echo "" >> pack-analysis-report.md
done
echo "## Recommendations" >> pack-analysis-report.md
# Add recommendations
pack_count=$(ls .git/objects/pack/*.pack 2>/dev/null | wc -l)
if [ "$pack_count" -gt 20 ]; then
echo "- Consider consolidating packs: \`git repack -a -d\`" >> pack-analysis-report.md
fi
loose_count=$(find .git/objects -type f | grep -v pack | wc -l)
if [ "$loose_count" -gt 1000 ]; then
echo "- Consider packing loose objects: \`git gc\`" >> pack-analysis-report.md
fi
echo "Comprehensive report generated: pack-analysis-report.md"
}
# Run all analyses
analyze_object_distribution
echo
find_duplicate_objects
echo
analyze_delta_chains
echo
generate_comprehensive_report
}
# Usage
repository_pack_analysis
Terminal window
# Diagnose pack corruption
diagnose_pack_corruption() {
echo "Diagnosing pack file corruption..."
# Check pack file headers
for pack in .git/objects/pack/*.pack; do
echo "Checking header of $(basename "$pack")..."
# Read first 12 bytes (pack header)
header=$(dd if="$pack" bs=1 count=12 2>/dev/null | od -c)
expected="177 P A C K \0 \0 \0 \2"
if [[ "$header" == *"$expected"* ]]; then
echo "✓ Valid pack header"
else
echo "✗ Invalid pack header"
fi
done
# Check index files
for idx in .git/objects/pack/*.idx; do
echo "Checking index of $(basename "$idx")..."
if git verify-pack "$idx" >/dev/null 2>&1; then
echo "✓ Valid pack index"
else
echo "✗ Invalid pack index"
fi
done
}
# Recover from pack corruption
recover_pack_corruption() {
echo "Attempting to recover from pack corruption..."
# Method 1: Use git fsck to find issues
echo "Running git fsck..."
git fsck --full 2>&1 | grep -E "(missing|corrupt)"
# Method 2: Try to unpack valid objects
echo "Attempting to extract valid objects..."
for pack in .git/objects/pack/*.pack; do
pack_name=$(basename "$pack")
echo "Processing $pack_name..."
# Create backup
cp "$pack" "${pack}.backup"
# Try strict unpacking
if git unpack-objects --strict < "$pack" 2>/dev/null; then
echo "✓ Successfully unpacked some objects from $pack_name"
else
echo "✗ Could not unpack objects from $pack_name"
fi
done
# Method 3: Rebuild from known good state
echo "Rebuilding repository from known good refs..."
git gc --aggressive
git fsck --full
echo "Recovery attempt complete"
}
Terminal window
# Troubleshoot pack performance issues
troubleshoot_pack_performance() {
echo "Troubleshooting pack file performance..."
# Check pack file sizes
echo "Pack file sizes:"
ls -lh .git/objects/pack/*.pack | while read -r line; do
size=$(echo "$line" | awk '{print $5}')
name=$(echo "$line" | awk '{print $9}')
echo " $(basename "$name"): $size"
done
# Check delta chain lengths
echo "Analyzing delta chains..."
long_chains=$(git verify-pack -v .git/objects/pack/*.idx | awk '
/delta/ {count++}
END {print count}
')
echo "Objects in delta chains: $long_chains"
# Check pack window settings
echo "Current pack settings:"
git config --list | grep "^pack\." | while read -r config; do
echo " $config"
done
# Recommendations
pack_count=$(ls .git/objects/pack/*.pack 2>/dev/null | wc -l)
if [ "$pack_count" -gt 10 ]; then
echo "Recommendation: Consolidate packs with 'git repack -a -d'"
fi
if [ "$long_chains" -gt 1000 ]; then
echo "Recommendation: Increase pack.window and repack"
fi
}
# Optimize pack access
optimize_pack_access() {
echo "Optimizing pack file access..."
# Enable pack bitmap indexes
git repack --write-bitmap-index -a -d
# Configure for better performance
git config core.deltaBaseCacheLimit 2g
git config pack.threads 4
git config pack.useBitmaps true
# Warm up object cache
echo "Warming up object cache..."
git log --all --oneline >/dev/null
echo "Pack access optimization complete"
}
Terminal window
# Handle memory issues during verification
handle_memory_issues() {
echo "Handling memory issues during pack verification..."
# Reduce memory usage
git config pack.windowMemory "100m"
git config pack.packSizeLimit "100m"
# Process packs individually
for idx in .git/objects/pack/*.idx; do
echo "Verifying $(basename "$idx") with limited memory..."
# Use ulimit to restrict memory
(ulimit -v 524288; git verify-pack "$idx" >/dev/null 2>&1 && echo "" || echo "")
done
# Reset memory limits
git config --unset pack.windowMemory
git config --unset pack.packSizeLimit
}
# Handle large pack files
handle_large_packs() {
echo "Handling large pack files..."
# Find large packs
find .git/objects/pack/ -name "*.pack" -size +100M | while read -r pack; do
echo "Large pack detected: $(basename "$pack")"
# Consider splitting or optimizing
pack_size=$(stat -f%z "$pack" 2>/dev/null || stat -c%s "$pack")
echo "Size: $((pack_size / 1024 / 1024))MB"
# Suggest optimization
echo "Consider: git repack -a -d --max-pack-size=500m"
done
}
# Batch processing for many packs
batch_pack_processing() {
echo "Batch processing pack files..."
# Process in parallel if possible
max_jobs=$(nproc 2>/dev/null || echo 2)
ls .git/objects/pack/*.idx | xargs -n 1 -P "$max_jobs" -I {} bash -c '
idx="$1"
if git verify-pack "$idx" >/dev/null 2>&1; then
echo "✓ $(basename "$idx")"
else
echo "✗ $(basename "$idx")"
fi
' _ {}
}
# Usage
handle_memory_issues
handle_large_packs
batch_pack_processing
#!/bin/bash
# Enterprise pack file maintenance system
enterprise_pack_maintenance() {
echo "=== Enterprise Pack File Maintenance ==="
# Multi-repository pack analysis
analyze_multi_repo_packs() {
local repos_dir="$1"
echo "Analyzing pack files across repositories..."
find "$repos_dir" -name "*.git" -type d | while read -r repo; do
echo "## Repository: $(basename "${repo%.git}")"
if [ -d "$repo/objects/pack" ]; then
pack_count=$(ls "$repo/objects/pack"/*.pack 2>/dev/null | wc -l)
total_size=$(du -bc "$repo/objects/pack"/*.pack 2>/dev/null | tail -1 | cut -f1)
echo " Pack files: $pack_count"
echo " Total size: $((total_size / 1024 / 1024))MB"
# Check for corruption
find "$repo/objects/pack" -name "*.idx" | while read -r idx; do
if ! git --git-dir="$repo" verify-pack "$idx" >/dev/null 2>&1; then
echo " ⚠ Corrupted pack: $(basename "$idx")"
fi
done
else
echo " No pack files"
fi
echo
done
}
# Automated pack consolidation
consolidate_enterprise_packs() {
local repos_dir="$1"
echo "Consolidating pack files across enterprise repositories..."
find "$repos_dir" -name "*.git" -type d | while read -r repo; do
repo_name=$(basename "${repo%.git}")
echo "Processing $repo_name..."
# Count packs before
packs_before=$(ls "$repo/objects/pack"/*.pack 2>/dev/null | wc -l)
# Consolidate packs
git --git-dir="$repo" repack -a -d >/dev/null 2>&1
# Count packs after
packs_after=$(ls "$repo/objects/pack"/*.pack 2>/dev/null | wc -l)
if [ "$packs_before" != "$packs_after" ]; then
echo " Consolidated: $packs_before$packs_after packs"
fi
done
echo "Enterprise pack consolidation complete"
}
# Generate enterprise pack report
generate_enterprise_report() {
local repos_dir="$1"
local report_file="enterprise-pack-report-$(date +%Y%m%d).md"
echo "Generating enterprise pack report..."
cat > "$report_file" << EOF
# Enterprise Pack File Report
Generated: $(date)
Repositories Directory: $repos_dir
## Summary Statistics
EOF
total_repos=0
total_packs=0
total_size=0
find "$repos_dir" -name "*.git" -type d | while read -r repo; do
((total_repos++))
repo_name=$(basename "${repo%.git}")
if [ -d "$repo/objects/pack" ]; then
pack_count=$(ls "$repo/objects/pack"/*.pack 2>/dev/null | wc -l)
repo_size=$(du -bc "$repo/objects/pack"/*.pack 2>/dev/null | tail -1 | cut -f1 || echo 0)
((total_packs += pack_count))
((total_size += repo_size))
echo "- $repo_name: $pack_count packs, $((repo_size / 1024 / 1024))MB" >> "$report_file"
fi
done
cat >> "$report_file" << EOF
## Overall Statistics
- Total Repositories: $total_repos
- Total Pack Files: $total_packs
- Total Pack Size: $((total_size / 1024 / 1024))MB
- Average Packs per Repo: $((total_packs / total_repos))
- Average Size per Repo: $((total_size / total_repos / 1024 / 1024))MB
## Recommendations
EOF
# Add recommendations
avg_packs=$((total_packs / total_repos))
if [ "$avg_packs" -gt 5 ]; then
echo "- Consider pack consolidation (average $avg_packs packs per repository)" >> "$report_file"
fi
avg_size=$((total_size / total_repos / 1024 / 1024))
if [ "$avg_size" -gt 500 ]; then
echo "- Large repositories detected (average ${avg_size}MB per repository)" >> "$report_file"
fi
echo "Enterprise pack report generated: $report_file"
}
# Interactive enterprise maintenance
echo "Enterprise Pack Maintenance Options:"
echo "1. Analyze multi-repository packs"
echo "2. Consolidate enterprise packs"
echo "3. Generate enterprise report"
read -p "Select option (1-3): " option
case "$option" in
1)
read -p "Repositories directory: " repos_dir
analyze_multi_repo_packs "$repos_dir"
;;
2)
read -p "Repositories directory: " repos_dir
consolidate_enterprise_packs "$repos_dir"
;;
3)
read -p "Repositories directory: " repos_dir
generate_enterprise_report "$repos_dir"
;;
esac
}
enterprise_pack_maintenance
Terminal window
# Forensic pack file analysis
forensic_pack_analysis() {
echo "=== Forensic Pack File Analysis ==="
# Analyze pack creation timeline
analyze_pack_timeline() {
echo "Analyzing pack file creation timeline..."
ls -la .git/objects/pack/ | while read -r line; do
if [[ "$line" == *".pack" ]]; then
# Extract timestamp and filename
timestamp=$(echo "$line" | awk '{print $6, $7, $8}')
filename=$(echo "$line" | awk '{print $9}')
echo "$timestamp - $filename"
fi
done | sort
echo "Timeline analysis complete"
}
# Extract pack metadata
extract_pack_metadata() {
echo "Extracting pack file metadata..."
for idx in .git/objects/pack/*.idx; do
pack_name=$(basename "${idx%.idx}")
echo "Pack: $pack_name"
# Get pack statistics
git verify-pack --stat-only "$idx" | while read -r line; do
echo " $line"
done
# Get creation time
pack_file="${idx%.idx}.pack"
if [ -f "$pack_file" ]; then
created=$(stat -c%y "$pack_file" 2>/dev/null || stat -f%Sm -t "%Y-%m-%d %H:%M:%S" "$pack_file")
echo " Created: $created"
fi
echo
done
}
# Detect pack file anomalies
detect_pack_anomalies() {
echo "Detecting pack file anomalies..."
# Check for unusually large packs
find .git/objects/pack/ -name "*.pack" -size +1G | while read -r pack; do
size=$(stat -f%z "$pack" 2>/dev/null || stat -c%s "$pack")
echo "⚠ Large pack detected: $(basename "$pack") ($((size / 1024 / 1024))MB)"
done
# Check for packs with unusual object counts
for idx in .git/objects/pack/*.idx; do
object_count=$(git verify-pack --stat-only "$idx" | grep "objects" | cut -d' ' -f1)
if [ "$object_count" -gt 100000 ]; then
echo "⚠ Pack with many objects: $(basename "$idx") ($object_count objects)"
elif [ "$object_count" -lt 10 ]; then
echo "⚠ Pack with few objects: $(basename "$idx") ($object_count objects)"
fi
done
# Check for packs created in rapid succession
ls -t .git/objects/pack/*.pack | head -5 | while read -r pack; do
mtime=$(stat -c%Y "$pack" 2>/dev/null || stat -f%Sm -t "%s" "$pack")
current_time=$(date +%s)
age_minutes=$(( (current_time - mtime) / 60 ))
if [ "$age_minutes" -lt 5 ]; then
echo "⚠ Recently created pack: $(basename "$pack") (${age_minutes} minutes ago)"
fi
done
}
# Generate forensic report
generate_forensic_report() {
echo "Generating forensic pack analysis report..."
cat > forensic-pack-report.md << EOF
# Forensic Pack File Analysis Report
Generated: $(date)
Repository: $(basename "$(pwd)")
Analyst: $(whoami)
## Executive Summary
This report contains forensic analysis of Git pack files in the repository.
## Pack File Timeline
EOF
analyze_pack_timeline >> forensic-pack-report.md
echo >> forensic-pack-report.md
echo "## Pack Metadata" >> forensic-pack-report.md
extract_pack_metadata >> forensic-pack-report.md
echo "## Anomalies Detected" >> forensic-pack-report.md
detect_pack_anomalies >> forensic-pack-report.md
echo "## Conclusions" >> forensic-pack-report.md
echo "Forensic analysis complete. Review anomalies above for potential security concerns." >> forensic-pack-report.md
echo "Forensic report generated: forensic-pack-report.md"
}
# Run forensic analysis
analyze_pack_timeline
echo
extract_pack_metadata
echo
detect_pack_anomalies
echo
generate_forensic_report
}
# Usage
forensic_pack_analysis
Terminal window
# Automated backup system with pack verification
automated_pack_backup() {
echo "=== Automated Pack-Based Backup System ==="
# Configuration
BACKUP_ROOT="/srv/backups/git"
RETENTION_DAYS=30
VERIFY_BACKUPS=true
# Create verified pack backup
create_verified_backup() {
local repo_name="$1"
local repo_path="$2"
echo "Creating verified backup for $repo_name..."
backup_dir="$BACKUP_ROOT/$repo_name"
mkdir -p "$backup_dir"
timestamp=$(date +%Y%m%d-%H%M%S)
backup_pack="$backup_dir/backup-$timestamp.pack"
# Create pack file
cd "$repo_path"
git pack-objects "$backup_pack" --all
# Verify pack integrity
if [ "$VERIFY_BACKUPS" = true ]; then
echo "Verifying backup integrity..."
if git verify-pack --stdin < "$backup_pack" >/dev/null 2>&1; then
echo "✓ Backup verification successful"
# Create verification manifest
cat > "${backup_pack}.manifest" << EOF
Repository: $repo_name
Created: $timestamp
Verified: $(date)
SHA256: $(sha256sum "$backup_pack" | cut -d' ' -f1)
Pack Stats: $(git verify-pack --stat-only --stdin < "$backup_pack")
EOF
else
echo "✗ Backup verification failed"
rm -f "$backup_pack"
return 1
fi
fi
# Cleanup old backups
cleanup_old_backups "$backup_dir"
echo "Verified backup created: $backup_pack"
}
# Restore from verified backup
restore_verified_backup() {
local backup_pack="$1"
local restore_path="$2"
echo "Restoring from verified backup..."
# Verify backup integrity before restore
if [ ! -f "${backup_pack}.manifest" ]; then
echo "No verification manifest found"
return 1
fi
# Check manifest
expected_sha=$(grep "SHA256:" "${backup_pack}.manifest" | cut -d' ' -f2)
actual_sha=$(sha256sum "$backup_pack" | cut -d' ' -f1)
if [ "$expected_sha" != "$actual_sha" ]; then
echo "Backup integrity check failed"
return 1
fi
# Restore repository
mkdir -p "$restore_path"
cd "$restore_path"
git init
git unpack-objects < "$backup_pack"
# Restore refs if available
# This would require additional metadata
echo "✓ Verified backup restored successfully"
}
# Cleanup old backups
cleanup_old_backups() {
local backup_dir="$1"
echo "Cleaning up old backups..."
# Remove backups older than retention period
find "$backup_dir" -name "backup-*.pack" -mtime +$RETENTION_DAYS | while read -r old_backup; do
echo "Removing old backup: $(basename "$old_backup")"
rm -f "$old_backup" "${old_backup}.manifest"
done
# Remove empty directories
find "$BACKUP_ROOT" -type d -empty -delete
}
# Monitor backup health
monitor_backup_health() {
echo "Monitoring backup system health..."
total_backups=0
valid_backups=0
total_size=0
find "$BACKUP_ROOT" -name "backup-*.pack" | while read -r backup; do
((total_backups++))
# Check size
size=$(stat -f%z "$backup" 2>/dev/null || stat -c%s "$backup")
((total_size += size))
# Verify integrity
if git verify-pack --stdin < "$backup" >/dev/null 2>&1; then
((valid_backups++))
else
echo "✗ Corrupted backup: $(basename "$backup")"
fi
done
echo "Backup Health Summary:"
echo " Total backups: $total_backups"
echo " Valid backups: $valid_backups"
echo " Total size: $((total_size / 1024 / 1024))MB"
validity_rate=$((valid_backups * 100 / total_backups))
echo " Validity rate: ${validity_rate}%"
if [ "$validity_rate" -lt 95 ]; then
echo "⚠ Low backup validity rate detected"
fi
}
# Interactive backup management
echo "Automated Pack Backup System Options:"
echo "1. Create verified backup"
echo "2. Restore from verified backup"
echo "3. Monitor backup health"
read -p "Select option (1-3): " option
case "$option" in
1)
read -p "Repository name: " repo_name
read -p "Repository path: " repo_path
create_verified_backup "$repo_name" "$repo_path"
;;
2)
read -p "Backup pack file: " backup_pack
read -p "Restore path: " restore_path
restore_verified_backup "$backup_pack" "$restore_path"
;;
3) monitor_backup_health ;;
esac
}
# Usage
automated_pack_backup