upload-pack Git Command Guide
The git upload-pack command serves Git repository data to clients during clone and fetch operations. It implements the server-side of Git’s network protocol, sending objects and references to support distributed version control operations across networks.
git upload-pack Syntax:
Section titled “git upload-pack Syntax:”git upload-pack [--strict] [--timeout=<n>] <directory>Options:
Section titled “Options:”| Option | Description |
|---|---|
--strict | Do not try |
--timeout=<n> | Interrupt transfer after |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<directory> | Repository directory to serve |
Understanding Upload-Pack Operations:
Section titled “Understanding Upload-Pack Operations:”Git Network Protocol:
Section titled “Git Network Protocol:”Git Network Protocol Flow:├── Client: git fetch/clone request├── Server: git upload-pack execution├── Negotiation: Reference discovery and want/have exchange├── Pack Generation: Create optimal pack file for client needs├── Transfer: Send pack file with progress reporting└── Completion: Update client referencesPack File Generation:
Section titled “Pack File Generation:”Pack File Creation Process:├── Reference Analysis: Determine required commits├── Object Graph Traversal: Find all reachable objects├── Delta Compression: Create efficient object deltas├── Pack Optimization: Arrange objects for best compression├── Index Generation: Create pack index for random access└── Transfer Preparation: Optimize for network transferClient-Server Negotiation:
Section titled “Client-Server Negotiation:”Reference Discovery and Negotiation:├── Client sends: git-upload-pack /repo.git├── Server responds: Reference advertisements├── Client sends: want/have lines (object requests)├── Server responds: NAK/ACK (acknowledgment)├── Pack generation: Based on negotiated objects└── Transfer: Optimized pack file to clientBasic Upload-Pack Operations:
Section titled “Basic Upload-Pack Operations:”Server Setup for Git Protocol:
Section titled “Server Setup for Git Protocol:”# Setup Git daemon for upload-pack servinggit daemon --base-path=/srv/git --export-all --enable=upload-archive
# Configure SSH access for upload-pack# In ~/.ssh/authorized_keys:command="git-upload-pack '/srv/git/myrepo.git'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@client
# Setup HTTP access with git-http-backendcat > /etc/apache2/sites-available/git-upload.conf << 'EOF'<VirtualHost *:80> ServerName git.example.com DocumentRoot /var/www/git
SetEnv GIT_PROJECT_ROOT /var/www/git SetEnv GIT_HTTP_EXPORT_ALL
<Directory /var/www/git> Options +ExecCGI AddHandler cgi-script .cgi
RewriteEngine On RewriteCond %{REQUEST_URI} ^/git/(.*/git-upload-pack)$ RewriteRule ^/git/(.*)$ /usr/lib/git-core/git-http-backend [L] </Directory></VirtualHost>EOFClient Fetch Operations:
Section titled “Client Fetch Operations:”# Standard fetch operationgit fetch origin
# Fetch with upload-packgit fetch --upload-pack=git-upload-pack origin
# Shallow fetchgit fetch --depth=1 origin
# Fetch specific branchgit fetch origin feature-branchRepository Synchronization:
Section titled “Repository Synchronization:”# Sync with remote repositorygit remote update
# Fetch all branchesgit fetch --all
# Fetch with progressGIT_TRACE=1 git fetch origin
# Fetch with custom upload-packgit fetch --upload-pack="/usr/bin/git-upload-pack" originAdvanced Upload-Pack Scenarios:
Section titled “Advanced Upload-Pack Scenarios:”Custom Protocol Extensions:
Section titled “Custom Protocol Extensions:”# Setup protocol extensionssetup_protocol_extensions() { echo "Setting up Git protocol extensions..."
# Enable protocol v2 git config protocol.version 2
# Configure extension support git config uploadpack.allowFilter true git config uploadpack.allowRefInWant true
# Setup custom capabilities cat > .git/config << EOF[uploadpack] allowFilter = true allowRefInWant = true allowSidebandAll = trueEOF
echo "Protocol extensions configured"}
# Usagesetup_protocol_extensionsLarge Repository Optimization:
Section titled “Large Repository Optimization:”# Optimize upload-pack for large repositoriesoptimize_large_repo() { echo "Optimizing upload-pack for large repository..."
# Configure pack generation git config pack.window 250 git config pack.depth 250 git config pack.compression 9
# Enable parallel processing git config pack.threads 4
# Configure bitmap indexes for fast object lookup git repack --write-bitmap-index -a -d
# Setup alternates for shared object storage echo "/shared/objects" >> .git/objects/info/alternates
# Configure upload-pack timeouts git config uploadpack.keepAlive 300 git config uploadpack.timeout 3600
echo "Large repository optimization complete"}
# Usageoptimize_large_repoAccess Control and Security:
Section titled “Access Control and Security:”# Implement access control for upload-packsetup_access_control() { echo "Setting up upload-pack access control..."
# Create access control script cat > /usr/local/bin/git-access-control << 'EOF'#!/bin/bash# Control access to git upload-pack
REPO="$1"USER="$2"OPERATION="$3"
# Allow read access to specific userscase "$USER" in alice|bob|charlie) if [ "$OPERATION" = "read" ]; then exit 0 # Allow read fi ;; admin) exit 0 # Allow all operations ;; *) echo "Access denied for user: $USER" exit 1 # Deny ;;esacEOF
chmod +x /usr/local/bin/git-access-control
# Configure git to use access control export GIT_ACCESS_CONTROL=/usr/local/bin/git-access-control
echo "Access control configured"}
# Usagesetup_access_controlConfiguration and Best Practices:
Section titled “Configuration and Best Practices:”Git Configuration for Upload-Pack:
Section titled “Git Configuration for Upload-Pack:”# Configure upload-pack behaviorgit config uploadpack.allowFilter true # Allow partial clonesgit config uploadpack.allowRefInWant true # Allow ref-in-wantgit config uploadpack.allowSidebandAll true # Allow sideband allgit config uploadpack.keepAlive 60 # Keep-alive intervalgit config uploadpack.timeout 3600 # Transfer timeout
# Configure pack generationgit config pack.window 10 # Delta window sizegit config pack.depth 50 # Delta depth limitgit config pack.compression 6 # Compression level
# Configure protocolgit config protocol.version 2 # Use protocol v2git config protocol.allow always # Protocol allowancesServer Configuration Best Practices:
Section titled “Server Configuration Best Practices:”# Apache configuration for Git HTTPcat > /etc/apache2/sites-available/git-http.conf << 'EOF'<VirtualHost *:80> ServerName git.company.com DocumentRoot /var/www/git
# Security headers Header always set X-Frame-Options DENY Header always set X-Content-Type-Options nosniff Header always set X-XSS-Protection "1; mode=block"
# Git configuration SetEnv GIT_PROJECT_ROOT /var/www/git SetEnv GIT_HTTP_EXPORT_ALL SetEnv GIT_HTTP_MAX_REQUEST_BUFFER 100M
<Directory /var/www/git> Options +ExecCGI +FollowSymLinks AddHandler cgi-script .cgi DirectoryIndex gitweb.cgi
# Upload-pack endpoint RewriteEngine On RewriteCond %{REQUEST_URI} ^/git/(.*/git-upload-pack)$ RewriteRule ^/git/(.*)$ /usr/lib/git-core/git-http-backend [L]
# Access control Require all granted </Directory>
# SSL configuration (recommended) SSLEngine on SSLCertificateFile /etc/ssl/certs/git.crt SSLCertificateKeyFile /etc/ssl/private/git.key</VirtualHost>EOF
# Nginx configurationcat > /etc/nginx/sites-available/git-upload << 'EOF'server { listen 80; server_name git.company.com;
root /var/www/git; index index.html;
# Git HTTP backend location ~ /git/(.*/git-upload-pack)$ { fastcgi_pass unix:/var/run/fcgiwrap.socket; fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; fastcgi_param GIT_PROJECT_ROOT /var/www/git; fastcgi_param GIT_HTTP_EXPORT_ALL 1; fastcgi_param REMOTE_USER $remote_user; include fastcgi_params; }
# Static file serving location / { try_files $uri $uri/ =404; }}EOFClient Configuration:
Section titled “Client Configuration:”# Configure client for upload-pack operationsgit config http.postBuffer 524288000 # 500MB buffergit config http.lowSpeedLimit 1000 # 1KB/s minimum speedgit config http.lowSpeedTime 300 # 5 minute timeout
# Configure fetch behaviorgit config fetch.prune true # Prune deleted branchesgit config fetch.pruneTags true # Prune deleted tags
# Configure protocol preferencesgit config protocol.version 2 # Use protocol v2git config protocol.allow always # Allow all protocolsSecurity Best Practices:
Section titled “Security Best Practices:”# Secure upload-pack deploymentsecure_upload_pack() { echo "Setting up secure upload-pack access..."
# Create dedicated git user useradd -r -s /bin/bash -m -d /home/git-upload git-upload
# Setup SSH with restricted commands mkdir -p /home/git-upload/.ssh cat > /home/git-upload/.ssh/authorized_keys << EOFcommand="git-upload-pack '/srv/git/myrepo.git'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@clientEOF
# Set proper permissions chown -R git-upload:git-upload /home/git-upload/.ssh chmod 700 /home/git-upload/.ssh chmod 600 /home/git-upload/.ssh/authorized_keys
# Setup repositories mkdir -p /srv/git chown git-upload:git-upload /srv/git
echo "Secure upload-pack setup complete"}
# Access validation scriptcat > /usr/local/bin/validate-git-access << 'EOF'#!/bin/bash# Validate Git upload-pack access
USER="$1"REPO="$2"
# Log accessecho "$(date): $USER accessed $REPO via upload-pack" >> /var/log/git-upload/access.log
# Check permissionsif [ "$USER" = "admin" ] || groups "$USER" | grep -q "developers"; then exec git-upload-pack "$REPO"else echo "Access denied" exit 1fiEOF
chmod +x /usr/local/bin/validate-git-accessIntegration with Development Workflows:
Section titled “Integration with Development Workflows:”CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# Upload-pack in CI/CD pipelinesci_upload_pack_integration() { echo "=== CI/CD Upload-Pack Integration ==="
# Setup repository for CI access setup_ci_repository() { echo "Setting up repository for CI access..."
# Create CI access token CI_TOKEN=$(openssl rand -hex 32)
# Configure repository for CI git config receive.denyDeletes false git config receive.denyDeleteCurrent false
# Setup CI remote git remote add ci "https://ci-user:$CI_TOKEN@git.company.com/repo.git"
echo "CI repository setup complete" }
# Automated testing with upload-pack automated_testing() { echo "Running automated testing with upload-pack..."
# Fetch latest changes git fetch --all
# Run tests on multiple branches for branch in $(git branch -r | grep -v HEAD); do echo "Testing branch: $branch" git checkout "$branch" run_tests || echo "Tests failed on $branch" done
# Return to original branch git checkout - }
# Deployment with upload-pack deploy_with_upload_pack() { local environment="$1"
echo "Deploying to $environment environment..."
# Fetch deployment branch git fetch origin "deployment/$environment"
# Deploy to environment deploy_to_environment "$environment" }
# Run CI/CD steps setup_ci_repository automated_testing deploy_with_upload_pack "production"}
# Usage in CIci_upload_pack_integrationRepository Mirroring:
Section titled “Repository Mirroring:”# Repository mirroring with upload-packsetup_repository_mirror() { local source_repo="$1" local mirror_path="$2"
echo "Setting up repository mirror..."
# Clone as mirror git clone --mirror "$source_repo" "$mirror_path" cd "$mirror_path"
# Configure for serving git config uploadpack.allowFilter true git config uploadpack.allowRefInWant true
# Setup automatic sync cat > sync-mirror.sh << 'EOF'#!/bin/bash# Sync mirror with source
cd "$(dirname "$0")"git fetch --allgit update-server-info
echo "Mirror synced at $(date)"EOF
chmod +x sync-mirror.sh
# Setup cron for regular sync (crontab -l ; echo "*/30 * * * * $(pwd)/sync-mirror.sh") | crontab -
echo "Repository mirror setup complete"}
# Usagesetup_repository_mirror "https://github.com/user/repo.git" "/srv/mirror/repo.git"Multi-Protocol Support:
Section titled “Multi-Protocol Support:”# Support multiple protocols with upload-packsetup_multi_protocol() { echo "Setting up multi-protocol Git access..."
# Configure for SSH access git config uploadpack.allowFilter true
# Configure for HTTP access cat > /etc/apache2/conf-available/git-multi.conf << 'EOF'# Multi-protocol Git configurationSetEnv GIT_PROJECT_ROOT /var/www/gitSetEnv GIT_HTTP_EXPORT_ALL
# Protocol detectionRewriteEngine OnRewriteCond %{REQUEST_URI} ^/git/(.*/git-upload-pack)$RewriteRule ^/git/(.*)$ /usr/lib/git-core/git-http-backend [L]EOF
# Enable configuration a2enconf git-multi systemctl reload apache2
# Setup SSH access cat >> /home/git/.ssh/authorized_keys << EOFcommand="git-upload-pack '/srv/git/myrepo.git'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@clientEOF
echo "Multi-protocol support configured"}
# Usagesetup_multi_protocolTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Protocol Negotiation Issues:
Section titled “Protocol Negotiation Issues:”# Diagnose protocol negotiation problemsdiagnose_protocol_issues() { echo "Diagnosing Git protocol issues..."
# Test basic connectivity if git ls-remote "$repo_url" >/dev/null 2>&1; then echo "✓ Basic connectivity works" else echo "✗ Cannot connect to repository" return 1 fi
# Test protocol version GIT_TRACE=1 git fetch --dry-run 2>&1 | grep "protocol"
# Check upload-pack availability ssh -T git@server "git-upload-pack '/repo.git'" </dev/null >/dev/null 2>&1 && \ echo "✓ SSH upload-pack works" || \ echo "✗ SSH upload-pack failed"
# Test HTTP upload-pack curl -s "http://server/git/repo.git/git-upload-pack" >/dev/null && \ echo "✓ HTTP upload-pack works" || \ echo "✗ HTTP upload-pack failed"}
# Usagediagnose_protocol_issuesPerformance Issues:
Section titled “Performance Issues:”# Troubleshoot upload-pack performanceoptimize_upload_pack_performance() { echo "Optimizing upload-pack performance..."
# Check current configuration git config --list | grep -E "(pack|uploadpack|protocol)"
# Optimize pack generation git config pack.window 250 git config pack.depth 250 git config pack.threads 4
# Enable bitmap indexes git repack --write-bitmap-index -a -d
# Configure timeouts git config uploadpack.keepAlive 300 git config uploadpack.timeout 3600
# Test performance time git fetch --dry-run
echo "Performance optimization complete"}
# Monitor transfer performancemonitor_transfer_performance() { echo "Monitoring transfer performance..."
# Enable verbose logging GIT_TRACE=1 git fetch 2>&1 | grep -E "(pack|object|time)"
# Check pack file statistics ls -lh .git/objects/pack/*.pack
# Monitor system resources iostat -x 1 5 free -h
echo "Performance monitoring complete"}Access Control Issues:
Section titled “Access Control Issues:”# Fix access control problemsfix_access_control() { echo "Fixing access control issues..."
# Check SSH configuration ssh -T git@server 2>&1 | grep -i "welcome"
# Test repository access git ls-remote "git@server:repo.git" >/dev/null 2>&1 && \ echo "✓ SSH access works" || \ echo "✗ SSH access failed"
# Check HTTP access curl -I "http://server/git/repo.git/git-upload-pack" | head -1
# Verify permissions ssh git@server "ls -la /srv/git/repo.git" | head -5
# Test with different users sudo -u other-user git ls-remote "git@server:repo.git" 2>/dev/null && \ echo "✓ Access works for other users" || \ echo "✗ Access restricted for other users"}
# Setup anonymous read accesssetup_anonymous_access() { echo "Setting up anonymous read access..."
# Configure git daemon cat > /etc/systemd/system/git-daemon.service << EOF[Unit]Description=Git DaemonAfter=network.target
[Service]ExecStart=/usr/bin/git daemon --base-path=/srv/git --export-all --enable=upload-archive --user=git --group=gitRestart=always
[Install]WantedBy=multi-user.targetEOF
systemctl enable git-daemon systemctl start git-daemon
echo "Anonymous access configured on port 9418"}Repository State Issues:
Section titled “Repository State Issues:”# Handle repository state problemsfix_repository_state() { echo "Fixing repository state issues..."
# Check repository validity if ! git fsck --full >/dev/null 2>&1; then echo "Repository has corruption issues" git fsck --full 2>&1 | head -10 return 1 fi
# Ensure HEAD exists and is valid if ! git rev-parse HEAD >/dev/null 2>&1; then echo "HEAD is invalid, attempting to fix..."
# Try to set HEAD to main/master for branch in main master; do if git rev-parse "refs/heads/$branch" >/dev/null 2>&1; then git update-ref HEAD "refs/heads/$branch" echo "Set HEAD to $branch" break fi done fi
# Clean up stale pack files git gc --aggressive --prune=now
# Test upload-pack echo "Testing upload-pack functionality..." git upload-pack . --dry-run >/dev/null 2>&1 && \ echo "✓ Upload-pack works" || \ echo "✗ Upload-pack failed"
echo "Repository state repair attempt complete"}
# Recover from interrupted operationsrecover_interrupted_operations() { echo "Recovering from interrupted operations..."
# Clean up temporary files find .git -name "tmp_*" -type f -mtime +1 -delete
# Remove stale lock files find .git -name "*.lock" -type f -mtime +1 -delete
# Reset any ongoing operations rm -f .git/MERGE_HEAD .git/REBASE_HEAD 2>/dev/null
# Verify repository state git status --porcelain | wc -l | xargs echo "Uncommitted changes:"
echo "Recovery operations complete"}Real-World Usage Examples:
Section titled “Real-World Usage Examples:”Enterprise Git Server Setup:
Section titled “Enterprise Git Server Setup:”#!/bin/bash# Enterprise Git server with upload-pack
enterprise_git_server() { echo "=== Enterprise Git Server Setup ==="
# Configuration SERVER_NAME="git.enterprise.com" BASE_DIR="/srv/git/enterprise" ADMIN_USERS="admin1 admin2" DEV_USERS="dev1 dev2 dev3 dev4"
# Setup base infrastructure setup_infrastructure() { echo "Setting up Git server infrastructure..."
# Install required packages apt-get update apt-get install -y git apache2 libapache2-mod-fcgi fcgiwrap
# Create git user and group groupadd git useradd -r -g git -d /home/git -s /bin/bash git
# Setup directory structure mkdir -p "$BASE_DIR" chown git:git "$BASE_DIR" chmod 755 "$BASE_DIR"
echo "Infrastructure setup complete" }
# Configure Apache for Git configure_apache() { echo "Configuring Apache for Git access..."
cat > "/etc/apache2/sites-available/$SERVER_NAME.conf" << EOF<VirtualHost *:80> ServerName $SERVER_NAME ServerAlias git.$SERVER_NAME
DocumentRoot /var/www/html ErrorLog \${APACHE_LOG_DIR}/git-error.log CustomLog \${APACHE_LOG_DIR}/git-access.log combined
# Security headers Header always set X-Frame-Options DENY Header always set X-Content-Type-Options nosniff Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Git HTTP Backend SetEnv GIT_PROJECT_ROOT $BASE_DIR SetEnv GIT_HTTP_EXPORT_ALL SetEnv GIT_HTTP_MAX_REQUEST_BUFFER 100M
<Directory $BASE_DIR> Options +ExecCGI +FollowSymLinks AddHandler cgi-script .cgi DirectoryIndex gitweb.cgi
# Upload-pack endpoint RewriteEngine On RewriteCond %{REQUEST_URI} ^/(.*/git-upload-pack)$ RewriteRule ^/(.*)$ /usr/lib/git-core/git-http-backend/\$1 [L]
# Access control AuthType Basic AuthName "Enterprise Git Access" AuthUserFile /etc/apache2/git-users Require valid-user
# Admin access to all repos <RequireAll> Require user $ADMIN_USERS </RequireAll> </Directory>
# SSL Configuration SSLEngine on SSLCertificateFile /etc/ssl/certs/git.crt SSLCertificateKeyFile /etc/ssl/private/git.key SSLProtocol all -SSLv2 -SSLv3 SSLCipherSuite HIGH:!aNULL:!MD5</VirtualHost>EOF
# Create htpasswd file htpasswd -bc /etc/apache2/git-users admin admin123 for user in $DEV_USERS; do htpasswd -b /etc/apache2/git-users "$user" "${user}pass" done
# Enable site a2ensite "$SERVER_NAME.conf" a2enmod ssl rewrite headers systemctl reload apache2
echo "Apache configuration complete" }
# Setup repositories setup_repositories() { echo "Setting up enterprise repositories..."
# Create departmental structure departments="engineering design qa devops shared"
for dept in $departments; do mkdir -p "$BASE_DIR/$dept" chown git:git "$BASE_DIR/$dept"
# Create sample repositories repos="core utils tools" for repo in $repos; do sudo -u git git init --bare "$BASE_DIR/$dept/$repo.git" cd "$BASE_DIR/$dept/$repo.git"
# Configure for upload-pack sudo -u git git config uploadpack.allowFilter true sudo -u git git config uploadpack.allowRefInWant true sudo -u git git config core.logAllRefUpdates true
# Set description echo "$dept $repo repository" > description done done
echo "Repository setup complete" }
# Setup monitoring and logging setup_monitoring() { echo "Setting up monitoring and logging..."
# Create log directory mkdir -p /var/log/git-server chown git:git /var/log/git-server
# Setup log rotation cat > /etc/logrotate.d/git-server << EOF/var/log/git-server/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 git git postrotate systemctl reload apache2 endscript}EOF
# Create monitoring script cat > /usr/local/bin/git-server-monitor.sh << EOF#!/bin/bash# Monitor Git server health
LOG_FILE="/var/log/git-server/monitor.log"BASE_DIR="$BASE_DIR"
echo "\$(date): Git server health check" >> "\$LOG_FILE"
# Check repository integrityfind "\$BASE_DIR" -name "*.git" -type d | while read -r repo; do if ! sudo -u git git --git-dir="\$repo" fsck --quiet >/dev/null 2>&1; then echo "WARNING: \$repo has integrity issues" >> "\$LOG_FILE" fidone
# Check disk usageDISK_USAGE=\$(df "$BASE_DIR" | tail -1 | awk '{print \$5}' | sed 's/%//')if [ "\$DISK_USAGE" -gt 90 ]; then echo "WARNING: Disk usage is \${DISK_USAGE}%" >> "\$LOG_FILE"fi
# Check active connectionsACTIVE_CONNECTIONS=\$(netstat -tlnp 2>/dev/null | grep :80 | wc -l)echo "Active HTTP connections: \$ACTIVE_CONNECTIONS" >> "\$LOG_FILE"
echo "\$(date): Health check complete" >> "\$LOG_FILE"EOF
chmod +x /usr/local/bin/git-server-monitor.sh
# Setup cron monitoring (crontab -l ; echo "*/15 * * * * /usr/local/bin/git-server-monitor.sh") | crontab -
echo "Monitoring setup complete" }
# Setup backup system setup_backup_system() { echo "Setting up backup system..."
BACKUP_DIR="/srv/backups/git" RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR" chown git:git "$BACKUP_DIR"
cat > /usr/local/bin/git-server-backup.sh << EOF#!/bin/bash# Backup Git server repositories
BACKUP_DIR="$BACKUP_DIR"SOURCE_DIR="$BASE_DIR"DATE=\$(date +%Y%m%d-%H%M%S)
echo "Starting Git server backup: \$DATE"
# Backup all repositoriesfind "\$SOURCE_DIR" -name "*.git" -type d | while read -r repo; do repo_name=\$(basename "\$repo" .git) dept_name=\$(basename "\$(dirname "\$repo")")
backup_file="\$BACKUP_DIR/\${dept_name}-\${repo_name}-\$DATE.tar.gz"
echo "Backing up \$dept_name/\$repo_name..." sudo -u git tar czf "\$backup_file" -C "\$repo" .
# Set permissions chmod 644 "\$backup_file"done
# Cleanup old backupsfind "\$BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup complete: \$DATE"EOF
chmod +x /usr/local/bin/git-server-backup.sh
# Setup daily backups (crontab -l ; echo "0 2 * * * /usr/local/bin/git-server-backup.sh") | crontab -
echo "Backup system configured" }
# Run setup steps setup_infrastructure configure_apache setup_repositories setup_monitoring setup_backup_system
# Create usage documentation cat > "$BASE_DIR/README.md" << EOF# Enterprise Git Server
## Access Information- URL: https://$SERVER_NAME- Protocol: HTTP/HTTPS with authentication- Admin Users: $ADMIN_USERS- Developer Users: $DEV_USERS
## Repository Structure\`\`\`$BASE_DIR/├── engineering/│ ├── core.git│ ├── utils.git│ └── tools.git├── design/├── qa/├── devops/└── shared/\`\`\`
## Usage Examples\`\`\`bash# Clone repositorygit clone https://username@$SERVER_NAME/engineering/core.git
# Add remotegit remote add origin https://username@$SERVER_NAME/engineering/core.git
# Push changesgit push origin main\`\`\`
## SupportContact IT support for access requests and issues.EOF
echo "Enterprise Git server setup complete!" echo "Server URL: https://$SERVER_NAME" echo "Admin users: $ADMIN_USERS" echo "See $BASE_DIR/README.md for usage information"}
enterprise_git_serverDistributed Development Setup:
Section titled “Distributed Development Setup:”# Distributed development with upload-packdistributed_development() { echo "=== Distributed Development Setup ==="
# Setup central repository setup_central_repo() { local repo_name="$1"
echo "Setting up central repository: $repo_name"
# Create bare repository git init --bare "/srv/git/central/$repo_name.git" cd "/srv/git/central/$repo_name.git"
# Configure for distributed development git config uploadpack.allowFilter true git config uploadpack.allowRefInWant true git config receive.denyDeletes false
# Enable reflog git config core.logAllRefUpdates true
echo "Central repository ready" }
# Setup developer repositories setup_developer_repos() { local developers="alice bob charlie" local repo_name="$1"
echo "Setting up developer repositories..."
for dev in $developers; do echo "Setting up repository for $dev..."
# Create developer directory sudo mkdir -p "/home/$dev/projects" sudo chown "$dev:$dev" "/home/$dev/projects"
# Clone as developer sudo -u "$dev" git clone "/srv/git/central/$repo_name.git" "/home/$dev/projects/$repo_name"
# Configure developer settings sudo -u "$dev" bash -c "cd /home/$dev/projects/$repo_name && git config user.name '$dev' && git config user.email '$dev@company.com'" done
echo "Developer repositories setup complete" }
# Setup code review workflow setup_code_review() { echo "Setting up code review workflow..."
# Create review repository git init --bare "/srv/git/review/repo.git" cd "/srv/git/review/repo.git"
# Configure for reviews git config uploadpack.allowFilter true
# Setup review hooks cat > hooks/pre-receive << 'EOF'#!/bin/bash# Code review hook
echo "=== Code Review Check ==="
# Check commit messageswhile read oldrev newrev refname; do # Get commit messages git log --oneline "$oldrev..$newrev" | while read commit msg; do if [[ ! "$msg" =~ \[REVIEWED\] ]]; then echo "ERROR: Commit $commit missing [REVIEWED] tag" echo "Please get code reviewed before pushing" exit 1 fi donedone
echo "Code review check passed"EOF
chmod +x hooks/pre-receive
echo "Code review workflow configured" }
# Setup automated synchronization setup_auto_sync() { echo "Setting up automated synchronization..."
cat > /usr/local/bin/sync-developer-repos.sh << EOF#!/bin/bash# Sync all developer repositories
DEVELOPERS="alice bob charlie"REPO_NAME="$repo_name"
for dev in \$DEVELOPERS; do echo "Syncing \$dev's repository..."
# Push developer changes to central sudo -u "\$dev" bash -c "cd /home/\$dev/projects/\$REPO_NAME && git push origin --all"
# Pull central changes to developer repo sudo -u "\$dev" bash -c "cd /home/\$dev/projects/\$REPO_NAME && git pull origin main"done
echo "Repository synchronization complete"EOF
chmod +x /usr/local/bin/sync-developer-repos.sh
# Setup hourly sync (crontab -l ; echo "0 * * * * /usr/local/bin/sync-developer-repos.sh") | crontab -
echo "Automated sync configured" }
# Interactive setup echo "Distributed Development Setup" echo "============================"
read -p "Repository name: " repo_name
setup_central_repo "$repo_name" setup_developer_repos "$repo_name" setup_code_review setup_auto_sync
echo "Distributed development setup complete!" echo "Central repo: /srv/git/central/$repo_name.git" echo "Developer repos: /home/*/projects/$repo_name"}
# Usagedistributed_developmentHigh-Availability Git Setup:
Section titled “High-Availability Git Setup:”# High-availability Git server with upload-packhigh_availability_git() { echo "=== High-Availability Git Setup ==="
# Configuration PRIMARY_SERVER="git-primary.company.com" BACKUP_SERVER="git-backup.company.com" LOAD_BALANCER="git.company.com" REPOS="project-a project-b shared-libs"
# Setup primary server setup_primary_server() { echo "Setting up primary Git server..."
# Install Git and configure apt-get update apt-get install -y git apache2
# Setup repositories for repo in $REPOS; do mkdir -p "/srv/git/$repo" cd "/srv/git/$repo" git init --bare git update-server-info
# Configure HA settings git config uploadpack.allowFilter true git config uploadpack.allowRefInWant true done
# Configure Apache cat > /etc/apache2/sites-available/git-primary.conf << EOF<VirtualHost *:80> ServerName $PRIMARY_SERVER
DocumentRoot /srv/git SetEnv GIT_HTTP_EXPORT_ALL
<Directory /srv/git> Options +ExecCGI AddHandler cgi-script .cgi
RewriteEngine On RewriteCond %{REQUEST_URI} ^/(.*/git-upload-pack)$ RewriteRule ^/(.*)$ /usr/lib/git-core/git-http-backend/\$1 [L]
Require all granted </Directory></VirtualHost>EOF
a2ensite git-primary.conf systemctl reload apache2
echo "Primary server setup complete" }
# Setup backup server setup_backup_server() { echo "Setting up backup Git server..."
# Same setup as primary setup_primary_server
# Configure as backup sed -i "s/$PRIMARY_SERVER/$BACKUP_SERVER/" /etc/apache2/sites-available/git-primary.conf mv /etc/apache2/sites-available/git-primary.conf /etc/apache2/sites-available/git-backup.conf a2ensite git-backup.conf a2dissite git-primary.conf systemctl reload apache2
echo "Backup server setup complete" }
# Setup replication setup_replication() { echo "Setting up repository replication..."
cat > /usr/local/bin/git-replicate.sh << EOF#!/bin/bash# Replicate repositories between servers
PRIMARY="$PRIMARY_SERVER"BACKUP="$BACKUP_SERVER"REPOS="$REPOS"
for repo in \$REPOS; do echo "Replicating \$repo..."
# Sync from primary to backup ssh git@\$BACKUP "git --git-dir=/srv/git/\$repo fetch --all" < /dev/null
# Or use rsync for full sync rsync -av --delete "/srv/git/\$repo/" "git@\$BACKUP:/srv/git/\$repo/"done
echo "Replication complete"EOF
chmod +x /usr/local/bin/git-replicate.sh
# Setup frequent replication (crontab -l ; echo "*/5 * * * * /usr/local/bin/git-replicate.sh") | crontab -
echo "Replication configured" }
# Setup load balancer setup_load_balancer() { echo "Setting up load balancer..."
# Install HAProxy apt-get install -y haproxy
cat > /etc/haproxy/haproxy.cfg << EOFfrontend git-frontend bind *:80 mode http default_backend git-backend
backend git-backend mode http balance roundrobin server primary $PRIMARY_SERVER:80 check server backup $BACKUP_SERVER:80 check backup
listen stats bind *:8080 mode http stats enable stats uri /stats stats refresh 30sEOF
systemctl enable haproxy systemctl start haproxy
echo "Load balancer configured" }
# Setup monitoring setup_monitoring() { echo "Setting up HA monitoring..."
cat > /usr/local/bin/git-ha-monitor.sh << EOF#!/bin/bash# Monitor Git HA setup
PRIMARY="$PRIMARY_SERVER"BACKUP="$BACKUP_SERVER"LOAD_BALANCER="$LOAD_BALANCER"
echo "=== Git HA Health Check ==="echo "\$(date)"
# Check primary serverif curl -s --max-time 5 "http://\$PRIMARY/info/refs" >/dev/null; then echo "✓ Primary server healthy"else echo "✗ Primary server down"fi
# Check backup serverif curl -s --max-time 5 "http://\$BACKUP/info/refs" >/dev/null; then echo "✓ Backup server healthy"else echo "✗ Backup server down"fi
# Check load balancerif curl -s --max-time 5 "http://\$LOAD_BALANCER/info/refs" >/dev/null; then echo "✓ Load balancer healthy"else echo "✗ Load balancer down"fi
# Check repository consistencyfor repo in $REPOS; do primary_head=\$(git ls-remote "http://\$PRIMARY/\$repo.git" HEAD 2>/dev/null | cut -f1) backup_head=\$(git ls-remote "http://\$BACKUP/\$repo.git" HEAD 2>/dev/null | cut -f1)
if [ "\$primary_head" = "\$backup_head" ]; then echo "✓ \$repo synchronized" else echo "✗ \$repo out of sync" fidone
echo "Health check complete"EOF
chmod +x /usr/local/bin/git-ha-monitor.sh
# Setup monitoring cron (crontab -l ; echo "*/10 * * * * /usr/local/bin/git-ha-monitor.sh >> /var/log/git-ha.log 2>&1") | crontab -
echo "Monitoring configured" }
# Run setup echo "Setting up High-Availability Git infrastructure..." echo "Primary: $PRIMARY_SERVER" echo "Backup: $BACKUP_SERVER" echo "Load Balancer: $LOAD_BALANCER"
setup_primary_server setup_backup_server setup_replication setup_load_balancer setup_monitoring
echo "High-availability Git setup complete!" echo "Access via: http://$LOAD_BALANCER" echo "Monitor at: http://$LOAD_BALANCER:8080/stats"}
high_availability_git