update-server-info Git Command Guide
The git update-server-info command updates auxiliary information files that enable dumb HTTP transport for Git repositories. It generates index files and metadata that allow HTTP clients to discover and fetch repository data without requiring smart HTTP or SSH protocols.
git update-server-info Syntax:
Section titled “git update-server-info Syntax:”git update-server-info [--force]Options:
Section titled “Options:”| Option | Description |
|---|---|
--force | Update info files even if they appear current |
Parameters:
Section titled “Parameters:”None
Understanding Server Info Operations:
Section titled “Understanding Server Info Operations:”Dumb HTTP Transport:
Section titled “Dumb HTTP Transport:”Dumb HTTP Transport Architecture:├── Static Files: Repository served as static files├── Info Files: Metadata for client discovery├── Pack Files: Compressed object collections├── Index Files: Lookup tables for pack files└── Refs: Branch and tag informationGenerated Files Structure:
Section titled “Generated Files Structure:”.git/info/ Directory Structure:├── refs (file): All reference information├── packs (file): List of pack files└── http Alternates (optional): Shared repository links
Static Web Directory:├── HEAD: Current branch reference├── info/refs: All repository references├── objects/info/packs: Pack file list├── objects/info/http-alternates: Alternate repository URLs└── objects/pack/*.pack: Pack filesClient Discovery Process:
Section titled “Client Discovery Process:”Dumb HTTP Client Flow:├── GET info/refs: Discover all references├── GET HEAD: Find current branch├── GET objects/info/packs: Find pack files├── GET objects/pack/*.pack: Download pack files├── GET objects/pack/*.idx: Download pack indexes└── Reconstruct: Build local repositoryBasic Update-Server-Info Operations:
Section titled “Basic Update-Server-Info Operations:”Update Server Information:
Section titled “Update Server Information:”# Update server info filesgit update-server-info
# Force update even if currentgit update-server-info --force
# Update after repository changesgit update-server-infoRepository Setup for HTTP:
Section titled “Repository Setup for HTTP:”# Initialize repository for HTTP servinggit init --bare myrepo.gitcd myrepo.git
# Create initial commit# ... add files and commit ...
# Update server infogit update-server-info
# Verify files createdls -la info/ls -la objects/info/Web Server Configuration:
Section titled “Web Server Configuration:”# Configure Apache for Git repository# In httpd.conf or .htaccess:<Directory "/var/www/git"> Options +ExecCGI AddHandler cgi-script .cgi DirectoryIndex index.cgi</Directory>
# Or for static serving:<Directory "/var/www/git"> Options Indexes FollowSymLinks AllowOverride None Require all granted</Directory>Advanced Update-Server-Info Scenarios:
Section titled “Advanced Update-Server-Info Scenarios:”Repository Publishing:
Section titled “Repository Publishing:”# Publish repository via HTTPpublish_repository() { local repo_path="$1" local web_path="$2"
echo "Publishing repository to web..."
# Copy repository to web directory cp -r "$repo_path" "$web_path"
cd "$web_path"
# Update server information git update-server-info
# Set proper permissions find . -type f -exec chmod 644 {} \; find . -type d -exec chmod 755 {} \;
echo "Repository published at $web_path"}
# Usagepublish_repository "/path/to/repo" "/var/www/html/myrepo.git"Multi-Repository Setup:
Section titled “Multi-Repository Setup:”# Setup multiple repositories for HTTPsetup_multi_repo() { local base_dir="$1" local repos=("project-a" "project-b" "shared-libs")
echo "Setting up multiple repositories..."
mkdir -p "$base_dir"
for repo in "${repos[@]}"; do echo "Setting up $repo..."
# Create bare repository git init --bare "$base_dir/$repo.git" cd "$base_dir/$repo.git"
# Add initial content or leave empty # ... populate repository ...
# Update server info git update-server-info
cd .. done
# Create index page cat > "$base_dir/index.html" << EOF<html><head><title>Git Repositories</title></head><body><h1>Available Repositories</h1><ul>$(for repo in "${repos[@]}"; do echo "<li><a href=\"$repo.git\">$repo</a></li>"done)</ul></body></html>EOF
echo "Multi-repository setup complete"}
# Usagesetup_multi_repo "/var/www/git"Automated Updates:
Section titled “Automated Updates:”# Automate server info updatessetup_auto_update() { echo "Setting up automated server info updates..."
# Create update script cat > update-server-info.sh << 'EOF'#!/bin/bash# Update server info for all repositories
REPO_BASE="/var/www/git"LOG_FILE="/var/log/git-updates.log"
echo "$(date): Starting server info updates" >> "$LOG_FILE"
find "$REPO_BASE" -name "*.git" -type d | while read -r repo; do if [ -d "$repo/.git" ] || git --git-dir="$repo" rev-parse --git-dir >/dev/null 2>&1; then echo "Updating $repo" >> "$LOG_FILE" cd "$repo" git update-server-info 2>> "$LOG_FILE" fidone
echo "$(date): Server info updates complete" >> "$LOG_FILE"EOF
chmod +x update-server-info.sh
# Setup cron job (crontab -l ; echo "*/30 * * * * /path/to/update-server-info.sh") | crontab -
echo "Automated updates configured"}
# Usagesetup_auto_updateConfiguration and Best Practices:
Section titled “Configuration and Best Practices:”Git Configuration for Server Info:
Section titled “Git Configuration for Server Info:”# Configure repository for dumb HTTPgit config http.receivepack false # Disable smart HTTP pushgit config http.uploadpack false # Force dumb HTTP fetch
# Configure server info updatesgit config core.logAllRefUpdates true # Ensure reflog for updatesgit config receive.updateserverinfo true # Auto-update on receive
# Configure alternates for shared reposecho "/shared/repo.git/objects" >> .git/objects/info/http-alternatesServer Configuration Best Practices:
Section titled “Server Configuration Best Practices:”# Apache configuration for Gitcat > /etc/apache2/sites-available/git.conf << 'EOF'<VirtualHost *:80> ServerName git.example.com DocumentRoot /var/www/git
<Directory /var/www/git> Options Indexes FollowSymLinks AllowOverride None Require all granted
# Enable directory listing for repo browsing IndexOptions FancyIndexing
# Protect .git directories RedirectMatch 404 /\.git(/|$) </Directory>
# Custom error pages ErrorDocument 404 /404.html</VirtualHost>EOF
# Enable sitea2ensite git.confsystemctl reload apache2Security Considerations:
Section titled “Security Considerations:”# Secure repository accesssecure_git_access() { echo "Configuring secure Git access..."
# Create git user useradd -r -s /bin/bash -d /home/git git
# Setup SSH keys for git user mkdir -p /home/git/.ssh cat > /home/git/.ssh/authorized_keys << EOFcommand="git shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@clientEOF
# Set proper permissions chown -R git:git /home/git/.ssh chmod 700 /home/git/.ssh chmod 600 /home/git/.ssh/authorized_keys
# Setup repositories mkdir -p /srv/git chown git:git /srv/git
echo "Secure Git access configured"}
# Usagesecure_git_accessIntegration with Development Workflows:
Section titled “Integration with Development Workflows:”CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# Update server info in CI/CDci_update_server_info() { echo "=== CI/CD Server Info Update ==="
# Update server info after build update_server_info() { echo "Updating server info..."
# Ensure we're in a git repository if ! git rev-parse --git-dir >/dev/null 2>&1; then echo "Not in a git repository" return 1 fi
# Update server information git update-server-info
# Verify update if [ -f info/refs ] && [ -f objects/info/packs ]; then echo "✓ Server info updated successfully" else echo "✗ Server info update failed" return 1 fi }
# Deploy to web server deploy_to_web() { local web_server="$1" local repo_name="$2"
echo "Deploying to web server..."
# Create deployment package git archive --format=tar --prefix="$repo_name/" HEAD | gzip > "${repo_name}.tar.gz"
# Upload to web server scp "${repo_name}.tar.gz" "$web_server:/tmp/" ssh "$web_server" "cd /var/www/git && tar xzf /tmp/${repo_name}.tar.gz && cd $repo_name && git update-server-info"
# Cleanup rm "${repo_name}.tar.gz"
echo "Deployment complete" }
# Run CI/CD steps update_server_info deploy_to_web "web-server.example.com" "my-app"}
# Usage in CIci_update_server_infoRepository Mirroring:
Section titled “Repository Mirroring:”# Mirror repository with server infosetup_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"
# Update server info for HTTP access git update-server-info
# Setup automatic mirroring cat > mirror-update.sh << 'EOF'#!/bin/bash# Update mirror from source
cd "$(dirname "$0")"git fetch --allgit update-server-info
echo "Mirror updated at $(date)"EOF
chmod +x mirror-update.sh
# Setup cron for regular updates (crontab -l ; echo "*/15 * * * * $(pwd)/mirror-update.sh") | crontab -
echo "Repository mirror setup complete"}
# Usagesetup_repository_mirror "https://github.com/user/repo.git" "/var/www/mirror/repo.git"Multi-Protocol Support:
Section titled “Multi-Protocol Support:”# Support both smart and dumb HTTPsetup_dual_protocol() { echo "Setting up dual protocol support..."
# Configure for smart HTTP git config http.receivepack true git config http.uploadpack true
# Also maintain dumb HTTP support git update-server-info
# Setup server to detect client capabilities cat > /var/www/git/.htaccess << 'EOF'# Detect Git client capabilitiesRewriteEngine On
# Smart HTTP for capable clientsRewriteCond %{REQUEST_URI} ^/git/(.*/git-receive-pack)$RewriteRule ^/git/(.*)$ /git/smart-http.cgi [L]
RewriteCond %{REQUEST_URI} ^/git/(.*/git-upload-pack)$RewriteRule ^/git/(.*)$ /git/smart-http.cgi [L]
# Fall back to dumb HTTPRewriteRule ^/git/(.*/info/refs)$ /git/dumb-http.cgi [L]EOF
echo "Dual protocol support configured"}
# Usagesetup_dual_protocolTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Missing Server Info Files:
Section titled “Missing Server Info Files:”# Check and create server info filescheck_server_info() { echo "Checking server info files..."
# Required files required_files=("info/refs" "objects/info/packs")
for file in "${required_files[@]}"; do if [ ! -f "$file" ]; then echo "Missing: $file" missing=true else echo "Present: $file" fi done
if [ "$missing" = true ]; then echo "Updating server info..." git update-server-info fi}
# Force recreation of server infoforce_update_server_info() { echo "Force updating server info..."
# Remove existing files rm -f info/refs objects/info/packs
# Recreate git update-server-info
# Verify ls -la info/refs objects/info/packs}Permission Issues:
Section titled “Permission Issues:”# Fix server info permissionsfix_server_permissions() { echo "Fixing server permissions..."
# Set proper permissions for web access find .git -type f -exec chmod 644 {} \; find .git -type d -exec chmod 755 {} \;
# Ensure info files are readable chmod 644 info/refs chmod 644 objects/info/packs
# Check web server user access web_user="www-data" if id "$web_user" >/dev/null 2>&1; then chown -R "$web_user:$web_user" . fi
echo "Permissions fixed"}
# Test web accesstest_web_access() { local repo_url="$1"
echo "Testing web access to $repo_url..."
# Test info/refs access if curl -s "$repo_url/info/refs" >/dev/null; then echo "✓ info/refs accessible" else echo "✗ info/refs not accessible" fi
# Test pack file access pack_file=$(curl -s "$repo_url/objects/info/packs" | head -1 | cut -d' ' -f2) if [ -n "$pack_file" ] && curl -s "$repo_url/objects/pack/$pack_file" >/dev/null; then echo "✓ Pack files accessible" else echo "✗ Pack files not accessible" fi}Repository State Issues:
Section titled “Repository State Issues:”# Handle repository state problemsfix_repository_state() { echo "Fixing repository state..."
# Check repository validity if ! git fsck --full >/dev/null 2>&1; then echo "Repository has corruption issues" return 1 fi
# Ensure HEAD exists if ! git rev-parse HEAD >/dev/null 2>&1; then echo "HEAD not set, setting to main/master" if git rev-parse refs/heads/main >/dev/null 2>&1; then git update-ref HEAD refs/heads/main elif git rev-parse refs/heads/master >/dev/null 2>&1; then git update-ref HEAD refs/heads/master else echo "No main/master branch found" return 1 fi fi
# Update server info git update-server-info
echo "Repository state fixed"}
# Clean up stale server infocleanup_stale_info() { echo "Cleaning up stale server info..."
# Remove outdated pack references comm -23 <(sort objects/info/packs) <(ls objects/pack/*.pack | sed 's|objects/pack/||' | sort) > stale_packs.txt
if [ -s stale_packs.txt ]; then echo "Removing stale pack references..." grep -v -f stale_packs.txt objects/info/packs > objects/info/packs.new mv objects/info/packs.new objects/info/packs fi
# Update server info git update-server-info
echo "Stale info cleaned up"}Client Access Issues:
Section titled “Client Access Issues:”# Diagnose client access problemsdiagnose_client_access() { local repo_url="$1"
echo "Diagnosing client access to $repo_url..."
# Check basic connectivity if ! curl -s "$repo_url" >/dev/null; then echo "Repository URL not accessible" return 1 fi
# Check info/refs info_refs=$(curl -s "$repo_url/info/refs") if [ -z "$info_refs" ]; then echo "info/refs not found or empty" return 1 fi
# Check for pack files pack_info=$(curl -s "$repo_url/objects/info/packs") if [ -z "$pack_info" ]; then echo "No pack files found" return 1 fi
# Test clone capability if git ls-remote "$repo_url" >/dev/null 2>&1; then echo "✓ Repository accessible via Git" else echo "✗ Repository not accessible via Git" return 1 fi
echo "Client access diagnosis complete"}
# Usagediagnose_client_access "http://example.com/git/myrepo.git"Real-World Usage Examples:
Section titled “Real-World Usage Examples:”Simple Git Web Server Setup:
Section titled “Simple Git Web Server Setup:”#!/bin/bash# Simple Git web server setup
simple_git_server() { echo "=== Simple Git Web Server Setup ==="
# Configuration WEB_ROOT="/var/www/html/git" REPO_NAME="myproject" DOMAIN="git.example.com"
# Create web directory sudo mkdir -p "$WEB_ROOT" sudo chown www-data:www-data "$WEB_ROOT"
# Setup repository sudo -u www-data git init --bare "$WEB_ROOT/$REPO_NAME.git" cd "$WEB_ROOT/$REPO_NAME.git"
# Create initial content sudo -u www-data git --git-dir=. --work-tree=/tmp/empty init sudo -u www-data git --git-dir=. update-server-info
# Setup Apache configuration sudo tee "/etc/apache2/sites-available/$DOMAIN.conf" << EOF<VirtualHost *:80> ServerName $DOMAIN DocumentRoot $WEB_ROOT
<Directory $WEB_ROOT> Options Indexes FollowSymLinks AllowOverride None Require all granted
# Enable Git content type AddType application/x-git-packed-objects .pack AddType application/x-git-loose-objects .idx </Directory></VirtualHost>EOF
# Enable site sudo a2ensite "$DOMAIN.conf" sudo systemctl reload apache2
# Create usage instructions cat > "$WEB_ROOT/README.html" << EOF<html><head><title>$DOMAIN Git Server</title></head><body><h1>$DOMAIN Git Server</h1><p>To clone repositories:</p><pre>git clone http://$DOMAIN/$REPO_NAME.git</pre>
<p>To add this server as remote:</p><pre>git remote add origin http://$DOMAIN/$REPO_NAME.git</pre></body></html>EOF
echo "Simple Git server setup complete" echo "Access at: http://$DOMAIN" echo "Repository: http://$DOMAIN/$REPO_NAME.git"}
simple_git_serverEnterprise Repository Hosting:
Section titled “Enterprise Repository Hosting:”# Enterprise Git repository hostingenterprise_git_hosting() { echo "=== Enterprise Git Repository Hosting ==="
# Configuration BASE_DIR="/srv/git/enterprise" DEPARTMENTS=("engineering" "design" "qa" "devops") ACCESS_CONTROL="/etc/git-access.conf"
# Create base structure sudo mkdir -p "$BASE_DIR" sudo chown git:git "$BASE_DIR"
# Setup departmental repositories for dept in "${DEPARTMENTS[@]}"; do echo "Setting up $dept department..."
# Create department directory sudo mkdir -p "$BASE_DIR/$dept" sudo chown git:git "$BASE_DIR/$dept"
# Create sample repositories repos=("shared-libs" "documentation" "tools") for repo in "${repos[@]}"; do sudo -u git git init --bare "$BASE_DIR/$dept/$repo.git" cd "$BASE_DIR/$dept/$repo.git" sudo -u git git update-server-info done done
# Setup access control sudo tee "$ACCESS_CONTROL" << EOF# Git access control configuration[groups]admins = alice, bobdevelopers = alice, bob, charlie, davedesigners = eve, frank
[repos]engineering/shared-libs = @developersdesigners = @designersqa = @developers, @designersdevops = @adminsEOF
# Create department index pages for dept in "${DEPARTMENTS[@]}"; do sudo tee "$BASE_DIR/$dept/index.html" << EOF<html><head><title>$dept Department Repositories</title></head><body><h1>$dept Department</h1><h2>Available Repositories:</h2><ul>$(ls -1 "$BASE_DIR/$dept"/*.git 2>/dev/null | while read -r repo; do repo_name=$(basename "$repo" .git) echo "<li><a href=\"$repo_name.git\">$repo_name</a></li>"done)</ul></body></html>EOF done
# Setup monitoring sudo tee "/usr/local/bin/git-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
# Update server info for all reposfind "\$BASE_DIR" -name "*.git" -type d | while read -r repo; do cd "\$repo" sudo -u git git update-server-info >/dev/null 2>&1done
echo "\$(date): Health check complete" >> "\$LOG_FILE"EOF
sudo chmod +x "/usr/local/bin/git-monitor.sh"
# Setup cron monitoring (sudo crontab -l ; echo "0 */6 * * * /usr/local/bin/git-monitor.sh") | sudo crontab -
echo "Enterprise Git hosting setup complete" echo "Base directory: $BASE_DIR" echo "Access control: $ACCESS_CONTROL"}
enterprise_git_hostingCDN and Caching Integration:
Section titled “CDN and Caching Integration:”# Integrate with CDN for Git hostingcdn_git_integration() { echo "=== CDN Integration for Git Hosting ==="
# Configuration REPO_DIR="/var/www/git" CDN_URL="https://cdn.example.com/git" CACHE_DIR="/var/cache/git-cdn"
# Setup CDN-friendly structure setup_cdn_structure() { echo "Setting up CDN-friendly structure..."
# Create cache directory sudo mkdir -p "$CACHE_DIR" sudo chown www-data:www-data "$CACHE_DIR"
# Setup repository with CDN headers cat > "$REPO_DIR/.htaccess" << EOF# CDN-friendly headers<Files *.pack> Header set Cache-Control "public, max-age=31536000" Header set ETag "$(git rev-parse HEAD)"</Files>
<Files *.idx> Header set Cache-Control "public, max-age=31536000"</Files>
<Files info/refs> Header set Cache-Control "public, max-age=300"</Files>EOF
# Update server info find "$REPO_DIR" -name "*.git" -type d | while read -r repo; do cd "$repo" git update-server-info done }
# CDN cache management manage_cdn_cache() { echo "Managing CDN cache..."
# Purge CDN cache for updated content updated_refs=$(git log --since="1 hour ago" --format="%H" | head -5)
for ref in $updated_refs; do # Invalidate CDN cache for this ref curl -X PURGE "$CDN_URL/objects/$ref" 2>/dev/null || true done
# Update cache manifest git ls-remote . | while read -r sha ref; do echo "$sha $ref $(date +%s)" >> "$CACHE_DIR/manifest.txt" done
# Clean old cache entries find "$CACHE_DIR" -name "*.pack" -mtime +30 -delete }
# Setup automated CDN sync setup_cdn_sync() { echo "Setting up automated CDN sync..."
cat > "/usr/local/bin/cdn-sync.sh" << EOF#!/bin/bash# Sync Git repositories to CDN
REPO_DIR="$REPO_DIR"CDN_URL="$CDN_URL"CACHE_DIR="$CACHE_DIR"
# Update all repositoriesfind "\$REPO_DIR" -name "*.git" -type d | while read -r repo; do cd "\$repo" git update-server-info
# Sync to CDN rsync -av --delete . "\$CDN_URL/$(basename "\$repo" .git)/"done
# Update cache"$0" cache-updateEOF
sudo chmod +x "/usr/local/bin/cdn-sync.sh"
# Setup cron (sudo crontab -l ; echo "*/30 * * * * /usr/local/bin/cdn-sync.sh") | sudo crontab - }
# Interactive setup echo "CDN Integration Options:" echo "1. Setup CDN-friendly structure" echo "2. Manage CDN cache" echo "3. Setup automated CDN sync"
read -p "Select option (1-3): " option
case "$option" in 1) setup_cdn_structure ;; 2) manage_cdn_cache ;; 3) setup_cdn_sync ;; esac}
cdn_git_integrationBackup and Disaster Recovery:
Section titled “Backup and Disaster Recovery:”# Backup system using update-server-infogit_backup_system() { echo "=== Git Backup System ==="
# Configuration PRIMARY_REPO="/srv/git/primary" BACKUP_REPO="/srv/git/backup" WEB_BACKUP="/var/www/backup"
# Create backup repository setup_backup_repo() { echo "Setting up backup repository..."
# Clone primary as backup git clone --mirror "$PRIMARY_REPO" "$BACKUP_REPO" cd "$BACKUP_REPO"
# Setup for web access git update-server-info
# Copy to web directory cp -r "$BACKUP_REPO" "$WEB_BACKUP/"
echo "Backup repository setup complete" }
# Incremental backup incremental_backup() { echo "Performing incremental backup..."
cd "$BACKUP_REPO"
# Fetch updates from primary git fetch --all
# Update server info git update-server-info
# Sync to web rsync -av --delete "$BACKUP_REPO/" "$WEB_BACKUP/"
# Update backup manifest cat > "$WEB_BACKUP/backup-info.txt" << EOFGit Repository Backup
Primary Repository: $PRIMARY_REPOBackup Location: $WEB_BACKUPLast Backup: $(date)Backup Size: $(du -sh "$BACKUP_REPO" | cut -f1)
To restore:git clone $WEB_BACKUP restored-repocd restored-repogit remote set-url origin $PRIMARY_REPOEOF
echo "Incremental backup complete" }
# Disaster recovery disaster_recovery() { echo "Initiating disaster recovery..."
# Check backup integrity cd "$BACKUP_REPO" if ! git fsck --full >/dev/null 2>&1; then echo "Backup repository corrupted" return 1 fi
# Restore to primary location rm -rf "$PRIMARY_REPO" git clone --mirror "$BACKUP_REPO" "$PRIMARY_REPO"
# Update server info cd "$PRIMARY_REPO" git update-server-info
echo "Disaster recovery complete" echo "Primary repository restored from backup" }
# Interactive backup management echo "Backup System Options:" echo "1. Setup backup repository" echo "2. Perform incremental backup" echo "3. Disaster recovery"
read -p "Select option (1-3): " option
case "$option" in 1) setup_backup_repo ;; 2) incremental_backup ;; 3) disaster_recovery ;; esac}
git_backup_system