replay Git Command Guide
The git replay command (EXPERIMENTAL) takes ranges of commits and replays them onto a new location. It leaves the working tree and index untouched, and outputs commands suitable for git update-ref —stdin to update references.
git replay Syntax:
Section titled “git replay Syntax:”git replay ([--contained] --onto <newbase> | --advance <branch>) <revision-range>...Replay Modes:
Section titled “Replay Modes:”| Option | Description |
|---|---|
--onto <newbase> | Replay onto new base commit |
--advance <branch> | Advance specific branch |
--contained | Include only fully contained branches |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<newbase> | New base commit for replay |
<branch> | Branch to advance |
<revision-range> | Commit ranges to replay |
Understanding Commit Replay:
Section titled “Understanding Commit Replay:”Experimental Nature:
Section titled “Experimental Nature:”⚠️ EXPERIMENTAL COMMAND ⚠️├── Behavior may change in future versions├── Not recommended for production use├── Requires careful testing and validation├── Best used by experienced Git users└── Always backup repositories before use
When to Use Replay:├── Repository restructuring without rebase├── Bare repository operations├── Complex branch reorganizations├── Automated repository surgery└── Advanced Git workflow automationReplay Process:
Section titled “Replay Process:”Replay Workflow:1. Analyze revision ranges to replay2. Create new commits on target base3. Preserve commit metadata (author, date, message)4. Generate update-ref commands for output5. Leave working tree and index unchanged6. Require manual application of changes
Output Format:├── Commands for git update-ref --stdin├── Reference updates for replayed branches├── Preserves branch relationships└── Safe for manual review before applicationComparison with Rebase:
Section titled “Comparison with Rebase:”Replay vs Rebase:├── git replay: Works with bare repos, outputs commands├── git rebase: Interactive, modifies working tree├── git replay: Batch operations, no working tree changes├── git rebase: Single branch operations├── git replay: Multiple branch updates└── git rebase: Immediate reference updatesBasic Replay Operations:
Section titled “Basic Replay Operations:”Replay onto New Base:
Section titled “Replay onto New Base:”# Replay commits onto new basegit replay --onto <new-base> <revision-range>
# Replay feature branch onto maingit replay --onto main feature-branch
# Replay multiple rangesgit replay --onto main branch1 branch2 branch3
# Replay with contained branchesgit replay --contained --onto main feature-branchAdvance Branch:
Section titled “Advance Branch:”# Advance branch to new locationgit replay --advance <branch> <revision-range>
# Advance main branchgit replay --advance main upstream/main
# Advance with multiple rangesgit replay --advance develop feature-a feature-bOutput Handling:
Section titled “Output Handling:”# Capture replay outputgit replay --onto main feature > replay-commands.txt
# Review commands before applyingcat replay-commands.txt
# Apply changesgit update-ref --stdin < replay-commands.txt
# Verify changesgit log --oneline --graph --allAdvanced Replay Scenarios:
Section titled “Advanced Replay Scenarios:”Repository Restructuring:
Section titled “Repository Restructuring:”# Restructure repository with replayrestructure_repo() { local new_base="$1" local branches_to_replay="$2"
echo "Restructuring repository onto $new_base"
# Generate replay commands replay_commands=$(git replay --onto "$new_base" $branches_to_replay)
# Review changes echo "Proposed changes:" echo "$replay_commands"
# Apply with confirmation read -p "Apply these changes? (y/N): " confirm if [[ "$confirm" == "y" ]]; then echo "$replay_commands" | git update-ref --stdin echo "Repository restructured" else echo "Changes not applied" fi}
restructure_repo "new-foundation" "feature-a feature-b feature-c"Bare Repository Operations:
Section titled “Bare Repository Operations:”# Work with bare repositoriesbare_repo_replay() { local bare_repo="$1" local new_base="$2" local branches="$3"
echo "Replaying in bare repository: $bare_repo"
# Execute in bare repo context GIT_DIR="$bare_repo" git replay --onto "$new_base" $branches > commands.txt
# Apply changes GIT_DIR="$bare_repo" git update-ref --stdin < commands.txt
echo "Bare repository replay complete"}
bare_repo_replay "/path/to/bare.git" "main" "develop feature"Batch Branch Updates:
Section titled “Batch Branch Updates:”# Update multiple branches at oncebatch_branch_update() { local new_base="$1" shift local branches=("$@")
echo "Batch updating branches onto $new_base"
# Generate combined replay all_commands="" for branch in "${branches[@]}"; do branch_commands=$(git replay --onto "$new_base" "$branch") all_commands="${all_commands}${branch_commands}" done
# Apply all at once echo "$all_commands" | git update-ref --stdin
echo "Batch update complete"}
batch_branch_update "main" "feature-a" "feature-b" "bugfix-123"Configuration and Best Practices:
Section titled “Configuration and Best Practices:”Git Configuration for Replay:
Section titled “Git Configuration for Replay:”# Configure replay behavior (experimental)git config replay.experimental true
# Configure update-ref safetygit config core.logAllRefUpdates true
# Configure reflog for safetygit config core.logAllRefUpdates trueSafe Replay Practices:
Section titled “Safe Replay Practices:”# Always backup before replay operationsgit branch backup-before-replaygit tag backup-$(date +%Y%m%d-%H%M%S)
# Test replay commands before applyinggit replay --onto <base> <range> | head -10
# Verify replay resultsgit log --oneline --graph --all | head -20
# Use dry-run mentality# Review all commands before piping to update-ref
# Document replay operationsecho "$(date): Replayed $ranges onto $base" >> .git/REPLAY_LOGValidation and Testing:
Section titled “Validation and Testing:”# Validate replay resultsvalidate_replay() { local original_refs="$1" local replay_commands="$2"
echo "Validating replay commands..."
# Check command syntax echo "$replay_commands" | while read -r line; do if [[ "$line" == update\ refs/* ]]; then # Valid update-ref command continue else echo "Invalid command: $line" return 1 fi done
# Check reference existence echo "$replay_commands" | grep "update refs/" | cut -d' ' -f2 | while read -r ref; do if ! git show-ref --verify --quiet "$ref" 2>/dev/null; then echo "Warning: Reference $ref does not exist" fi done
echo "Validation complete"}
validate_replay "original-refs.txt" "$(cat replay-commands.txt)"Integration with Development Workflows:
Section titled “Integration with Development Workflows:”Automated Repository Surgery:
Section titled “Automated Repository Surgery:”#!/bin/bash# Automated repository surgery with replay
automated_surgery() { local surgery_type="$1" local target_branch="$2"
echo "Performing automated surgery: $surgery_type on $target_branch"
case "$surgery_type" in "branch-rebase") # Rebase branch without changing working tree replay_commands=$(git replay --onto main "$target_branch") echo "$replay_commands" | git update-ref --stdin echo "Branch rebased without working tree changes" ;;
"merge-squash") # Squash merge multiple branches temp_base=$(git commit-tree -m "Temporary base" main^{tree}) replay_commands=$(git replay --onto "$temp_base" branch1 branch2 branch3) echo "$replay_commands" | git update-ref --stdin echo "Branches squashed" ;;
"history-rewrite") # Rewrite history without rebase new_base=$(git commit-tree -m "New history start" main^{tree}) replay_commands=$(git replay --onto "$new_base" --contained "$target_branch") echo "$replay_commands" | git update-ref --stdin echo "History rewritten" ;; esac}
automated_surgery "branch-rebase" "feature/complex"CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# CI/CD pipeline with replayci_replay_integration() { echo "CI/CD replay integration"
# Get branches to replay branches_to_replay=$(git for-each-ref --format='%(refname:short)' refs/heads/feature/*)
# Replay onto main replay_commands=$(git replay --onto main $branches_to_replay)
# Validate commands if validate_replay_commands "$replay_commands"; then # Apply in CI echo "$replay_commands" | git update-ref --stdin
# Run tests on replayed branches for branch in $branches_to_replay; do git checkout "$branch" run-tests.sh || exit 1 done
echo "CI replay integration successful" else echo "Replay validation failed" exit 1 fi}
ci_replay_integrationRepository Migration Aid:
Section titled “Repository Migration Aid:”# Aid repository migration with replaymigration_replay() { local source_repo="$1" local target_repo="$2"
echo "Aiding migration from $source_repo to $target_repo"
# Get branches from source source_branches=$(GIT_DIR="$source_repo" git for-each-ref --format='%(refname:short)' refs/heads/)
# Replay branches in target for branch in $source_branches; do echo "Replaying $branch..."
# Create replay commands replay_commands=$(GIT_DIR="$target_repo" git replay --onto main "$branch")
# Apply in target repo echo "$replay_commands" | GIT_DIR="$target_repo" git update-ref --stdin done
echo "Migration replay complete"}
migration_replay "/source/repo.git" "/target/repo.git"Troubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Invalid Revision Ranges:
Section titled “Invalid Revision Ranges:”# Fix revision range issuesdebug_revision_ranges() { local ranges="$1"
echo "Debugging revision ranges: $ranges"
# Check range validity for range in $ranges; do if ! git rev-parse --verify "$range" >/dev/null 2>&1; then echo "Invalid range: $range"
# Try to find valid alternatives git branch -a | grep "$range" git tag | grep "$range" fi done
# Test replay command if git replay --onto main $ranges >/dev/null 2>&1; then echo "Ranges are valid" else echo "Ranges validation failed" fi}
debug_revision_ranges "feature-a feature-b"Update-Ref Command Issues:
Section titled “Update-Ref Command Issues:”# Handle update-ref command problemsfix_update_ref_issues() { local commands_file="$1"
echo "Fixing update-ref command issues"
# Validate command format while read -r line; do if [[ "$line" =~ ^update\ refs/[^[:space:]]+\ [a-f0-9]{40}\ [a-f0-9]{40}$ ]]; then echo "Valid command: $line" else echo "Invalid command format: $line" return 1 fi done < "$commands_file"
# Check reference locks git update-ref --stdin < "$commands_file" 2>&1 | grep -i error
echo "Update-ref validation complete"}
fix_update_ref_issues "replay-commands.txt"Bare Repository Issues:
Section titled “Bare Repository Issues:”# Handle bare repository problemsfix_bare_repo_issues() { local repo_path="$1"
echo "Fixing bare repository issues: $repo_path"
# Verify it's bare if [ ! -f "$repo_path/HEAD" ] || ! grep -q "bare = true" "$repo_path/config" 2>/dev/null; then echo "Not a bare repository: $repo_path" return 1 fi
# Check permissions if [ ! -w "$repo_path" ]; then echo "No write permission for repository" return 1 fi
# Test replay capability GIT_DIR="$repo_path" git replay --help >/dev/null 2>&1 || { echo "Replay command not available in this Git version" return 1 }
echo "Bare repository ready for replay"}
fix_bare_repo_issues "/path/to/bare.git"Performance Issues:
Section titled “Performance Issues:”# Optimize replay performanceoptimize_replay_performance() { echo "Optimizing replay performance"
# Use contained mode when possible git replay --contained --onto main large-range
# Process in smaller batches # Instead of: git replay --onto main branch1 branch2 branch3 # Use separate calls for large operations
# Clean repository before replay git gc --quiet git repack -a -d
# Monitor memory usage /usr/bin/time -v git replay --onto main large-branch
echo "Performance optimization complete"}
optimize_replay_performanceRecovery from Failed Replay:
Section titled “Recovery from Failed Replay:”# Recover from failed replay operationsrecover_failed_replay() { echo "Recovering from failed replay"
# Check reflog for recovery git reflog --all | head -20
# Restore from backup if git show-ref --verify --quiet refs/heads/backup-before-replay; then git reset --hard backup-before-replay echo "Restored from backup" fi
# Clean up partial changes git update-ref --stdin << EOFdelete refs/heads/partial-replayEOF
# Verify repository integrity git fsck --full
echo "Recovery complete"}
recover_failed_replayReal-World Usage Examples:
Section titled “Real-World Usage Examples:”Repository Branch Consolidation:
Section titled “Repository Branch Consolidation:”#!/bin/bash# Consolidate repository branches with replay
consolidate_branches() { local target_branch="$1" local branches_to_consolidate="$2"
echo "Consolidating branches into $target_branch"
# Create consolidation base consolidation_base=$(git commit-tree -m "Branch consolidation base" -p "$target_branch" "$target_branch^{tree}")
# Replay branches onto consolidation base replay_commands=$(git replay --onto "$consolidation_base" $branches_to_consolidate)
# Review consolidation echo "Consolidation commands:" echo "$replay_commands"
# Apply consolidation echo "$replay_commands" | git update-ref --stdin
# Update target branch git update-ref "$target_branch" "$consolidation_base"
echo "Branch consolidation complete"}
consolidate_branches "main" "feature-a feature-b feature-c"Automated Release Branching:
Section titled “Automated Release Branching:”# Automated release branching with replayautomated_release_branching() { local release_version="$1" local source_branches="$2"
echo "Creating release $release_version from branches: $source_branches"
# Create release base release_base=$(git commit-tree -m "Release $release_version base" main^{tree})
# Replay source branches onto release base replay_commands=$(git replay --onto "$release_base" $source_branches)
# Create release branch git update-ref "refs/heads/release/$release_version" "$release_base"
# Apply branch updates echo "$replay_commands" | git update-ref --stdin
# Tag release git tag -a "v$release_version" "release/$release_version" -m "Release version $release_version"
echo "Release $release_version created"}
automated_release_branching "2.1.0" "feature-x feature-y"Repository Surgery for History Cleanup:
Section titled “Repository Surgery for History Cleanup:”# Repository surgery for history cleanuphistory_cleanup_surgery() { local bad_commits="$1" local cleanup_reason="$2"
echo "Performing history cleanup surgery: $cleanup_reason"
# Find commits to remove commits_to_remove="" for bad_commit in $bad_commits; do if git cat-file -t "$bad_commit" >/dev/null 2>&1; then commits_to_remove="$commits_to_remove $bad_commit" fi done
if [ -z "$commits_to_remove" ]; then echo "No valid commits to remove" return 1 fi
# Create new history without bad commits # This is complex and requires careful analysis echo "Analyzing commit relationships..."
# For each affected branch, replay without bad commits affected_branches=$(git for-each-ref --contains="$bad_commits" --format='%(refname:short)' refs/heads/)
for branch in $affected_branches; do echo "Processing branch: $branch"
# Find good base (last good commit) branch_commits=$(git rev-list "$branch") good_base=""
for commit in $branch_commits; do if [[ ! " $bad_commits " =~ " $commit " ]]; then good_base="$commit" break fi done
if [ -n "$good_base" ]; then # Replay branch from good base replay_commands=$(git replay --onto "$good_base" "$branch") echo "$replay_commands" | git update-ref --stdin echo "Branch $branch cleaned" fi done
echo "History cleanup surgery complete"}
history_cleanup_surgery "bad123 bad456" "Remove sensitive data"Complex Repository Restructuring:
Section titled “Complex Repository Restructuring:”# Complex repository restructuringcomplex_restructure() { local restructure_plan="$1"
echo "Performing complex repository restructuring"
# Parse restructure plan (simplified example) # Plan format: "source-branch -> target-base" while IFS=' -> ' read -r source target; do echo "Restructuring $source onto $target"
# Validate targets exist if ! git rev-parse --verify "$target" >/dev/null 2>&1; then echo "Target $target does not exist" continue fi
# Perform replay replay_commands=$(git replay --onto "$target" "$source")
# Apply changes echo "$replay_commands" | git update-ref --stdin
echo "Restructured $source onto $target" done < "$restructure_plan"
echo "Complex restructuring complete"}
# Create restructure plancat > restructure-plan.txt << EOFfeature-a -> mainfeature-b -> developbugfix-123 -> release/v1.0EOF
complex_restructure "restructure-plan.txt"Disaster Recovery with Replay:
Section titled “Disaster Recovery with Replay:”# Disaster recovery using replaydisaster_recovery() { local backup_repo="$1" local recovery_branches="$2"
echo "Performing disaster recovery with replay"
# Validate backup repository if [ ! -d "$backup_repo" ]; then echo "Backup repository not found: $backup_repo" return 1 fi
# Get current state current_refs=$(git for-each-ref --format='%(refname) %(objectname)')
# Replay from backup for branch in $recovery_branches; do echo "Recovering branch: $branch"
# Get branch from backup backup_commit=$(GIT_DIR="$backup_repo" git rev-parse --verify "$branch" 2>/dev/null)
if [ -n "$backup_commit" ]; then # Replay branch from backup replay_commands=$(git replay --onto "$backup_commit" "$branch" 2>/dev/null || echo "")
if [ -n "$replay_commands" ]; then echo "$replay_commands" | git update-ref --stdin echo "Branch $branch recovered" else echo "Could not replay branch $branch" fi else echo "Branch $branch not found in backup" fi done
# Verify recovery git fsck --full
echo "Disaster recovery complete"}
disaster_recovery "/path/to/backup.git" "main develop"Automated Repository Synchronization:
Section titled “Automated Repository Synchronization:”# Automated repository synchronizationrepo_sync_replay() { local source_repo="$1" local target_repo="$2" local sync_branches="$3"
echo "Synchronizing repositories with replay"
# Get branches to sync for branch in $sync_branches; do echo "Syncing branch: $branch"
# Get source commit source_commit=$(GIT_DIR="$source_repo" git rev-parse --verify "$branch" 2>/dev/null)
if [ -n "$source_commit" ]; then # Check if target needs update target_commit=$(GIT_DIR="$target_repo" git rev-parse --verify "$branch" 2>/dev/null || echo "")
if [ "$source_commit" != "$target_commit" ]; then # Replay branch in target replay_commands=$(GIT_DIR="$target_repo" git replay --onto "$source_commit" "$branch" 2>/dev/null || echo "")
if [ -n "$replay_commands" ]; then echo "$replay_commands" | GIT_DIR="$target_repo" git update-ref --stdin echo "Branch $branch synchronized" fi else echo "Branch $branch already in sync" fi else echo "Branch $branch not found in source" fi done
echo "Repository synchronization complete"}
repo_sync_replay "/source/repo.git" "/target/repo.git" "main develop feature"What’s the difference between replay and rebase?
Section titled “What’s the difference between replay and rebase?”replay works with bare repositories and outputs update-ref commands; rebase modifies the working tree directly. replay is designed for batch operations and repository surgery.
Can replay work with bare repositories?
Section titled “Can replay work with bare repositories?”Yes, replay is specifically designed to work with bare repositories, unlike rebase which requires a working tree.
How do I apply replay output?
Section titled “How do I apply replay output?”Pipe the output to git update-ref —stdin: git replay —onto
Is replay safe to use?
Section titled “Is replay safe to use?”Replay is experimental - always backup repositories and test commands before applying. The behavior may change in future Git versions.
What’s the —contained option for?
Section titled “What’s the —contained option for?”—contained includes only branches that are fully contained within the specified revision range, avoiding partial updates.
Can replay update multiple branches at once?
Section titled “Can replay update multiple branches at once?”Yes, specify multiple revision ranges and replay will generate update commands for all affected branches.
How do I preview replay changes?
Section titled “How do I preview replay changes?”Run replay without applying output, then review the generated update-ref commands before piping to git update-ref —stdin.
Does replay modify the working tree?
Section titled “Does replay modify the working tree?”No, replay leaves the working tree and index untouched, only generating reference update commands.
Can replay work across repositories?
Section titled “Can replay work across repositories?”Replay works within a single repository. For cross-repository operations, use fetch/push or manual object copying.
What’s the difference between —onto and —advance?
Section titled “What’s the difference between —onto and —advance?”—onto replays onto any commit; —advance specifically advances a named branch to new commits.
How do I recover from failed replay?
Section titled “How do I recover from failed replay?”Check reflog for recovery points, restore from backup branches/tags, or use git fsck to verify repository integrity.
Can replay handle merge commits?
Section titled “Can replay handle merge commits?”Yes, replay preserves merge commit structure and parent relationships during replay operations.
What’s the performance impact of replay?
Section titled “What’s the performance impact of replay?”Replay can be intensive for large repositories with many branches. Use —contained and limit ranges for better performance.
Can replay be used in CI/CD pipelines?
Section titled “Can replay be used in CI/CD pipelines?”Yes, but with caution due to experimental nature. Use for automated repository maintenance and branch management.
How do I validate replay commands?
Section titled “How do I validate replay commands?”Parse the output to ensure valid update-ref command format and verify target references exist.
Does replay support interactive mode?
Section titled “Does replay support interactive mode?”No, replay is designed for automated/batch operations. Use rebase for interactive history modification.
Can replay work with remote branches?
Section titled “Can replay work with remote branches?”Yes, as long as the remote branches exist locally. Use fetch to ensure remote branches are available.
Applications of the git replay command
Section titled “Applications of the git replay command”- Repository Surgery: Complex branch reorganizations without working tree changes
- Bare Repository Operations: Work with repositories without working directories
- Batch Branch Updates: Update multiple branches simultaneously
- Automated Workflows: CI/CD integration for repository maintenance
- Disaster Recovery: Restore repository state from backups
- History Restructuring: Reorganize commit history without rebase conflicts