Skip to content

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.

Terminal window
git update-server-info [--force]
OptionDescription
--forceUpdate info files even if they appear current

None

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 information
.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 files
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 repository
Terminal window
# Update server info files
git update-server-info
# Force update even if current
git update-server-info --force
# Update after repository changes
git update-server-info
Terminal window
# Initialize repository for HTTP serving
git init --bare myrepo.git
cd myrepo.git
# Create initial commit
# ... add files and commit ...
# Update server info
git update-server-info
# Verify files created
ls -la info/
ls -la objects/info/
Terminal window
# 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>
Terminal window
# Publish repository via HTTP
publish_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"
}
# Usage
publish_repository "/path/to/repo" "/var/www/html/myrepo.git"
Terminal window
# Setup multiple repositories for HTTP
setup_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"
}
# Usage
setup_multi_repo "/var/www/git"
Terminal window
# Automate server info updates
setup_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"
fi
done
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"
}
# Usage
setup_auto_update
Terminal window
# Configure repository for dumb HTTP
git config http.receivepack false # Disable smart HTTP push
git config http.uploadpack false # Force dumb HTTP fetch
# Configure server info updates
git config core.logAllRefUpdates true # Ensure reflog for updates
git config receive.updateserverinfo true # Auto-update on receive
# Configure alternates for shared repos
echo "/shared/repo.git/objects" >> .git/objects/info/http-alternates
Terminal window
# Apache configuration for Git
cat > /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 site
a2ensite git.conf
systemctl reload apache2
Terminal window
# Secure repository access
secure_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 << EOF
command="git shell -c \"$SSH_ORIGINAL_COMMAND\"",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3... user@client
EOF
# 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"
}
# Usage
secure_git_access
Terminal window
# Update server info in CI/CD
ci_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 CI
ci_update_server_info
Terminal window
# Mirror repository with server info
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"
# 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 --all
git 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"
}
# Usage
setup_repository_mirror "https://github.com/user/repo.git" "/var/www/mirror/repo.git"
Terminal window
# Support both smart and dumb HTTP
setup_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 capabilities
RewriteEngine On
# Smart HTTP for capable clients
RewriteCond %{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 HTTP
RewriteRule ^/git/(.*/info/refs)$ /git/dumb-http.cgi [L]
EOF
echo "Dual protocol support configured"
}
# Usage
setup_dual_protocol
Terminal window
# Check and create server info files
check_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 info
force_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
}
Terminal window
# Fix server info permissions
fix_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 access
test_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
}
Terminal window
# Handle repository state problems
fix_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 info
cleanup_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"
}
Terminal window
# Diagnose client access problems
diagnose_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"
}
# Usage
diagnose_client_access "http://example.com/git/myrepo.git"
#!/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_server
Terminal window
# Enterprise Git repository hosting
enterprise_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, bob
developers = alice, bob, charlie, dave
designers = eve, frank
[repos]
engineering/shared-libs = @developers
designers = @designers
qa = @developers, @designers
devops = @admins
EOF
# 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 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
# Update server info for all repos
find "\$BASE_DIR" -name "*.git" -type d | while read -r repo; do
cd "\$repo"
sudo -u git git update-server-info >/dev/null 2>&1
done
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_hosting
Terminal window
# Integrate with CDN for Git hosting
cdn_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 repositories
find "\$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-update
EOF
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_integration
Terminal window
# Backup system using update-server-info
git_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" << EOF
Git Repository Backup
Primary Repository: $PRIMARY_REPO
Backup Location: $WEB_BACKUP
Last Backup: $(date)
Backup Size: $(du -sh "$BACKUP_REPO" | cut -f1)
To restore:
git clone $WEB_BACKUP restored-repo
cd restored-repo
git remote set-url origin $PRIMARY_REPO
EOF
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