
Modern Git
- 16 installs
- 1 repo stars
- Updated January 26, 2026
- daleseo/git-skills
Teaches modern Git 2.23+ commands (switch, restore, push --force-with-lease) as clearer, safer replacements for overloaded legacy commands like checkout.
About
Recommends git switch for branches, git restore for files, and --force-with-lease over --force for explicit, safer intent. Developers use it to write clearer Git commands and avoid checkout mistakes.
- git switch and git restore instead of git checkout
- push --force-with-lease instead of --force
Modern Git by the numbers
- 16 all-time installs (skills.sh)
- Ranked #400 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/daleseo/git-skills --skill modern-gitAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 16 |
|---|---|
| repo stars | ★ 1 |
| Last updated | January 26, 2026 |
| Repository | daleseo/git-skills ↗ |
What it does
Teaches modern Git 2.23+ commands (switch, restore, push --force-with-lease) as clearer, safer replacements for overloaded legacy commands like checkout.
Files
Modern Git Commands
Purpose: This skill teaches AI agents to use modern, intuitive Git commands instead of legacy multi-purpose commands like git checkout. Modern commands are clearer, safer, and make code intent more obvious.
Core Principles
1. Use `git switch` for branch operations - NOT git checkout 2. Use `git restore` for file operations - NOT git checkout -- 3. Use `git push --force-with-lease` - NOT git push --force 4. Be explicit about intent - Clear commands prevent mistakes
Quick Reference
Branch Operations → Use git switch
# ✓ CORRECT: Modern commands
git switch main # Switch to existing branch
git switch -c feature-branch # Create and switch to new branch
git switch - # Switch to previous branch
# ✗ AVOID: Legacy commands
git checkout main # Overloaded command, unclear intent
git checkout -b feature-branch # Same operation, less clear
git checkout - # Same, but what does "-" mean?Why: git switch has a single, clear purpose: branch operations. It provides better error messages and is harder to misuse.
File Operations → Use git restore
# ✓ CORRECT: Modern commands
git restore src/app.js # Discard working directory changes
git restore --staged src/app.js # Unstage file
git restore --source=abc123 src/app.js # Restore from specific commit
git restore --staged --worktree src/app.js # Unstage AND discard
# ✗ AVOID: Legacy commands
git checkout -- src/app.js # Requires confusing "--" separator
git reset HEAD src/app.js # "reset" sounds destructive
git checkout abc123 -- src/app.js # Unclear what's happeningWhy: git restore is dedicated to file operations with explicit flags (--staged, --worktree, --source) that make intent crystal clear.
Force Push → Use --force-with-lease
# ✓ CORRECT: Safe force push
git push --force-with-lease origin feature-branch
# ✗ AVOID: Dangerous force push
git push --force origin feature-branchWhy: --force-with-lease checks if the remote branch has been updated by others before force pushing. Prevents accidental overwrites.
Decision Trees
"I need to switch branches"
Do you need to create the branch first?
├─ YES → git switch -c <new-branch>
└─ NO → git switch <existing-branch>
Special cases:
├─ Previous branch → git switch -
└─ With uncommitted changes → git stash && git switch <branch> && git stash pop
OR git switch -c <new-branch> (bring changes with you)"I need to fix a file"
What do you want to fix?
├─ Discard working directory changes
│ └─> git restore <file>
│
├─ Unstage file (keep changes in working directory)
│ └─> git restore --staged <file>
│
├─ Discard AND unstage
│ └─> git restore --staged --worktree <file>
│
└─ Restore from specific commit
└─> git restore --source=<commit> <file>"I need to force push"
Why do you need to force push?
├─ After rebase/amend (common, safe scenario)
│ └─> git push --force-with-lease origin <branch>
│
├─ To overwrite remote (rare, potentially dangerous)
│ ├─ Are you SURE no one else has pushed?
│ │ ├─ YES → git push --force-with-lease origin <branch>
│ │ └─ NO → git fetch && git rebase origin/<branch>
│ │
│ └─> Tip: ALWAYS prefer --force-with-lease over --forceCommon Workflows
Workflow 1: Start New Feature
# ✓ CORRECT
git switch main
git pull
git switch -c feature/new-feature
# ✗ AVOID
git checkout main
git pull
git checkout -b feature/new-featureWorkflow 2: Discard File Changes
# ✓ CORRECT
git restore src/broken.js # Single file
git restore . # All files in current directory
# ✗ AVOID
git checkout -- src/broken.js
git checkout -- .Workflow 3: Unstage and Discard
# ✓ CORRECT
git restore --staged --worktree src/app.js
# OR two steps for clarity
git restore --staged src/app.js # Unstage
git restore src/app.js # Then discard
# ✗ AVOID
git reset HEAD src/app.js
git checkout -- src/app.jsWorkflow 4: Restore from Specific Commit
# ✓ CORRECT
git restore --source=abc123 src/legacy.js
git restore --source=HEAD~3 src/config.js
# ✗ AVOID
git checkout abc123 -- src/legacy.js
git checkout HEAD~3 -- src/config.jsWorkflow 5: Safe Rebase and Push
# ✓ CORRECT
git switch feature-branch
git rebase main
git push --force-with-lease origin feature-branch
# ✗ AVOID
git checkout feature-branch
git rebase main
git push --force origin feature-branchSafety Guidelines
1. Always Use Modern Commands for Common Operations
| Operation | Use This | NOT This |
|---|---|---|
| Switch branch | git switch <branch> | git checkout <branch> |
| Create branch | git switch -c <branch> | git checkout -b <branch> |
| Discard changes | git restore <file> | git checkout -- <file> |
| Unstage | git restore --staged <file> | git reset HEAD <file> |
| Force push | git push --force-with-lease | git push --force |
2. Be Explicit About Intent
# ✓ GOOD: Intent is obvious
git restore --staged src/app.js # Clearly unstaging
git restore --source=HEAD~1 src/app.js # Clearly restoring from parent commit
# ✗ UNCLEAR: What's happening?
git checkout -- src/app.js # Restoring? From where?
git checkout HEAD~1 -- src/app.js # Is this switching branches or restoring?3. Protect Against Accidents
# ✓ SAFE: --force-with-lease protects against overwrites
git push --force-with-lease origin feature-branch
# ✗ DANGEROUS: Can overwrite others' work
git push --force origin feature-branch
# ✓ SAFE: git switch refuses to switch with uncommitted changes
git switch main # Errors if uncommitted changes
# ✗ RISKY: Need to remember --discard flag
git switch --discard-changes main # Only use when you WANT to lose changes4. Use Stash for Experimentation
# ✓ SAFE: Can recover if experiment fails
git stash push -m "Before risky operation"
# Try risky operation
git restore --source=old-commit .
# If it fails:
git stash pop # Recover
# ✗ RISKY: No recovery option
git restore --source=old-commit .
# Changes lost forever!When Legacy Commands Are Still OK
Some scenarios don't have modern equivalents:
# Exploring history (detached HEAD)
git checkout abc123 # Still acceptable
git switch --detach abc123 # More explicit alternative
# Complex remote tracking
git checkout -b local origin/remote # Still commonly usedRule of thumb: If there's a modern equivalent for your use case, use it. Legacy commands are OK only when no modern alternative exists.
Common Mistakes to Avoid
Mistake 1: Using git checkout for Everything
# ✗ BAD: Unclear intent, error-prone
git checkout main
git checkout -b feature
git checkout -- src/app.js
# ✓ GOOD: Clear intent for each operation
git switch main
git switch -c feature
git restore src/app.jsMistake 2: Forgetting --force-with-lease
# ✗ BAD: Can overwrite others' commits
git rebase main
git push --force origin feature-branch
# ✓ GOOD: Safe against overwrites
git rebase main
git push --force-with-lease origin feature-branchMistake 3: Confusing --staged and --worktree
# ✗ WRONG: Only unstages, doesn't discard changes
git restore --staged src/app.js
# File still modified in working directory!
# ✓ CORRECT: Specify both if you want both
git restore --staged --worktree src/app.js
# OR
git restore --staged src/app.js # Unstage
git restore src/app.js # Then discardMistake 4: Not Checking Before Discarding
# ✗ RISKY: Blindly discarding without checking
git restore .
# ✓ SAFE: Check what you're losing first
git status
git diff
git restore .Integration with AI Code Generation
When generating Git commands in code or documentation:
1. Default to Modern Commands
# ✓ GOOD: Use modern commands in examples
To discard your changes, run:
\`\`\`bash
git restore src/app.js
\`\`\`
# ✗ AVOID: Don't teach legacy commands
To discard your changes, run:
\`\`\`bash
git checkout -- src/app.js
\`\`\`2. Explain Why Modern Commands Are Better
# ✓ GOOD: Educate users
Use `git switch` instead of `git checkout` for branch operations.
This makes your intent clearer and provides better error messages.
# ✗ INSUFFICIENT: Just showing command without context
Use `git switch main` to switch branches.3. Use Consistent Command Patterns
# ✓ GOOD: Consistent modern commands throughout
git switch develop
git pull
git switch -c feature/new-feature
git restore --staged accidental-file.js
# ✗ INCONSISTENT: Mixing old and new
git checkout develop
git pull
git switch -c feature/new-feature
git checkout -- accidental-file.jsReference Documentation
For detailed comparisons and advanced scenarios:
- [Command Comparison](./references/command-comparison.md) - Side-by-side legacy vs modern command comparisons
- [Migration Guide](./references/migration-guide.md) - Detailed patterns for complex scenarios
Summary Table
| Use Case | Command | Key Flags | Notes |
|---|---|---|---|
| Switch to branch | git switch <branch> | -c (create), - (previous) | Replaces git checkout <branch> |
| Discard file changes | git restore <file> | --worktree (default) | Replaces git checkout -- <file> |
| Unstage file | git restore --staged <file> | --staged | Replaces git reset HEAD <file> |
| Restore from commit | git restore --source=<commit> <file> | --source | Replaces git checkout <commit> -- <file> |
| Force push safely | git push --force-with-lease | --force-with-lease | Replaces git push --force |
Key Takeaway
Always prefer modern commands for clarity, safety, and better error messages. Your future self (and code reviewers) will thank you.
When in doubt:
- Branch operations →
git switch - File operations →
git restore - Force push →
--force-with-lease
Modern Git Commands: Command Comparison
This guide provides side-by-side comparisons of legacy Git commands and their modern alternatives introduced in Git 2.23+.
Quick Reference Table
| Legacy Command | Modern Alternative | Purpose |
|---|---|---|
git checkout <branch> | git switch <branch> | Switch to existing branch |
git checkout -b <branch> | git switch -c <branch> | Create and switch to new branch |
git checkout - | git switch - | Switch to previous branch |
git checkout -- <file> | git restore <file> | Discard changes in working directory |
git reset HEAD <file> | git restore --staged <file> | Unstage file |
git checkout <commit> -- <file> | git restore --source=<commit> <file> | Restore file from specific commit |
git push --force | git push --force-with-lease | Force push with safety check |
git reset HEAD <file> | git restore --staged <file> | Unstage changes |
Detailed Comparisons
Branch Switching
Legacy: git checkout
# Switch to existing branch
git checkout main
# Create new branch and switch to it
git checkout -b feature-branch
# Switch to previous branch
git checkout -Problems:
- Same command handles branches, files, and commits
- Easy to accidentally detach HEAD
- Confusing error messages when branch name conflicts with file name
- Intent is unclear: are you switching branches or restoring files?
Modern: git switch
# Switch to existing branch
git switch main
# Create new branch and switch to it
git switch -c feature-branch
# Switch to previous branch
git switch -Benefits:
- Single, clear purpose: branch operations only
- Better error messages
- Safer: refuses to switch with uncommitted changes (use
--discard-changesexplicitly) - Intent is immediately obvious
File Restoration
Legacy: git checkout -- <file>
# Discard changes in working directory
git checkout -- src/app.js
# Restore file from specific commit
git checkout abc123 -- src/app.js
# Common mistake: forget the -- separator
git checkout src/app.js # Tries to switch to branch named "src/app.js"!Problems:
- Requires
--separator to distinguish from branch names - Same command as branch switching (confusing)
- No way to restore from index vs HEAD
- Dangerous: silently discards work
Modern: git restore
# Discard changes in working directory
git restore src/app.js
# Restore file from specific commit
git restore --source=abc123 src/app.js
# Restore from staging area (index)
git restore --worktree --staged src/app.jsBenefits:
- Dedicated command for file operations
- No
--separator needed - Explicit
--sourceflag makes intent clear - Can restore from index, HEAD, or any commit
- More explicit flags prevent accidents
Unstaging Files
Legacy: git reset HEAD <file>
# Unstage a file
git reset HEAD src/app.js
# Unstage all files
git reset HEADProblems:
git resethas multiple modes (--soft, --mixed, --hard)- Easy to confuse with destructive operations
- Not intuitive that it unstages files
Modern: git restore --staged
# Unstage a file
git restore --staged src/app.js
# Unstage all files
git restore --staged .Benefits:
- Clear, explicit purpose
- No confusion with
git resetcommit history operations - Consistent with
git restorefor working directory
Force Pushing
Legacy: git push --force
# Force push (dangerous!)
git push --force origin feature-branchProblems:
- Can overwrite others' commits if branch was updated
- No safety check
- Common cause of lost work in collaborative projects
Modern: git push --force-with-lease
# Force push with safety check
git push --force-with-lease origin feature-branchBenefits:
- Checks if remote branch matches your expectation
- Refuses to push if someone else has pushed commits
- Prevents accidental overwrites
- Still allows force push when intentional
Common Migration Patterns
Pattern 1: Switching Branches
# OLD
git checkout develop
git pull
git checkout -b feature/new-feature
# NEW
git switch develop
git pull
git switch -c feature/new-featurePattern 2: Discarding File Changes
# OLD
git checkout -- src/broken.js
git checkout -- .
# NEW
git restore src/broken.js
git restore .Pattern 3: Unstaging and Discarding
# OLD
git reset HEAD src/app.js
git checkout -- src/app.js
# NEW
git restore --staged src/app.js
git restore src/app.js
# Or in one command (Git 2.25+)
git restore --staged --worktree src/app.jsPattern 4: Restoring from Specific Commit
# OLD
git checkout abc123 -- src/legacy.js
# NEW
git restore --source=abc123 src/legacy.jsPattern 5: Safe Force Push
# OLD (after rebase or amend)
git push --force origin feature-branch
# NEW
git push --force-with-lease origin feature-branchWhen Legacy Commands Are Still Useful
Some git checkout use cases don't have modern alternatives:
# Detached HEAD state (exploring history)
git checkout abc123
# Checkout remote branch
git checkout -b local-branch origin/remote-branch
# Modern equivalent requires two steps:
git switch -c local-branch
git branch --set-upstream-to=origin/remote-branchFor these cases, git checkout is still appropriate. The modern commands are about separating the most common use cases (switching branches, restoring files) into dedicated commands.
Safety Tips
1. Always use `--force-with-lease` instead of `--force`
- Prevents accidental overwrites
- Only use
--forcewhen you understand the risk
2. Prefer `git switch` over `git checkout` for branches
- Clearer intent
- Better error messages
- Harder to make mistakes
3. Use `git restore` for file operations
- Explicit
--stagedand--worktreeflags - Clear
--sourcefor commit references - Less confusion with branch operations
4. Be explicit about what you're restoring
# Good: Clear what's being restored
git restore --staged src/app.js
git restore --worktree src/app.js
# Less clear: What's being restored?
git restore src/app.js # Defaults to --worktreeError Message Improvements
Modern commands provide better error messages:
# OLD
$ git checkout non-existent-branch
error: pathspec 'non-existent-branch' did not match any file(s) known to git
# NEW
$ git switch non-existent-branch
fatal: invalid reference: non-existent-branch
hint: use 'git switch -c non-existent-branch' to create the branchThe modern command recognizes you're trying to switch branches and provides helpful hints.
Summary
| Use Case | Legacy | Modern | Why Change? |
|---|---|---|---|
| Switch branch | git checkout <branch> | git switch <branch> | Single responsibility, clearer intent |
| Create branch | git checkout -b <branch> | git switch -c <branch> | Consistent with switch |
| Discard changes | git checkout -- <file> | git restore <file> | No separator needed, dedicated purpose |
| Unstage file | git reset HEAD <file> | git restore --staged <file> | Clearer semantics |
| Force push | git push --force | git push --force-with-lease | Prevents accidental overwrites |
Key principle: Modern Git separates commands by purpose, making each operation more explicit and reducing the chance of mistakes.
Migration Guide: From Legacy to Modern Git Commands
This guide provides detailed migration patterns for complex scenarios when transitioning from legacy Git commands to modern alternatives.
Philosophy
Modern Git commands follow these principles:
1. Single Responsibility: Each command does one thing well 2. Explicit Intent: Flags and options clearly express what you want 3. Safe by Default: Destructive operations require explicit flags 4. Better Error Messages: Helpful hints when things go wrong
Migration Scenarios
Scenario 1: Working with Uncommitted Changes
Problem: Switching branches with uncommitted changes
Legacy approach:
git stash
git checkout target-branch
git stash popModern approach (explicit):
# Option 1: Stash (still useful)
git stash
git switch target-branch
git stash pop
# Option 2: Discard changes explicitly
git switch --discard-changes target-branch
# Option 3: Create new branch with changes
git switch -c new-branch-with-changesWhy this matters:
git switchrefuses to switch with uncommitted changes by default- Forces explicit decision: stash, discard, or create new branch
- Prevents accidental loss of work
Scenario 2: Detached HEAD State
Problem: Exploring commit history
Legacy approach:
# View specific commit
git checkout abc123
# Return to branch
git checkout mainModern approach:
# View specific commit (git checkout still appropriate here)
git checkout abc123
# Or use git switch with --detach for clarity
git switch --detach abc123
# Return to branch
git switch mainWhen to use what:
git checkout <commit>: Still acceptable for detached HEADgit switch --detach <commit>: More explicit about intentgit switch <branch>: Always use for returning to a branch
Scenario 3: Restoring Files from Different Sources
Problem: Complex file restoration scenarios
Legacy approach:
# Restore file from HEAD
git checkout -- src/app.js
# Restore file from staging area
git checkout HEAD -- src/app.js # Actually restores from HEAD, not staging!
# Restore file from specific commit
git checkout abc123 -- src/app.js
# Restore and stage
git checkout abc123 -- src/app.js
git add src/app.jsModern approach:
# Restore file from HEAD (discard working directory changes)
git restore src/app.js
# Restore file from staging area to working directory
git restore --staged --worktree src/app.js
# Or separately:
git restore --staged src/app.js # Unstage
git restore src/app.js # Discard changes
# Restore file from specific commit to working directory
git restore --source=abc123 src/app.js
# Restore file from specific commit to staging AND working directory
git restore --source=abc123 --staged --worktree src/app.jsDecision tree:
What do you want to restore?
│
├─ Discard working directory changes
│ └─> git restore <file>
│
├─ Unstage file (keep working directory changes)
│ └─> git restore --staged <file>
│
├─ Restore from specific commit
│ ├─ To working directory only
│ │ └─> git restore --source=<commit> <file>
│ │
│ └─ To staging AND working directory
│ └─> git restore --source=<commit> --staged --worktree <file>
│
└─ Restore from staging to working directory
└─> Copy from staging to worktree (advanced)Scenario 4: Branch Creation from Remote
Problem: Creating local branch from remote
Legacy approach:
# Fetch and create tracking branch
git fetch origin
git checkout -b local-branch origin/remote-branch
# Or shorthand (if remote branch exists)
git checkout remote-branch # Creates local branch automaticallyModern approach:
# Fetch and create tracking branch explicitly
git fetch origin
git switch -c local-branch origin/remote-branch
# Or track remote branch with same name
git fetch origin
git switch remote-branch # Creates local branch tracking origin/remote-branch
# Set upstream separately (more explicit)
git switch -c local-branch
git branch --set-upstream-to=origin/remote-branchBest practice:
# Most explicit and clear
git fetch origin
git switch -c local-branch --track origin/remote-branchScenario 5: Partial File Restoration
Problem: Restore specific parts of files
Legacy approach:
# Restore entire file from commit
git checkout abc123 -- src/app.js
# For partial restore, use git diff + patch
git diff HEAD abc123 -- src/app.js > patch.diff
# Manually edit patch.diff
git apply patch.diffModern approach:
# Restore entire file
git restore --source=abc123 src/app.js
# For partial restore, still use patches or interactive add
git restore --source=abc123 --patch src/app.js
# Interactive: choose which hunks to restore
# Or use git diff with restore
git diff HEAD abc123 -- src/app.js > patch.diff
# Edit patch.diff
git apply patch.diffPro tip:
# Interactive restore (Git 2.25+)
git restore --patch src/app.js
# Shows each change hunk, ask whether to restore itScenario 6: Recovering from Mistakes
Problem: Accidentally discarded important changes
Legacy approach:
# If you did: git checkout -- important.js
# Changes are lost! No easy recovery unless in reflog or editor undo
# Try reflog (might not work for unstaged changes)
git reflog
git checkout <sha> -- important.jsModern approach:
# If you did: git restore important.js
# Same problem - changes are lost!
# Prevention: Use git stash before risky operations
git stash push -m "Before risky restore" important.js
# Try your changes
git stash pop # Recover if neededBest practice:
# Before discarding changes, always check what you're losing
git diff important.js
# Or stash instead of discard
git stash push important.js # Can recover later with git stash popScenario 7: Force Push After Rebase
Problem: Updating remote branch after history rewrite
Legacy approach:
git rebase -i HEAD~3
# Edit commits
git push --force origin feature-branchRisk: If teammate pushed commits, you'll overwrite them!
Modern approach:
git rebase -i HEAD~3
# Edit commits
git push --force-with-lease origin feature-branchWhat `--force-with-lease` does:
# Checks: Does remote branch match my last fetch?
# YES: Push succeeds (safe to force push)
# NO: Push rejected (someone else pushed commits)
# If rejected, fetch and handle conflict:
git fetch origin
git rebase origin/feature-branch # Reapply your changes
git push --force-with-lease origin feature-branchAdvanced: Specific lease checks
# Only push if remote matches specific commit
git push --force-with-lease=feature-branch:abc123 origin feature-branchScenario 8: Switching Between Multiple Worktrees
Problem: Working on multiple branches simultaneously
Legacy approach:
# Clone repository multiple times
# Or constantly switch branches
git checkout feature-1
# Work...
git checkout feature-2
# Work...
git checkout mainModern approach:
# Use git worktree for parallel work
git worktree add ../project-feature-1 feature-1
git worktree add ../project-feature-2 feature-2
# Switch between directories, not branches
cd ../project-feature-1 # Working on feature-1
cd ../project-feature-2 # Working on feature-2
# In main project directory, use git switch
git switch mainBest practice:
# Worktrees for long-running branches
git worktree add ../project-hotfix hotfix-branch
# git switch for quick branch changes in main directory
git switch main
git switch feature-branch
git switch -Muscle Memory Migration
Common Aliases to Retrain Habits
Add to ~/.gitconfig:
[alias]
sw = switch
swc = switch -c
rs = restore
rss = restore --stagedTraining Exercises
1. Week 1: Branch operations
- Replace all
git checkout <branch>withgit switch <branch> - Replace all
git checkout -bwithgit switch -c
2. Week 2: File operations
- Replace all
git checkout -- <file>withgit restore <file> - Replace all
git reset HEAD <file>withgit restore --staged <file>
3. Week 3: Force push
- Replace all
git push --forcewithgit push --force-with-lease
4. Week 4: Complex scenarios
- Practice
git restore --source=<commit> - Practice
git restore --staged --worktree
Troubleshooting Common Issues
Issue 1: "git switch refuses to switch with uncommitted changes"
Error:
error: Your local changes to the following files would be overwritten by checkout:
src/app.js
Please commit your changes or stash them before you switch branches.Solutions:
# Option 1: Stash changes
git stash
git switch target-branch
git stash pop
# Option 2: Commit changes
git commit -am "WIP: Save work in progress"
git switch target-branch
# Option 3: Discard changes explicitly (destructive!)
git switch --discard-changes target-branch
# Option 4: Create new branch with changes
git switch -c new-branchIssue 2: "git restore --staged doesn't discard changes"
Confusion:
git restore --staged src/app.js
# File still shows changes in git status!Explanation: --staged only unstages the file. Changes remain in working directory.
Solution:
# Unstage AND discard
git restore --staged --worktree src/app.js
# Or two steps
git restore --staged src/app.js # Unstage
git restore src/app.js # DiscardIssue 3: "git push --force-with-lease rejected"
Error:
error: failed to push some refs to 'origin'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref.Solutions:
# Option 1: Fetch and rebase
git fetch origin
git rebase origin/feature-branch
git push --force-with-lease origin feature-branch
# Option 2: Fetch and merge
git fetch origin
git merge origin/feature-branch
git push origin feature-branch # No force needed
# Option 3: Force push anyway (dangerous!)
git push --force origin feature-branch # Only if you're SUREAdvanced Patterns
Pattern 1: Selective File Restoration from Multiple Commits
# Restore different files from different commits
git restore --source=abc123 src/feature-a.js
git restore --source=def456 src/feature-b.js
git restore --source=HEAD~5 src/legacy.js
# Stage them all
git add src/feature-a.js src/feature-b.js src/legacy.js
git commit -m "Cherry-pick specific files from history"Pattern 2: Branch Renaming Workflow
# Rename local branch
git branch -m old-name new-name
# Delete old remote branch and push new one
git push origin --delete old-name
git push -u origin new-name
# Update tracking
git branch --set-upstream-to=origin/new-name new-namePattern 3: Safe Experimentation
# Save current state
git stash push -m "Backup before experiment"
# Try dangerous operation
git restore --source=abc123 .
# If experiment fails, recover
git stash pop
# If experiment succeeds, drop backup
git stash dropCheat Sheet: Quick Reference
| Task | Legacy | Modern |
|---|---|---|
| Switch branch | git checkout main | git switch main |
| Create branch | git checkout -b feat | git switch -c feat |
| Previous branch | git checkout - | git switch - |
| Discard changes | git checkout -- file | git restore file |
| Unstage | git reset HEAD file | git restore --staged file |
| Restore from commit | git checkout abc123 -- file | git restore --source=abc123 file |
| Force push | git push --force | git push --force-with-lease |
Summary
Modern Git commands improve clarity and safety by:
1. Separating concerns: switch for branches, restore for files 2. Explicit intent: Clear flags like --staged, --worktree, --source 3. Better defaults: Refuse dangerous operations without explicit flags 4. Improved errors: Helpful messages guide you to the right command
The migration is straightforward for most use cases. Start with branch operations (git switch), then file operations (git restore), and finally adopt safety improvements (--force-with-lease).