Skip to content

mv Git Command Guide

The git mv command moves or renames files, directories, or symlinks in the working directory and updates the Git index to reflect the changes. It combines the functionality of Unix mv with Git index management.

Terminal window
git mv [-v] [-f] [-n] [-k] <source> <destination>
git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>
OptionDescription
-v, --verboseReport renamed files
-f, --forceOverwrite destination if it exists
-n, --dry-runShow what would be done without doing it
-k, --skip-errorsSkip rename errors and continue
ParameterDescription
<source>File, directory, or symlink to move/rename
<destination>New name/path for the item
<destination-directory>Directory to move sources into
git mv combines two operations:
1. Unix mv: Move/rename in working directory
2. Git add/rm: Update index to reflect changes
Equivalent to:
git rm <source>
mv <source> <destination>
git add <destination>
Terminal window
# Rename (same directory)
git mv old-name.txt new-name.txt
# Move (different directory)
git mv file.txt subdir/file.txt
# Move multiple files
git mv file1.txt file2.txt docs/
Terminal window
# Rename a single file
git mv old-file.txt new-file.txt
# Rename with verbose output
git mv -v README.md README.rst
# Rename multiple files to new directory
git mv script.py test.py bin/
Terminal window
# Move file to subdirectory
git mv config.yml config/settings.yml
# Move directory
git mv old-package new-package
# Move multiple items to directory
git mv file1.txt file2.txt docs/
Terminal window
# Force overwrite existing destination
git mv -f new-file.txt existing-file.txt
# Force move read-only files
git mv -f readonly-file.txt destination/
Terminal window
# Preview what would be moved
git mv -n old-name new-name
# Check multiple file moves
git mv -n *.log logs/
#!/bin/bash
# Organize project files by type
organize_project() {
echo "Organizing project files..."
# Create directories if they don't exist
mkdir -p src include docs tests scripts
# Move source files
git mv -v *.c *.cpp *.h src/ 2>/dev/null || true
git mv -v include/*.h include/ 2>/dev/null || true
# Move documentation
git mv -v *.md *.rst *.txt docs/ 2>/dev/null || true
# Move test files
git mv -v test_*.py test-*.js tests/ 2>/dev/null || true
# Move scripts
git mv -v *.sh *.py scripts/ 2>/dev/null || true
echo "File organization complete"
git status --porcelain
}
organize_project
Terminal window
# Refactor package structure
refactor_structure() {
echo "Refactoring directory structure..."
# Create new structure
mkdir -p src/core src/utils src/api tests/unit tests/integration
# Move core modules
git mv lib/core/* src/core/
git mv lib/utils/* src/utils/
# Move API files
git mv api/* src/api/
# Move tests
git mv tests/unit/* tests/unit/
git mv tests/integration/* tests/integration/
# Remove empty directories
find . -type d -empty -delete
echo "Structure refactoring complete"
git status
}
refactor_structure
Terminal window
# Safe file operations with backup
safe_move() {
local source="$1"
local destination="$2"
# Check if source exists
if [ ! -e "$source" ]; then
echo "Error: Source '$source' does not exist"
return 1
fi
# Create backup if destination exists
if [ -e "$destination" ]; then
cp "$destination" "${destination}.backup"
echo "Created backup: ${destination}.backup"
fi
# Perform move
if git mv "$source" "$destination"; then
echo "Successfully moved '$source' to '$destination'"
else
echo "Failed to move '$source'"
# Restore backup if it exists
[ -e "${destination}.backup" ] && mv "${destination}.backup" "$destination"
return 1
fi
}
# Usage
safe_move "important-file.txt" "archive/important-file.txt"
#!/bin/bash
# Complete code refactoring workflow
refactor_component() {
local old_component="$1"
local new_component="$2"
echo "Refactoring component: $old_component -> $new_component"
# Rename main file
git mv "${old_component}.py" "${new_component}.py"
# Rename test file
git mv "test_${old_component}.py" "test_${new_component}.py"
# Update imports in all Python files
find . -name "*.py" -exec sed -i "s/from $old_component import/from $new_component import/g" {} \;
find . -name "*.py" -exec sed -i "s/import $old_component/import $new_component/g" {} \;
# Update documentation
sed -i "s/$old_component/$new_component/g" README.md
# Stage all changes
git add .
echo "Component refactoring complete"
echo "Review changes with: git diff --cached"
}
# Usage
refactor_component "old_module" "new_module"
Terminal window
# Manage project assets
organize_assets() {
echo "Organizing project assets..."
# Create asset directories
mkdir -p assets/images assets/fonts assets/audio assets/video
# Move image files
git mv *.png *.jpg *.jpeg *.gif *.svg assets/images/ 2>/dev/null || true
# Move font files
git mv *.ttf *.woff *.woff2 assets/fonts/ 2>/dev/null || true
# Move audio files
git mv *.mp3 *.wav *.ogg assets/audio/ 2>/dev/null || true
# Move video files
git mv *.mp4 *.avi *.mov assets/video/ 2>/dev/null || true
echo "Asset organization complete"
git status --short
}
organize_assets
Terminal window
# Manage configuration files
manage_configs() {
echo "Managing configuration files..."
# Create config directory
mkdir -p config
# Move configuration files
git mv *.config *.cfg *.ini *.yaml *.yml config/ 2>/dev/null || true
# Move environment files
git mv .env* config/ 2>/dev/null || true
# Create .gitignore for sensitive configs
cat >> config/.gitignore << EOF
*.local
*.secret
*password*
EOF
git add config/.gitignore
echo "Configuration management complete"
}
manage_configs
Terminal window
# Configure mv behavior
git config core.ignorecase false # Case-sensitive renames
# Set up aliases for common operations
git config alias.mv 'mv -v' # Always verbose
git config alias.rename 'mv' # Alias for rename operations
Terminal window
# Handle case-sensitive renames
git mv oldName newName # Works on case-sensitive filesystems
# Handle symlinks
git mv symlink.txt new-symlink.txt
# Handle directories with content
git mv old-dir/ new-dir/
# Handle files with special characters
git mv "file with spaces.txt" "renamed file.txt"
Terminal window
# Batch operations for performance
batch_rename() {
local pattern="$1"
local replacement="$2"
# Find files matching pattern
find . -name "*$pattern*" -type f | while read file; do
new_name=$(echo "$file" | sed "s/$pattern/$replacement/g")
mkdir -p "$(dirname "$new_name")"
git mv "$file" "$new_name"
done
}
# Usage
batch_rename "_old" "_new"
Terminal window
# Check if file exists
ls -la file-to-move.txt
# Check Git status
git status --porcelain | grep file-to-move.txt
# Check if file is ignored
git check-ignore file-to-move.txt
Terminal window
# Check file permissions
ls -la file.txt
# Fix permissions
chmod 644 file.txt
# Handle read-only files
chmod u+w file.txt
git mv file.txt destination/
Terminal window
# Check filesystem case sensitivity
touch test.txt
mv test.txt TEST.txt 2>/dev/null && echo "Case-insensitive" || echo "Case-sensitive"
# Handle case-insensitive filesystems
git mv oldname.txt newname.txt # May not work on case-insensitive FS
Terminal window
# Check if destination directory exists
ls -la destination/
# Create destination if needed
mkdir -p destination/
git mv source/ destination/
# Handle nested directories
git mv -k source/ destination/ # Skip errors
Terminal window
# Check index status
git status
# Reset index if needed
git reset HEAD file.txt
git mv file.txt new-location/
# Handle staged changes
git stash
git mv file.txt new-location/
git stash pop
#!/bin/bash
# Complete project restructuring
restructure_project() {
echo "Restructuring project layout..."
# Create new directory structure
mkdir -p src/main src/test src/docs scripts tools
# Move source files
git mv *.java src/main/ 2>/dev/null || true
git mv src/*.java src/main/ 2>/dev/null || true
# Move test files
git mv *Test.java src/test/ 2>/dev/null || true
git mv test/*.java src/test/ 2>/dev/null || true
# Move documentation
git mv *.md src/docs/ 2>/dev/null || true
git mv docs/* src/docs/ 2>/dev/null || true
# Move build scripts
git mv build.sh scripts/ 2>/dev/null || true
git mv *.gradle scripts/ 2>/dev/null || true
# Move tools and utilities
git mv tools/* tools/ 2>/dev/null || true
git mv utils/* tools/ 2>/dev/null || true
# Clean up empty directories
find . -type d -empty -delete
echo "Project restructuring complete"
echo "Review changes: git status"
echo "Commit when ready: git commit -m 'Restructure project layout'"
}
restructure_project
Terminal window
# Extract component to separate directory
extract_component() {
local component_name="$1"
local target_dir="$2"
echo "Extracting component: $component_name"
# Create component directory
mkdir -p "$target_dir"
# Find component files
find . -name "*$component_name*" -type f | while read file; do
# Calculate relative path
rel_path="${file#./}"
target_path="$target_dir/$rel_path"
# Create target directory
mkdir -p "$(dirname "$target_path")"
# Move file
git mv "$file" "$target_path"
done
echo "Component extraction complete"
echo "Component files moved to: $target_dir"
}
# Usage
extract_component "auth" "components/authentication"
Terminal window
# Automated file organization by type
auto_organize() {
echo "Auto-organizing project files..."
# Define file type mappings
declare -A file_types=(
["*.py"]="src/"
["*.js"]="src/"
["*.ts"]="src/"
["*.java"]="src/"
["*.c"]="src/"
["*.cpp"]="src/"
["*.h"]="include/"
["*.hpp"]="include/"
["*.md"]="docs/"
["*.txt"]="docs/"
["*.rst"]="docs/"
["*.html"]="docs/"
["*.css"]="assets/css/"
["*.scss"]="assets/scss/"
["*.js"]="assets/js/"
["*.png"]="assets/images/"
["*.jpg"]="assets/images/"
["*.svg"]="assets/images/"
["*.ttf"]="assets/fonts/"
["*.woff"]="assets/fonts/"
["test_*.py"]="tests/"
["*Test.java"]="tests/"
["*.spec.js"]="tests/"
["*.sh"]="scripts/"
["Makefile"]="scripts/"
)
# Process each file type
for pattern in "${!file_types[@]}"; do
target_dir="${file_types[$pattern]}"
mkdir -p "$target_dir"
# Move matching files
git mv $pattern "$target_dir" 2>/dev/null || true
done
echo "Auto-organization complete"
git status --short
}
auto_organize

What’s the difference between git mv and regular mv?

Section titled “What’s the difference between git mv and regular mv?”

git mv moves files in working directory and updates Git index automatically; regular mv only affects working directory, requiring separate git add/rm commands.

Yes, git mv can move entire directories and their contents recursively, updating the index for all moved files.

Working directory changes are reverted, index remains unchanged. No partial moves occur - operation is atomic.

Use -f/—force flag to overwrite existing destination files. Without force, git mv refuses to overwrite.

Use -n/—dry-run to show what would be moved without actually performing the operation.

No, git mv only works on files tracked by Git. Use regular mv for untracked files, then git add.

What’s the impact of git mv on Git history?

Section titled “What’s the impact of git mv on Git history?”

File moves are tracked in Git history. git log —follow shows file history across renames and moves.

No, git mv operates on current working directory and index. File moves must be committed before affecting other branches.

Use git reset HEAD to unstage the move, then git checkout to restore original location.

Yes, git mv properly handles symbolic links, preserving link targets and updating index appropriately.

What’s the performance impact of git mv on large directories?

Section titled “What’s the performance impact of git mv on large directories?”

Similar to regular mv for working directory, plus index update overhead. Use git mv -k to skip errors and continue with large operations.

Use -n for dry runs, check exit codes, and use -k to continue on errors. Always verify operations with git status.

Yes, git mv works normally with LFS-tracked files. LFS handles the large file content separately from Git operations.

What’s the relationship between git mv and git rm/git add?

Section titled “What’s the relationship between git mv and git rm/git add?”

git mv is equivalent to: git rm && mv && git add

How do I handle encoding issues with git mv?

Section titled “How do I handle encoding issues with git mv?”

git mv preserves file content and encoding. Use consistent encoding across repository to avoid issues.

No, requires working directory for file operations. Use in non-bare repositories only.

What’s the difference between git mv and git mv —force?

Section titled “What’s the difference between git mv and git mv —force?”

—force allows overwriting existing destination files; normal git mv refuses to overwrite.

How do I handle git mv with merge conflicts?

Section titled “How do I handle git mv with merge conflicts?”

Resolve conflicts first, then use git mv. Avoid moving conflicted files until conflicts are resolved.

  1. Code Refactoring: Rename classes, modules, and functions while preserving Git history
  2. Project Restructuring: Reorganize directory layouts and file hierarchies
  3. Asset Management: Organize media files, documentation, and project resources
  4. Configuration Management: Move configuration files to dedicated directories
  5. Component Extraction: Move related files into separate component directories
  6. Build System Organization: Restructure build scripts and configuration files