send-pack Git Command Guide
The git send-pack command is a low-level Git command that pushes objects and references from a local repository to a remote repository. It implements the client side of the Git push protocol, handling the negotiation and transfer of Git objects between repositories.
git send-pack Syntax:
Section titled “git send-pack Syntax:”git send-pack [--dry-run] [--force] [--verbose] [--thin] [--no-progress] [--all] [--mirror] [--atomic] [--signed | --no-signed] [--receive-pack=<git-receive-pack>] [--negotiate-only] [--deepen=<depth>] [--shallow-since=<time>] [--update-shallow] [<host>:]<directory> [<ref>...]Push Control Options:
Section titled “Push Control Options:”| Option | Description |
|---|---|
--dry-run | Show what would be pushed without pushing |
--force | Force update of remote refs |
--verbose, -v | Verbose output |
--quiet, -q | Suppress output |
--progress | Show progress (default) |
--no-progress | Don’t show progress |
Reference Control Options:
Section titled “Reference Control Options:”| Option | Description |
|---|---|
--all | Push all refs |
--mirror | Mirror all refs |
--atomic | Use atomic transactions |
--signed | GPG-sign the push |
--no-signed | Don’t GPG-sign the push |
--thin | Use thin pack |
--no-thin | Don’t use thin pack |
Negotiation Options:
Section titled “Negotiation Options:”| Option | Description |
|---|---|
--negotiate-only | Only negotiate, don’t send |
--deepen=<depth> | Deepen shallow repository |
--shallow-since=<time> | Shallow since time |
--update-shallow | Update shallow refs |
Advanced Options:
Section titled “Advanced Options:”| Option | Description |
|---|---|
--receive-pack=<cmd> | Receive pack command |
--exec=<cmd> | Execute command on remote |
--remote=<remote> | Specify remote name |
--push-option=<opt> | Pass push option to receiver |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<host>:<directory> | Remote repository location |
<ref> | References to push |
Understanding Send-Pack Operations:
Section titled “Understanding Send-Pack Operations:”Push Protocol Flow:
Section titled “Push Protocol Flow:”Git Push Protocol (send-pack):├── Discovery: List remote refs├── Negotiation: Find common objects├── Compression: Create pack file├── Transfer: Send pack to remote├── Update: Update remote refs└── Verification: Confirm successPack File Creation:
Section titled “Pack File Creation:”Pack File Generation:├── Object Discovery: Find objects to send├── Delta Compression: Create efficient deltas├── Pack Creation: Bundle objects into pack├── Index Creation: Create pack index└── Transfer: Send pack + index to remoteReference Updates:
Section titled “Reference Updates:”Reference Update Process:├── Pre-receive: Server validation hooks├── Update: Atomic ref updates├── Post-receive: Notification hooks└── Cleanup: Remove temporary filesBasic Send-Pack Operations:
Section titled “Basic Send-Pack Operations:”Direct Repository Push:
Section titled “Direct Repository Push:”# Push to remote repositorygit send-pack origin main
# Push multiple branchesgit send-pack origin main develop feature-x
# Push all branchesgit send-pack --all origin
# Mirror repositorygit send-pack --mirror originDry Run Operations:
Section titled “Dry Run Operations:”# Show what would be pushedgit send-pack --dry-run origin main
# Verbose dry rungit send-pack --dry-run --verbose origin
# Check remote capabilitiesgit send-pack --negotiate-only originForce Operations:
Section titled “Force Operations:”# Force push branchgit send-pack --force origin main
# Force push with atomic transactiongit send-pack --force --atomic origin main develop
# Force mirror pushgit send-pack --force --mirror originAdvanced Send-Pack Scenarios:
Section titled “Advanced Send-Pack Scenarios:”Custom Remote Operations:
Section titled “Custom Remote Operations:”# Use custom receive-pack commandgit send-pack --receive-pack=/usr/local/bin/git-receive-pack origin
# Push to non-standard remotegit send-pack user@host:/path/to/repo.git main
# Push over SSH with custom portgit send-pack ssh://user@host:2222/path/to/repo.git mainThin Pack Operations:
Section titled “Thin Pack Operations:”# Use thin pack for efficiencygit send-pack --thin origin main
# Force thin packgit send-pack --no-thin origin main
# Thin pack with progressgit send-pack --thin --progress originSigned Push Operations:
Section titled “Signed Push Operations:”# GPG sign the pushgit send-pack --signed origin main
# Don't sign pushgit send-pack --no-signed origin main
# Sign with specific keyGIT_COMMITTER_KEY=ABC123 git send-pack --signed origin mainShallow Repository Operations:
Section titled “Shallow Repository Operations:”# Push to shallow remotegit send-pack --update-shallow origin main
# Deepen remote shallow repogit send-pack --deepen=10 origin
# Push since specific timegit send-pack --shallow-since="1 week ago" originConfiguration and Best Practices:
Section titled “Configuration and Best Practices:”Git Configuration for Send-Pack:
Section titled “Git Configuration for Send-Pack:”# Configure send-pack behaviorgit config sendpack.verbose true # Verbose output by defaultgit config sendpack.thin true # Use thin packs by defaultgit config sendpack.atomic true # Use atomic pushes
# Configure remote operationsgit config remote.origin.receivepack /usr/local/bin/git-receive-packgit config remote.origin.push refs/heads/*:refs/heads/*
# Configure signinggit config push.gpgSign true # Sign all pushesgit config user.signingkey ABC123 # Default GPG keySend-Pack Best Practices:
Section titled “Send-Pack Best Practices:”# Use dry-run firstgit send-pack --dry-run origin main
# Use atomic for multi-branch pushesgit send-pack --atomic origin main develop
# Use thin packs for efficiencygit send-pack --thin origin
# Sign important pushesgit send-pack --signed origin mainSafe Send-Pack Operations:
Section titled “Safe Send-Pack Operations:”# Backup before force operationsgit branch backup-before-force
# Verify remote stategit ls-remote origin
# Check connectivityssh user@host git --version
# Validate local repositorygit fsckIntegration with Development Workflows:
Section titled “Integration with Development Workflows:”Custom Push Scripts:
Section titled “Custom Push Scripts:”#!/bin/bash# Custom push workflow with send-pack
smart_push() { local remote="$1" local branch="$2"
echo "Smart push to $remote/$branch"
# Check if branch exists if ! git show-ref --verify --quiet "refs/heads/$branch"; then echo "Branch $branch does not exist" return 1 fi
# Check remote connectivity if ! git ls-remote "$remote" >/dev/null 2>&1; then echo "Cannot connect to remote $remote" return 1 fi
# Dry run first echo "Dry run results:" git send-pack --dry-run "$remote" "$branch"
# Confirm push read -p "Proceed with push? (y/N): " confirm if [[ "$confirm" != "y" ]]; then echo "Push cancelled" return 0 fi
# Execute push if git send-pack --verbose "$remote" "$branch"; then echo "✓ Push successful" else echo "✗ Push failed" return 1 fi}
smart_push "origin" "main"Automated Deployment:
Section titled “Automated Deployment:”# Automated deployment with send-packdeploy_to_production() { local prod_remote="$1" local release_tag="$2"
echo "Deploying $release_tag to production"
# Validate tag if ! git show-ref --verify --quiet "refs/tags/$release_tag"; then echo "Tag $release_tag does not exist" return 1 fi
# Pre-deployment checks if ! run_pre_deploy_checks; then echo "Pre-deployment checks failed" return 1 fi
# Push to production if git send-pack --atomic "$prod_remote" "$release_tag"; then echo "✓ Deployment successful"
# Update production ref git send-pack "$prod_remote" "$release_tag:refs/heads/production"
# Post-deployment tasks run_post_deploy_tasks "$release_tag"
else echo "✗ Deployment failed" return 1 fi}
deploy_to_production "prod-server:/var/git/app.git" "v2.1.0"Repository Mirroring:
Section titled “Repository Mirroring:”# Repository mirroring with send-packmirror_repository() { local source_repo="$1" local mirror_repo="$2"
echo "Mirroring $source_repo to $mirror_repo"
# Full mirror push if git send-pack --mirror "$mirror_repo"; then echo "✓ Repository mirrored successfully"
# Verify mirror mirror_refs=$(git ls-remote "$mirror_repo" | wc -l) local_refs=$(git show-ref | wc -l)
if [ "$mirror_refs" -eq "$local_refs" ]; then echo "✓ Mirror verification passed" else echo "⚠ Mirror verification failed: $mirror_refs vs $local_refs refs" fi
else echo "✗ Mirroring failed" return 1 fi}
mirror_repository "." "mirror-server:/var/git/mirror.git"Troubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Connection Issues:
Section titled “Connection Issues:”# Test remote connectionssh user@host git --version
# Check remote repository accessgit ls-remote remote-url
# Verify SSH keysssh -T user@host
# Test with verbose outputgit send-pack --verbose remote-url mainPermission Issues:
Section titled “Permission Issues:”# Check remote permissionsssh user@host ls -la /path/to/repo.git
# Verify git user accessssh user@host whoami
# Check repository ownershipssh user@host stat /path/to/repo.git
# Fix permissionsssh user@host chmod -R g+w /path/to/repo.gitReference Issues:
Section titled “Reference Issues:”# Check remote refsgit ls-remote origin
# Verify local refsgit show-ref
# Check for conflicting refsgit show-ref | grep refs/heads/maingit ls-remote origin | grep refs/heads/main
# Force update if neededgit send-pack --force origin mainPack File Issues:
Section titled “Pack File Issues:”# Check pack file integritygit verify-pack .git/objects/pack/*.pack
# Repack repositorygit repack -a -d
# Check for corrupted objectsgit fsck --full
# Clean up unreachable objectsgit gc --prune=nowMemory Issues:
Section titled “Memory Issues:”# Reduce memory usagegit config pack.windowMemory "100m"git config pack.packSizeLimit "100m"
# Use shallow operationsgit send-pack --depth=1 remote-url
# Split large pushesgit send-pack remote-url maingit send-pack remote-url developReal-World Usage Examples:
Section titled “Real-World Usage Examples:”Custom Push Automation:
Section titled “Custom Push Automation:”#!/bin/bash# Advanced push automation with send-pack
automated_push_workflow() { local remote="$1" local branches="${2:-main}" local options="${3:---atomic}"
echo "=== Automated Push Workflow ===" echo "Remote: $remote" echo "Branches: $branches" echo "Options: $options"
# Pre-push validation echo "Running pre-push validation..."
# Check repository cleanliness if ! git diff --quiet || ! git diff --cached --quiet; then echo "✗ Repository has uncommitted changes" echo "Commit or stash changes before pushing" return 1 fi
# Check remote connectivity if ! timeout 10 git ls-remote "$remote" >/dev/null 2>&1; then echo "✗ Cannot connect to remote $remote" return 1 fi
# Validate branches exist for branch in $branches; do if ! git show-ref --verify --quiet "refs/heads/$branch"; then echo "✗ Branch $branch does not exist locally" return 1 fi done
echo "✓ Pre-push validation passed"
# Execute push echo "Executing push..." if eval "git send-pack $options '$remote' $branches"; then echo "✓ Push successful"
# Post-push operations echo "Running post-push operations..."
# Update tracking branches for branch in $branches; do git branch --set-upstream-to="$remote/$branch" "$branch" 2>/dev/null done
# Notify team (if configured) if command -v notify_team >/dev/null 2>&1; then notify_team "Push completed: $branches to $remote" fi
# Run post-push hooks if [ -f .git/hooks/post-push ]; then .git/hooks/post-push "$remote" "$branches" fi
else echo "✗ Push failed"
# Diagnostic information echo "Diagnostic information:" echo "- Remote refs:" git ls-remote "$remote" 2>/dev/null | head -5
echo "- Local refs:" for branch in $branches; do git show-ref "refs/heads/$branch" 2>/dev/null done
return 1 fi}
# Usage examplesautomated_push_workflow "origin" "main develop" "--atomic --signed"automated_push_workflow "upstream" "feature-x" "--force"CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# CI/CD pipeline with send-packci_push_pipeline() { echo "=== CI/CD Push Pipeline ==="
# Environment variables CI_COMMIT_REF="${CI_COMMIT_REF:-main}" CI_REMOTE_URL="${CI_REMOTE_URL:-origin}"
# Determine push strategy case "$CI_JOB_TYPE" in "deploy") # Production deployment echo "Production deployment push"
# Additional validation for production if ! run_security_checks; then echo "Security checks failed" exit 1 fi
if ! run_performance_tests; then echo "Performance tests failed" exit 1 fi
# Signed push to production git send-pack --signed --atomic "$CI_REMOTE_URL" "$CI_COMMIT_REF"
# Update production ref git send-pack "$CI_REMOTE_URL" "$CI_COMMIT_REF:refs/heads/production" ;;
"staging") # Staging deployment echo "Staging deployment push"
git send-pack --atomic "$CI_REMOTE_URL" "$CI_COMMIT_REF" git send-pack "$CI_REMOTE_URL" "$CI_COMMIT_REF:refs/heads/staging" ;;
"feature") # Feature branch push echo "Feature branch push"
# Check if feature is approved if ! is_feature_approved "$CI_COMMIT_REF"; then echo "Feature not approved for push" exit 1 fi
git send-pack "$CI_REMOTE_URL" "$CI_COMMIT_REF" ;;
*) # Standard push echo "Standard push" git send-pack --quiet "$CI_REMOTE_URL" "$CI_COMMIT_REF" ;; esac
# Post-push validation if git ls-remote "$CI_REMOTE_URL" | grep -q "$CI_COMMIT_REF"; then echo "✓ Push validation successful" else echo "✗ Push validation failed" exit 1 fi}
ci_push_pipelineRepository Synchronization:
Section titled “Repository Synchronization:”# Repository synchronization with send-packsync_repositories() { local source_repo="$1" local target_repo="$2" local sync_branches="${3:-main}"
echo "=== Repository Synchronization ===" echo "Source: $source_repo" echo "Target: $target_repo" echo "Branches: $sync_branches"
# Change to source repository cd "$source_repo" || { echo "Cannot access source repository: $source_repo" return 1 }
# Fetch latest changes git fetch --all --prune
# Synchronize each branch for branch in $sync_branches; do echo "Synchronizing branch: $branch"
# Check if branch exists in source if ! git show-ref --verify --quiet "refs/heads/$branch"; then echo "Branch $branch does not exist in source" continue fi
# Push to target if git send-pack --verbose "$target_repo" "$branch"; then echo "✓ Branch $branch synchronized"
# Update target branch ref if needed git send-pack "$target_repo" "$branch:refs/heads/$branch"
else echo "✗ Failed to synchronize branch $branch" return 1 fi done
# Synchronize tags echo "Synchronizing tags..." git send-pack --tags "$target_repo"
# Verify synchronization echo "Verifying synchronization..." source_refs=$(git show-ref | wc -l) target_refs=$(git ls-remote "$target_repo" 2>/dev/null | wc -l)
if [ "$source_refs" -eq "$target_refs" ]; then echo "✓ Synchronization verified" else echo "⚠ Reference count mismatch: $source_refs vs $target_refs" fi
echo "Repository synchronization complete"}
sync_repositories "/path/to/source" "/path/to/target" "main develop"Disaster Recovery:
Section titled “Disaster Recovery:”# Disaster recovery with send-packdisaster_recovery() { local backup_repo="$1" local primary_repo="${2:-origin}"
echo "=== Disaster Recovery ===" echo "Backup: $backup_repo" echo "Primary: $primary_repo"
# Assess damage echo "Assessing repository damage..."
if git fsck --full >/dev/null 2>&1; then echo "✓ Primary repository is healthy" return 0 else echo "✗ Primary repository has issues" fi
# Attempt recovery from backup echo "Attempting recovery from backup..."
# Get list of recoverable refs backup_refs=$(git ls-remote "$backup_repo" 2>/dev/null | awk '{print $2}' | grep -E '^refs/(heads|tags)/')
if [ -z "$backup_refs" ]; then echo "No recoverable refs in backup" return 1 fi
# Recover refs one by one recovered=0 for ref in $backup_refs; do echo "Recovering $ref..."
# Create recovery branch/tag if git send-pack "$primary_repo" "$ref:$ref.recovery"; then echo "✓ Recovered $ref as $ref.recovery" ((recovered++)) else echo "✗ Failed to recover $ref" fi done
if [ "$recovered" -gt 0 ]; then echo "✓ Recovered $recovered refs" echo "Manual review and cleanup required" echo "Use: git branch -m <ref.recovery> <ref> # to restore" else echo "✗ No refs could be recovered" return 1 fi}
disaster_recovery "backup-server:/var/git/backup.git"What’s the difference between git send-pack and git push?
Section titled “What’s the difference between git send-pack and git push?”git push is high-level and user-friendly; git send-pack is low-level implementation. push calls send-pack internally with additional features.
How do I push to a remote repository using send-pack?
Section titled “How do I push to a remote repository using send-pack?”git send-pack
Can send-pack work with SSH?
Section titled “Can send-pack work with SSH?”Yes, use SSH URLs: git send-pack user@host:/path/to/repo.git branch
What’s the —atomic option for?
Section titled “What’s the —atomic option for?”—atomic ensures all ref updates succeed or all fail together, preventing partial pushes.
How do I force push with send-pack?
Section titled “How do I force push with send-pack?”Use —force option: git send-pack —force remote branch
Can send-pack push multiple branches?
Section titled “Can send-pack push multiple branches?”Yes, list multiple branches: git send-pack remote branch1 branch2 branch3
What’s the —mirror option for?
Section titled “What’s the —mirror option for?”—mirror pushes all refs and sets up mirror configuration for complete repository duplication.
How do I see what send-pack would push?
Section titled “How do I see what send-pack would push?”Use —dry-run: git send-pack —dry-run remote branch
Can send-pack work with HTTP remotes?
Section titled “Can send-pack work with HTTP remotes?”Yes, but requires HTTP server with Git support configured.
What’s the —thin option for?
Section titled “What’s the —thin option for?”—thin creates thin packs that reference objects from remote, reducing transfer size.
How do I debug send-pack issues?
Section titled “How do I debug send-pack issues?”Use —verbose and check SSH/git server logs for connection issues.
Can send-pack work with partial clones?
Section titled “Can send-pack work with partial clones?”Yes, but may need —update-shallow for shallow repository operations.
What’s the performance impact of send-pack?
Section titled “What’s the performance impact of send-pack?”Generally fast, but large pushes may take time. Use —progress to monitor.
Can send-pack work with Git LFS?
Section titled “Can send-pack work with Git LFS?”Basic send-pack works, but LFS objects need separate handling by LFS client.
How do I handle send-pack authentication?
Section titled “How do I handle send-pack authentication?”Configure SSH keys or credentials. For HTTP, use credential helpers.
Applications of the git send-pack command
Section titled “Applications of the git send-pack command”- Low-level Pushing: Direct object and reference pushing to remotes
- Automation Scripts: Custom push workflows and deployment automation
- Repository Mirroring: Complete repository duplication and backup
- CI/CD Integration: Automated deployment and synchronization
- Disaster Recovery: Repository restoration from backups
- Custom Protocols: Implementation of specialized push workflows
- Performance Optimization: Efficient object transfer and delta compression
- Security Controls: Signed pushes and access-controlled operations