Skip to content

update-index Git Command Guide

The git update-index command registers file contents in the index (staging area) and manages Git’s internal state. It’s a low-level command that provides direct control over the index, allowing you to add, remove, and modify index entries with precise control over Git’s staging operations.

Terminal window
git update-index [--add] [--remove] [--refresh] [-q] [--ignore-submodules]
[--ignore-missing] [--unmerged] [--really-refresh] [--again] [--unresolve]
[--info-only] [--index-info] [--chmod=(+|-)x] [--assume-unchanged]
[--no-assume-unchanged] [--skip-worktree] [--no-skip-worktree]
[--ignore-skip-worktree-entries] [--really-refresh] [--unresolve]
[--again] [--info-only] [--index-info] [--chmod=(+|-)x]
[--[no-]fsmonitor-valid] [--[no-]skip-worktree] [--[no-]assume-unchanged]
[--[no-]ignore-skip-worktree-entries] [--renormalize]
[--mode=<permissions>] [--cacheinfo <mode>,<object>,<path>]
[--index-version <n>] [--null] [--file-truncate] [--untracked-cache]
[--test-untracked-cache] [--force-untracked-cache] [--untracked-cache-no-op]
[--force-remove] [--replace] [--stdin] [--verbose] [--clear-resolve-undo]
[--pathspec-from-file=<file> [--pathspec-file-nul]] [<pathspec>...]
OptionDescription
--addAdd files not already in index
--removeRemove files from index and working tree
--force-removeRemove files even if modified
--replaceReplace files in index
OptionDescription
--refreshRefresh stat information in index
--really-refreshRefresh even if up-to-date
--againRun refresh on previously failed entries
--unresolveMark files as unresolved (merge conflicts)
--clear-resolve-undoClear resolve-undo information
OptionDescription
`—chmod=(+-)x`
--mode=<permissions>Set file permissions
--cacheinfo <mode>,<object>,<path>Add arbitrary entry to index
OptionDescription
--assume-unchangedMark files as unchanged
--no-assume-unchangedUnmark files as unchanged
--skip-worktreeMark files to skip worktree updates
--no-skip-worktreeUnmark files for worktree updates
--ignore-skip-worktree-entriesIgnore skip-worktree entries
OptionDescription
--renormalizeForce re-normalization of files
--info-onlyOnly show files that need updating
--index-infoRead index info from stdin
--stdinRead file names from stdin
--verboseVerbose output
-q, --quietSuppress output
ParameterDescription
<pathspec>Files/directories to operate on
<mode>File permissions (octal)
<object>SHA-1 of object to add
Git Index (.git/index):
├── File Entries: Path, SHA-1, permissions, timestamps
├── Stage Information: Normal, ancestor, ours, theirs
├── Skip Worktree: Files ignored by worktree updates
├── Assume Unchanged: Files assumed unchanged
└── Resolve Undo: Conflict resolution information
Index Entry Format:
├── ctime: Change time (last metadata change)
├── mtime: Modify time (last content change)
├── dev/ino: Device/inode numbers
├── mode: File permissions
├── uid/gid: User/group IDs
├── size: File size
├── sha1: Object SHA-1 hash
└── path: File path
File States in Index:
├── Untracked: Not in index or repository
├── Unstaged: Modified but not in index
├── Staged: In index, ready for commit
├── Committed: In current commit
└── Ignored: Excluded by .gitignore
Terminal window
# Add new files to index
git update-index --add new-file.txt
# Add all files in directory
git update-index --add *.txt
# Add files with specific permissions
git update-index --add --chmod=+x script.sh
# Add files from stdin
echo "file1.txt" | git update-index --add --stdin
Terminal window
# Remove file from index
git update-index --remove old-file.txt
# Force remove modified file
git update-index --force-remove modified-file.txt
# Remove files matching pattern
git update-index --remove *.tmp
Terminal window
# Refresh stat information
git update-index --refresh
# Refresh all files including up-to-date ones
git update-index --really-refresh
# Refresh previously failed entries
git update-index --again
Terminal window
# Add executable permission
git update-index --chmod=+x script.sh
# Remove executable permission
git update-index --chmod=-x script.sh
# Set specific permissions
git update-index --mode=0644 file.txt
# Set executable permissions
git update-index --mode=0755 script.sh
Terminal window
# Mark files to skip worktree updates
git update-index --skip-worktree large-file.dat
# Unmark files for worktree updates
git update-index --no-skip-worktree large-file.dat
# List skip-worktree files
git ls-files -v | grep "^S"
# Check skip-worktree status
git ls-files --stage large-file.dat
Terminal window
# Mark files as unchanged (performance optimization)
git update-index --assume-unchanged config.local.php
# Unmark files as unchanged
git update-index --no-assume-unchanged config.local.php
# List assume-unchanged files
git ls-files -v | grep "^h"
# Check assume-unchanged status
git ls-files --stage config.local.php
Terminal window
# Add arbitrary entry to index
git update-index --cacheinfo 100644,abc123def,file.txt
# Add blob object to index
blob_sha=$(echo "content" | git hash-object -w --stdin)
git update-index --cacheinfo 100644,$blob_sha,new-file.txt
# Replace existing index entry
git update-index --cacheinfo 100644,newsha123,existing-file.txt
Terminal window
# Read index info from stdin
git update-index --index-info << EOF
100644 abc123... 0 file1.txt
100644 def456... 0 file2.txt
EOF
# Show files needing update
git update-index --info-only
# Verbose index operations
git update-index --verbose --add *.txt
Terminal window
# Mark files as unresolved (during merge)
git update-index --unresolve conflicted-file.txt
# Clear resolve-undo information
git update-index --clear-resolve-undo
# Check merge status
git ls-files --stage conflicted-file.txt
Terminal window
# Configure index behavior
git config core.filemode true # Track file permissions
git config core.ignorecase false # Case-sensitive file names
git config core.trustctime false # Don't trust ctime for changes
# Configure performance options
git config core.untrackedcache true # Cache untracked files
git config core.fsmonitor true # File system monitor
git config core.ignorestat true # Ignore stat changes
Terminal window
# Backup index before operations
cp .git/index .git/index.backup
# Validate operations
git update-index --dry-run --add new-files/
# Check index integrity
git fsck --full --strict
# Restore index if needed
cp .git/index.backup .git/index
Terminal window
# Enable untracked cache
git update-index --untracked-cache
# Test untracked cache
git update-index --test-untracked-cache
# Force untracked cache rebuild
git update-index --force-untracked-cache
# Disable untracked cache operations
git update-index --untracked-cache-no-op
Terminal window
# Mark files as fsmonitor valid
git update-index --fsmonitor-valid *.txt
# Unmark files as fsmonitor valid
git update-index --no-fsmonitor-valid *.txt
# Check fsmonitor status
git ls-files --stage | grep fsmonitor
#!/bin/bash
# Update-index in build workflows
prepare_build_artifacts() {
echo "Preparing build artifacts for index..."
# Add generated files to index
find build/ -name "*.min.js" -exec git update-index --add {} \;
# Set proper permissions
git update-index --chmod=+x build/scripts/*.sh
# Mark build artifacts as assume-unchanged
git update-index --assume-unchanged build/artifacts/*
echo "Build artifacts prepared"
}
# Clean build artifacts
clean_build_artifacts() {
echo "Cleaning build artifacts..."
# Remove build files from index
git update-index --force-remove build/artifacts/*
# Reset permissions
find build/ -name "*.sh" -exec git update-index --chmod=-x {} \;
echo "Build artifacts cleaned"
}
# Usage
prepare_build_artifacts
# ... build process ...
clean_build_artifacts
Terminal window
# Manage large files in index
optimize_large_repo() {
echo "Optimizing large repository index..."
# Find large files
git ls-files --stage | while read -r mode sha stage path; do
size=$(git cat-file -s "$sha" 2>/dev/null || echo "0")
if [ "$size" -gt 104857600 ]; then # > 100MB
echo "Marking large file as skip-worktree: $path"
git update-index --skip-worktree "$path"
fi
done
# Mark build artifacts as assume-unchanged
find . -name "*.jar" -o -name "*.war" | while read -r file; do
git update-index --assume-unchanged "$file" 2>/dev/null
done
echo "Large repository optimized"
}
# Restore full worktree
restore_worktree() {
echo "Restoring full worktree..."
# Unmark skip-worktree files
git ls-files -v | grep "^S" | cut -c3- | while read -r file; do
git update-index --no-skip-worktree "$file"
done
# Unmark assume-unchanged files
git ls-files -v | grep "^h" | cut -c3- | while read -r file; do
git update-index --no-assume-unchanged "$file"
done
echo "Worktree restored"
}
Terminal window
# Advanced selective staging
selective_staging() {
local pattern="$1"
echo "Performing selective staging for pattern: $pattern"
# Find files matching pattern
git ls-files --others --exclude-standard | grep "$pattern" | while read -r file; do
echo "Adding untracked file: $file"
git update-index --add "$file"
done
# Refresh modified files matching pattern
git ls-files | grep "$pattern" | while read -r file; do
if [ -n "$(git diff "$file")" ]; then
echo "Refreshing modified file: $file"
git update-index "$file"
fi
done
echo "Selective staging complete"
}
# Usage
selective_staging "\.java$"
Terminal window
# Check index integrity
git fsck --full --strict
# Rebuild index from HEAD
rm .git/index
git read-tree HEAD
# Recover from backup
cp .git/index.backup .git/index
# Reset index to HEAD
git reset --hard HEAD
Terminal window
# Fix permission inconsistencies
git ls-files --stage | while read -r mode sha stage path; do
if [ -f "$path" ]; then
actual_mode=$(stat -c%a "$path" 2>/dev/null || stat -f%p "$path" | cut -c4-6)
index_mode=$(printf "%o" $((mode & 0777)))
if [ "$actual_mode" != "$index_mode" ]; then
echo "Fixing permissions for: $path"
chmod "$index_mode" "$path"
fi
fi
done
# Refresh permissions in index
git update-index --refresh
Terminal window
# Resolve skip-worktree conflicts
git ls-files -v | grep "^S" | while read -r line; do
file=$(echo "$line" | cut -c3-)
if [ -n "$(git diff HEAD "$file")" ]; then
echo "Conflict detected for skip-worktree file: $file"
# Choose: keep worktree version or index version
git update-index "$file" # Update index to match worktree
# or: git checkout HEAD "$file" # Update worktree to match index
fi
done
# Clear all skip-worktree marks
git ls-files -v | grep "^S" | cut -c3- | xargs git update-index --no-skip-worktree
Terminal window
# Check for assume-unchanged conflicts
git ls-files -v | grep "^h" | while read -r line; do
file=$(echo "$line" | cut -c3-)
if [ -n "$(git diff "$file")" ]; then
echo "Assume-unchanged file has changes: $file"
git update-index --no-assume-unchanged "$file"
fi
done
# Reset assume-unchanged status
git ls-files -v | grep "^h" | cut -c3- | xargs git update-index --no-assume-unchanged
Terminal window
# Force index refresh
git update-index --really-refresh
# Clear stat cache
rm .git/index
git read-tree HEAD
# Handle filesystem timestamp issues
git config core.ignorestat true
git update-index --refresh
git config core.ignorestat false
Terminal window
# Handle large index files
git config core.untrackedcache false # Disable for large repos
git update-index --untracked-cache-no-op
# Optimize index operations
git config core.deltaBaseCacheLimit 2g
git config pack.threads 1
# Split large index operations
find . -name "*.txt" | head -100 | xargs git update-index --add
find . -name "*.txt" | tail -n +101 | xargs git update-index --add
#!/bin/bash
# Advanced staging workflows with update-index
intelligent_staging() {
echo "=== Intelligent Staging Workflow ==="
# Stage only modified configuration files
git ls-files | grep "config.*\.yml$" | while read -r file; do
if git diff --quiet "$file"; then
echo "No changes in: $file"
else
echo "Staging changes in: $file"
git update-index "$file"
fi
done
# Stage new documentation files
git ls-files --others --exclude-standard | grep "\.md$" | while read -r file; do
echo "Adding new documentation: $file"
git update-index --add "$file"
done
# Skip staging large binary files
git ls-files --others | while read -r file; do
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file")
if [ "$size" -gt 10485760 ]; then # > 10MB
echo "Skipping large file: $file"
continue
fi
fi
git update-index --add "$file"
done
echo "Intelligent staging complete"
}
# Selective unstaging
selective_unstaging() {
echo "=== Selective Unstaging ==="
# Unstage files larger than threshold
git diff --cached --name-only | while read -r file; do
size=$(git cat-file -s :"$file" 2>/dev/null || echo "0")
if [ "$size" -gt 5242880 ]; then # > 5MB
echo "Unstaging large file: $file"
git update-index --force-remove "$file"
fi
done
# Unstage generated files
git diff --cached --name-only | grep -E "\.(min\.js|min\.css)$" | while read -r file; do
echo "Unstaging generated file: $file"
git update-index --force-remove "$file"
done
echo "Selective unstaging complete"
}
# Usage
intelligent_staging
selective_unstaging
Terminal window
# Index integrity and consistency checks
index_integrity_check() {
echo "=== Index Integrity Check ==="
# Verify index matches working directory
git update-index --refresh --info-only | while read -r file; do
echo "File needs refresh: $file"
done
# Check for inconsistent file modes
git ls-files --stage | while read -r mode sha stage path; do
if [ -f "$path" ]; then
actual_mode=$(stat -c%a "$path" 2>/dev/null || echo "unknown")
index_mode=$(printf "%o" $((mode & 0777)))
if [ "$actual_mode" != "$index_mode" ] && [ "$actual_mode" != "unknown" ]; then
echo "Permission mismatch: $path (index: $index_mode, actual: $actual_mode)"
git update-index --mode="$actual_mode" "$path"
fi
fi
done
# Verify object existence
git ls-files --stage | while read -r mode sha stage path; do
if ! git cat-file -e "$sha" 2>/dev/null; then
echo "Missing object for: $path ($sha)"
git update-index --force-remove "$path"
fi
done
echo "Index integrity check complete"
}
# Index optimization
optimize_index() {
echo "=== Index Optimization ==="
# Enable performance features
git update-index --untracked-cache
git update-index --fsmonitor-valid
# Refresh and compact index
git update-index --really-refresh
# Remove unnecessary entries
git ls-files --others --exclude-standard | head -100 | xargs git update-index --add 2>/dev/null || true
echo "Index optimization complete"
}
# Usage
index_integrity_check
optimize_index
Terminal window
# Update-index in build pipelines
build_pipeline_integration() {
echo "=== Build Pipeline Integration ==="
# Prepare build environment
setup_build_index() {
echo "Setting up build index..."
# Mark source files as assume-unchanged during build
find src/ -name "*.ts" -o -name "*.js" | xargs git update-index --assume-unchanged 2>/dev/null || true
# Add build outputs
mkdir -p dist/
echo "Build output placeholder" > dist/.gitkeep
git update-index --add dist/.gitkeep
echo "Build index setup complete"
}
# Update index after build
update_build_index() {
echo "Updating index after build..."
# Unmark source files
find src/ -name "*.ts" -o -name "*.js" | xargs git update-index --no-assume-unchanged 2>/dev/null || true
# Add build artifacts
find dist/ -type f -not -name ".gitkeep" | while read -r file; do
git update-index --add "$file" 2>/dev/null || true
done
# Set proper permissions on executables
find dist/ -name "*.sh" -o -name "*.exe" | xargs git update-index --chmod=+x 2>/dev/null || true
echo "Build index updated"
}
# Clean build artifacts from index
clean_build_index() {
echo "Cleaning build artifacts from index..."
# Remove build files
git ls-files dist/ | xargs git update-index --force-remove 2>/dev/null || true
# Keep placeholder
git update-index --add dist/.gitkeep 2>/dev/null || true
echo "Build index cleaned"
}
# Run pipeline steps
setup_build_index
echo "Building application..."
# ... actual build commands ...
update_build_index
echo "Build pipeline complete"
}
# Usage
build_pipeline_integration
Terminal window
# Update-index for monorepo workflows
monorepo_index_management() {
echo "=== Monorepo Index Management ==="
# Manage team-specific index states
team_index_workflow() {
local team="$1"
echo "Managing index for team: $team"
# Create team-specific index snapshot
git ls-files --stage > "team-$team-index.txt"
# Mark team files as assume-unchanged for other teams
find "teams/$team/" -type f | while read -r file; do
if git ls-files --error-unmatch "$file" >/dev/null 2>&1; then
git update-index --assume-unchanged "$file"
fi
done
echo "Team index configured"
}
# Selective operations by directory
selective_directory_ops() {
local operation="$1"
local directory="$2"
echo "Performing $operation on directory: $directory"
case "$operation" in
"add")
find "$directory" -type f | while read -r file; do
git update-index --add "$file" 2>/dev/null || true
done
;;
"remove")
git ls-files "$directory" | xargs git update-index --force-remove 2>/dev/null || true
;;
"refresh")
git ls-files "$directory" | xargs git update-index --refresh 2>/dev/null || true
;;
esac
echo "Directory operation complete"
}
# Index performance monitoring
monitor_index_performance() {
echo "=== Index Performance Monitoring ==="
# Measure index operations
start_time=$(date +%s.%3N)
git update-index --refresh >/dev/null 2>&1
end_time=$(date +%s.%3N)
refresh_time=$(echo "$end_time - $start_time" | bc)
echo "Index refresh time: ${refresh_time}s"
# Check index size
index_size=$(stat -f%z .git/index 2>/dev/null || stat -c%s .git/index)
echo "Index file size: $index_size bytes"
# Count index entries
entry_count=$(git ls-files | wc -l)
echo "Index entries: $entry_count"
# Performance recommendations
if [ "$entry_count" -gt 100000 ]; then
echo "Consider enabling untracked cache: git update-index --untracked-cache"
fi
if (( $(echo "$refresh_time > 10" | bc -l) )); then
echo "Consider enabling fsmonitor: git config core.fsmonitor true"
fi
}
# Interactive monorepo management
echo "Monorepo Index Management Options:"
echo "1. Configure team index"
echo "2. Selective directory operations"
echo "3. Monitor index performance"
read -p "Select option (1-3): " option
case "$option" in
1)
read -p "Team name: " team
team_index_workflow "$team"
;;
2)
read -p "Operation (add/remove/refresh): " op
read -p "Directory: " dir
selective_directory_ops "$op" "$dir"
;;
3)
monitor_index_performance
;;
*) echo "Invalid option" ;;
esac
}
# Usage
monorepo_index_management