Skip to content

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.

Terminal window
git upload-pack [--strict] [--timeout=<n>] <directory>
OptionDescription
--strictDo not try /.git if is not a Git directory
--timeout=<n>Interrupt transfer after seconds of inactivity
ParameterDescription
<directory>Repository directory to serve
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 references
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 transfer
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 client
Terminal window
# Setup Git daemon for upload-pack serving
git 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-backend
cat > /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>
EOF
Terminal window
# Standard fetch operation
git fetch origin
# Fetch with upload-pack
git fetch --upload-pack=git-upload-pack origin
# Shallow fetch
git fetch --depth=1 origin
# Fetch specific branch
git fetch origin feature-branch
Terminal window
# Sync with remote repository
git remote update
# Fetch all branches
git fetch --all
# Fetch with progress
GIT_TRACE=1 git fetch origin
# Fetch with custom upload-pack
git fetch --upload-pack="/usr/bin/git-upload-pack" origin
Terminal window
# Setup protocol extensions
setup_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 = true
EOF
echo "Protocol extensions configured"
}
# Usage
setup_protocol_extensions
Terminal window
# Optimize upload-pack for large repositories
optimize_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"
}
# Usage
optimize_large_repo
Terminal window
# Implement access control for upload-pack
setup_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 users
case "$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
;;
esac
EOF
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"
}
# Usage
setup_access_control
Terminal window
# Configure upload-pack behavior
git config uploadpack.allowFilter true # Allow partial clones
git config uploadpack.allowRefInWant true # Allow ref-in-want
git config uploadpack.allowSidebandAll true # Allow sideband all
git config uploadpack.keepAlive 60 # Keep-alive interval
git config uploadpack.timeout 3600 # Transfer timeout
# Configure pack generation
git config pack.window 10 # Delta window size
git config pack.depth 50 # Delta depth limit
git config pack.compression 6 # Compression level
# Configure protocol
git config protocol.version 2 # Use protocol v2
git config protocol.allow always # Protocol allowances
Terminal window
# Apache configuration for Git HTTP
cat > /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 configuration
cat > /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;
}
}
EOF
Terminal window
# Configure client for upload-pack operations
git config http.postBuffer 524288000 # 500MB buffer
git config http.lowSpeedLimit 1000 # 1KB/s minimum speed
git config http.lowSpeedTime 300 # 5 minute timeout
# Configure fetch behavior
git config fetch.prune true # Prune deleted branches
git config fetch.pruneTags true # Prune deleted tags
# Configure protocol preferences
git config protocol.version 2 # Use protocol v2
git config protocol.allow always # Allow all protocols
Terminal window
# Secure upload-pack deployment
secure_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 << EOF
command="git-upload-pack '/srv/git/myrepo.git'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@client
EOF
# 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 script
cat > /usr/local/bin/validate-git-access << 'EOF'
#!/bin/bash
# Validate Git upload-pack access
USER="$1"
REPO="$2"
# Log access
echo "$(date): $USER accessed $REPO via upload-pack" >> /var/log/git-upload/access.log
# Check permissions
if [ "$USER" = "admin" ] || groups "$USER" | grep -q "developers"; then
exec git-upload-pack "$REPO"
else
echo "Access denied"
exit 1
fi
EOF
chmod +x /usr/local/bin/validate-git-access
Terminal window
# Upload-pack in CI/CD pipelines
ci_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 CI
ci_upload_pack_integration
Terminal window
# Repository mirroring with upload-pack
setup_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 --all
git 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"
}
# Usage
setup_repository_mirror "https://github.com/user/repo.git" "/srv/mirror/repo.git"
Terminal window
# Support multiple protocols with upload-pack
setup_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 configuration
SetEnv GIT_PROJECT_ROOT /var/www/git
SetEnv GIT_HTTP_EXPORT_ALL
# Protocol detection
RewriteEngine On
RewriteCond %{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 << EOF
command="git-upload-pack '/srv/git/myrepo.git'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@client
EOF
echo "Multi-protocol support configured"
}
# Usage
setup_multi_protocol
Terminal window
# Diagnose protocol negotiation problems
diagnose_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"
}
# Usage
diagnose_protocol_issues
Terminal window
# Troubleshoot upload-pack performance
optimize_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 performance
monitor_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"
}
Terminal window
# Fix access control problems
fix_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 access
setup_anonymous_access() {
echo "Setting up anonymous read access..."
# Configure git daemon
cat > /etc/systemd/system/git-daemon.service << EOF
[Unit]
Description=Git Daemon
After=network.target
[Service]
ExecStart=/usr/bin/git daemon --base-path=/srv/git --export-all --enable=upload-archive --user=git --group=git
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable git-daemon
systemctl start git-daemon
echo "Anonymous access configured on port 9418"
}
Terminal window
# Handle repository state problems
fix_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 operations
recover_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"
}
#!/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 integrity
find "\$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"
fi
done
# Check disk usage
DISK_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 connections
ACTIVE_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 repositories
find "\$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 backups
find "\$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 repository
git clone https://username@$SERVER_NAME/engineering/core.git
# Add remote
git remote add origin https://username@$SERVER_NAME/engineering/core.git
# Push changes
git push origin main
\`\`\`
## Support
Contact 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_server
Terminal window
# Distributed development with upload-pack
distributed_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 messages
while 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
done
done
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"
}
# Usage
distributed_development
Terminal window
# High-availability Git server with upload-pack
high_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 << EOF
frontend 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 30s
EOF
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 server
if curl -s --max-time 5 "http://\$PRIMARY/info/refs" >/dev/null; then
echo "✓ Primary server healthy"
else
echo "✗ Primary server down"
fi
# Check backup server
if curl -s --max-time 5 "http://\$BACKUP/info/refs" >/dev/null; then
echo "✓ Backup server healthy"
else
echo "✗ Backup server down"
fi
# Check load balancer
if 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 consistency
for 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"
fi
done
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