Git Command Combinations

Combining pull, push, rebase, revert, restore, amend, commit, and add

Learn how to combine Git commands effectively for various development scenarios. Each workflow shows the exact sequence of commands to handle common situations.

Update & Synchronization Scenarios

Keeping Feature Branch Updated Intermediate
Regularly update feature branch with main branch changes

Keep your feature branch current with the latest changes from main

# Start from your feature branch git checkout feature/new-feature # Fetch the latest changes from remote git fetch origin # Rebase your feature branch on top of main git rebase origin/main # Resolve any conflicts if they occur # git add . (after resolving conflicts) # git rebase --continue # Force push the updated branch (safe with --force-with-lease) git push --force-with-lease origin feature/new-feature
Recovering From a Bad Push Advanced
When you've pushed incorrect changes to remote

Revert changes both locally and remotely after a bad push

# First, revert the commit locally git revert HEAD # Then push the revert to remote git push origin main # Alternatively, if you need to completely remove the commit # Reset to the previous commit (only if no one else has pulled) git reset --hard HEAD~1 # Force push to update remote (use with extreme caution!) git push --force-with-lease origin main

Commit Management Scenarios

Fixing the Previous Commit Intermediate
When you need to modify the most recent commit

Add forgotten changes or edit the commit message

# Make your changes to the files echo "Forgotten change" >> file.txt # Stage the changes git add file.txt # Amend the previous commit git commit --amend # If you've already pushed, you'll need to force push git push --force-with-lease origin feature-branch # To just change the commit message (no file changes) git commit --amend -m "New commit message"
Partial Commit Management Advanced
When you want to commit only some changes from files

Stage and commit specific parts of files, not entire files

# Add changes interactively git add -p # For each change, choose: (y) stage, (n) don't stage, (s) split, (e) edit # Commit the staged changes git commit -m "Commit only specific changes" # Restore (discard) the unstaged changes if needed git restore file.txt # Or keep working on the unstaged changes

Recovery Scenarios

Undoing Published Changes Advanced
When you need to revert changes that were already pushed

Safely undo changes that are already in the remote repository

# Create a revert commit git revert <commit-hash> # Push the revert commit git push origin main # If you need to revert multiple commits git revert <older-commit-hash>..<newer-commit-hash> # If you want to revert but modify the changes git revert -n <commit-hash> # Make your adjustments git add . git commit -m "Adjusted revert" git push origin main
Restoring Lost Work Expert
When you've lost changes due to a hard reset or mistaken deletion

Recover work that seemed to be lost

# First, check the reflog for recent actions git reflog # Identify the commit where your work existed # abc1234 HEAD@{2}: commit: My important work # Restore files from that commit git restore --source=abc1234 file.txt # Or create a new branch from that commit git branch recovery-branch abc1234 # Cherry-pick specific commits if needed git cherry-pick abc1234 # Once recovered, add and commit the changes git add . git commit -m "Recover lost work"

Team Collaboration Scenarios

Integrating Team Changes Intermediate
When you need to incorporate a teammate's work

Merge or rebase with changes made by other team members

# First, fetch the latest changes git fetch --all # Checkout your teammate's branch git checkout teammate/feature git pull origin teammate/feature # Go back to your branch git checkout my-feature # Merge their changes into yours git merge teammate/feature # Alternatively, rebase your changes on top of theirs git rebase teammate/feature # Resolve any conflicts, then add and continue # git add . && git rebase --continue # Push the integrated changes git push origin my-feature
Resolving Push Rejections Intermediate
When your push is rejected due to remote changes

Handle the common situation where you can't push because the remote has new commits

# First, fetch the remote changes git fetch origin # Option 1: Merge the remote changes git merge origin/main # Resolve any merge conflicts # git add . && git commit -m "Merge remote changes" # Option 2: Rebase your changes on top of remote git rebase origin/main # Resolve any conflicts during rebase # git add . && git rebase --continue # After either approach, push your changes git push origin feature-branch # If you rebased, you might need to force push git push --force-with-lease origin feature-branch

Complex Workflow Scenarios

Interactive Rebase for Clean History Expert
When you want to clean up your commit history before sharing

Squash, edit, or reorder commits to create a clean history

# Start interactive rebase for the last 5 commits git rebase -i HEAD~5 # In the editor, change 'pick' to: # - 'squash' or 's' to combine with previous commit # - 'edit' or 'e' to modify a commit # - 'reword' or 'r' to change commit message # If you choose to edit a commit: # Make your changes, then stage them git add . # Continue the rebase git rebase --continue # If you need to abort at any point git rebase --abort # After completing, force push (if already pushed) git push --force-with-lease origin feature-branch
Partial Rollback of Changes Expert
When you need to undo some changes but keep others

Selectively revert certain changes while preserving others

# Create a revert commit but don't commit it yet git revert -n <commit-to-revert> # Now unstage the changes git reset # Interactively add only the changes you want to revert git add -p # Commit the partial revert git commit -m "Partial revert of <commit>" # Restore the changes you don't want to revert git restore . # Push the changes git push origin feature-branch

Branch Management Scenarios

Resolving Divergent Branches Advanced
When your branch has diverged significantly from main

Reconcile major differences between your feature branch and the main branch

# Checkout your feature branch git checkout feature/major-changes # Fetch the latest changes from remote git fetch origin # Rebase interactively to clean up your commits first git rebase -i HEAD~10 # Squash, fixup, or reorder commits as needed # Now rebase onto the latest main git rebase origin/main # Resolve conflicts systematically # For each conflict: git status # Review conflicts, edit files, then: git add . git rebase --continue # If it gets too complicated, abort and try a different approach git rebase --abort # Alternative: create a merge commit instead git merge origin/main # Resolve conflicts, then: git add . git commit -m "Merge main into feature" # Push the resolved branch git push --force-with-lease origin feature/major-changes
Recovering Deleted Branch with Unpushed Commits Expert
When you've accidentally deleted a branch with unpushed work

Find and restore a deleted branch that hasn't been pushed to remote yet

# First, check the reflog to find the commit git reflog # Look for the commit where your branch was last active # abc1234 (HEAD -> main) HEAD@{0}: commit: Some commit # def5678 (feature/my-work) HEAD@{1}: commit: My important work # Note the commit hash (def5678) and recreate the branch git branch feature/my-work def5678 # If you can't find it in reflog, check for dangling commits git fsck --full --no-reflogs --unreachable --lost-found # Look for dangling commit objects # dangling commit def5678abcdef1234567890abcdef123456789 # Check what's in that commit git show def5678 # If it's your work, create a branch from it git branch recovered-work def5678 # Verify the content is correct git checkout recovered-work git log --oneline -5 # Once verified, push to remote git push -u origin recovered-work

History Rewriting Scenarios

Splitting a Large Commit Advanced
When you need to split a large commit into logical pieces

Break down a monolithic commit into smaller, focused commits

# Start an interactive rebase git rebase -i HEAD~5 # Mark the commit you want to split with 'edit' # When rebase pauses at that commit, reset it git reset HEAD~ # This keeps changes in working directory but removes the commit # Now add changes piece by piece git add -p # For each logical change, stage and commit separately git add path/to/file1.js git commit -m "Add feature X component" git add path/to/file2.js git commit -m "Implement feature Y logic" git add path/to/test/file1.spec.js git commit -m "Add tests for feature X" # Continue the rebase git rebase --continue # Force push if already pushed to remote git push --force-with-lease origin feature-branch
Removing Sensitive Data from History Expert
When you've accidentally committed sensitive information

Completely remove sensitive data from Git history

# First, install git-filter-repo if not available # pip install git-filter-repo # Backup your repository first! git clone --mirror repo-url repo-backup # Remove the sensitive file from entire history git filter-repo --path config/database.yml --invert-paths # Or to remove a specific string from all files git filter-repo --replace-text <(echo "PASSWORD==>REDACTED" ) # Force push to all branches (warn your team first!) git push origin --force --all git push origin --force --tags # Every team member must reclone or reset # For those who can't reclone: git fetch origin git reset --hard origin/main # For each branch: git reset --hard origin/branch-name # Note: This rewrites history, so coordinate with your team

Team Collaboration Scenarios

Resolving Complex Merge Conflicts Advanced
When you encounter difficult merge conflicts

Systematically resolve complicated merge conflicts across multiple files

# Start the merge process git merge feature/conflicting-branch # If conflicts occur, see which files are affected git status # Both modified: path/to/conflicting-file.js # Use a visual merge tool if available git mergetool # Or resolve manually by editing files # Look for conflict markers: <<<<<<<,=======,>>>>>>> # For each conflicted file, resolve and stage git add path/to/resolved-file.js # If you want to abort the merge and try a different strategy git merge --abort # Alternative: use theirs or ours version for specific files git checkout --ours path/to/file.js # Or git checkout --theirs path/to/file.js # After resolving all conflicts, complete the merge git commit -m "Merge feature/conflicting-branch" # If it's a particularly complex merge, consider using a merge driver # Or break it into smaller merges
Collaborative Debugging with Git Bisect Expert
When you need to find which commit introduced a bug

Use binary search to efficiently locate the problematic commit

# Start the bisect process git bisect start # Mark the current commit as bad git bisect bad # Find a known good commit from the past git log --oneline --since="2023-01-01" # Identify a commit hash where things worked # Mark that commit as good git bisect good abc1234 # Git will now checkout a commit in the middle # Test if this commit has the bug npm test # Or manually test the specific functionality # Based on test results, mark as good or bad git bisect bad # Or git bisect good # Repeat until Git identifies the first bad commit # abc1234 is the first bad commit # Examine what changed in that commit git show abc1234 # End the bisect session git bisect reset # Now you can revert or fix the problematic commit

Advanced Tooling Scenarios

Using Worktree for Context Switching Advanced
When you need to work on multiple features simultaneously

Use Git worktree to avoid constant branch switching

# Create a new worktree for a bugfix while working on a feature git worktree add ../myproject-bugfix bugfix/urgent-issue # Now you can work on both simultaneously # Your main repository continues on the current branch # The worktree is in ../myproject-bugfix on the bugfix branch # Work on the bugfix in the separate directory cd ../myproject-bugfix # Make changes, commit, push as needed # When done, remove the worktree git worktree remove ../myproject-bugfix # You can create multiple worktrees for different tasks git worktree add ../myproject-docs docs-update git worktree add ../myproject-refactor refactor/component # List all worktrees git worktree list # This avoids the overhead of multiple clones # and keeps everything in sync automatically
Advanced Stashing Techniques Intermediate
When you need to temporarily store work in progress

Use advanced stashing techniques for complex context switching

# Stash your current work with a descriptive message git stash push -m "WIP: authentication feature" # Work on something else, then come back # See what's in your stash git stash list # Apply a specific stash without removing it from the stack git stash apply stash@{1} # If you have conflicts when applying, resolve them # Then you can drop the stash if applied successfully git stash drop stash@{1} # Create a branch from a stash git stash branch authentication-feature stash@{1} # Stash only untracked files git stash -u # Stash only specific files git stash push path/to/file1.js path/to/file2.js # View the content of a stash git stash show -p stash@{1} # Clean up old stashes git stash clear # Or drop specific stashes git stash drop stash@{2}

Critical Recovery Scenarios

I reset hard but need some files back Critical
Scenario
git reset --hard HEAD~3

You did a hard reset but later realized you needed changes from those commits.

Solution: Use git reflog to find the lost commits and restore files from them.

# Find the lost commits git reflog abc1234 HEAD@{0}: reset: moving to HEAD~3 def5678 HEAD@{1}: commit: Important feature ghi9012 HEAD@{2}: commit: Bug fixes # Restore files from specific commit git restore --source=def5678 path/to/important-file.txt
I pushed sensitive/accidental files Critical
Scenario
git push origin main

You pushed API keys, passwords, or other sensitive data to a remote repository.

Solution: Use git filter-repo to completely remove the file from history.

# 1. Remove file from history (install git-filter-repo first) git filter-repo --path secrets.txt --invert-paths # 2. Force push (warn your team first!) git push --force # 3. Everyone else must reclone or reset their repos git fetch origin git reset --hard origin/main
I need to find which commit introduced a bug Caution
Scenario
git push origin main

You pushed multiple commits that introduced a bug and need to identify which specific commit caused it.

Solution: Use git bisect to perform a binary search through your commit history.

# Start the bisect process git bisect start # Mark the current commit as bad git bisect bad # Mark a known good commit from the past git bisect good abc1234 # Git will checkout a commit in the middle - test your code # Then mark it as good or bad: git bisect good # OR git bisect bad # Repeat until Git identifies the first bad commit # End the bisect session git bisect reset
I need to discard only the last commit but keep changes Safe
Scenario
git commit -m "Wrong commit"

You made a commit but want to undo it while keeping all the changes in your working directory.

Solution: Use git reset --soft to remove the commit but keep changes staged.

# Remove the last commit but keep changes staged git reset --soft HEAD~1 # Now you can make a new commit with the correct changes git commit -m "Correct commit message" # If you want to unstage the changes too: git reset HEAD~1 # This keeps changes in working directory but unstaged
I need to discard the last commit completely Caution
Scenario
git commit -m "Bad commit"

You made a commit with errors and want to completely remove it and discard all changes.

Solution: Use git reset --hard to completely remove the commit and all changes.

# Completely remove the last commit and all changes git reset --hard HEAD~1 # If you've already pushed to remote, you'll need to force push # WARNING: This can cause issues for collaborators git push --force-with-lease # For multiple commits back: git reset --hard HEAD~3 # This will remove the last 3 commits
I need Lost uncommitted changes after hard reset Caution

Scenario: Lost uncommitted changes after hard reset

Critical
git reset --hard HEAD

You had uncommitted changes in your working directory, but accidentally ran git reset --hard and lost everything. You never committed these changes, so they're not in your commit history.

Recovery Solutions

# 1. First, check if Git has stored your changes as dangling blobs git fsck --lost-found dangling blob 1676c54c5aa0b98c5badc70d6dcd5f40c2562d0d dangling commit 45d9e2ae8495a2bfbdee59b2f44ec0c7c5e33bf2 ... # 2. Look for 'dangling blob' entries - these might be your lost files git show 1676c54c5aa0b98c5badc70d6dcd5f40c2562d0d > recovered_file.txt # 3. Alternatively, check the reflog for any possible references git reflog # 4. Search for specific content in dangling blobs git fsck --lost-found | grep blob | awk '{print $3}' | xargs -I{} sh -c 'echo "=== {} ==="; git show {}' | less

If you're using an IDE like VS Code, IntelliJ, or WebStorm, check if it has local history features that might have preserved your changes:

# IDE-Specific recovery options: # VS Code: Check "Local History" extension or timed backups # IntelliJ/WebStorm: Right-click file -> Local History -> Show History # Eclipse: Right-click file -> Replace With -> Local History

If dangling blobs don't work

If the above methods don't recover your files, you might try these system-level approaches:

# 1. Check your OS trash/recycle bin # Files might have been moved to trash instead of being deleted # 2. Use file recovery software # Tools like Recuva (Windows), TestDisk (Cross-platform), or # PhotoRec (Cross-platform) can recover recently deleted files # 3. Check for temporary files or backups # Many editors create backup files (e.g., file.txt~, .swp files) find . -name "*~" -o -name "*.swp" -o -name "*.swo"
Prevention for the future

To avoid this situation in the future:

  • Commit your work frequently, even if it's just to a temporary branch
  • Use git stash to temporarily store changes instead of resetting
  • Configure your IDE to use automatic backups and local history
  • Consider using git add -p to selectively stage changes
  • Before destructive operations, create a backup branch: git branch backup/before-reset

Pro Tip: Recover from IDE autosaves

Many modern IDEs automatically save versions of your files as you work:

# VS Code (check these locations): # Windows: %APPDATA%\Code\Backups # macOS: ~/Library/Application Support/Code/Backups # Linux: ~/.config/Code/Backups # IntelliJ/WebStorm: Check the "Local History" feature # Right-click on file or directory -> Local History -> Show History
I need to clone only a specific commit Safe
Scenario
git clone repository-url

You want to give a junior developer only code from a specific commit, not the entire history.

Solution: Clone the repository then checkout the specific commit, or use shallow clone.

# Method 1: Clone then checkout specific commit git clone https://github.com/user/repo.git cd repo git checkout abc1234 # Method 2: Shallow clone with specific depth git clone --depth 1 https://github.com/user/repo.git # This clones only the latest commit # Method 3: Clone then create new branch at specific commit git clone https://github.com/user/repo.git cd repo git checkout -b stable-version abc1234
I need to clone only a specific branch Safe
Scenario
git clone repository-url

You want to clone only a specific branch to save time and bandwidth, especially for large repositories.

Solution: Use the --branch and --single-branch options to clone only the desired branch.

# Clone only the main branch git clone --branch main --single-branch https://github.com/user/repo.git # Clone only the development branch git clone --branch develop --single-branch https://github.com/user/repo.git # Clone with limited history (last 10 commits) git clone --branch main --single-branch --depth 10 https://github.com/user/repo.git # To later fetch other branches from this clone: git remote set-branches origin 'other-branch' git fetch --depth 1 origin other-branch git checkout other-branch

Nuclear Scenarios

The Nuclear Reset Extreme
Scenario
git reset --hard origin/main

You lost days of uncommitted work after a hard reset.

Solution: Use git's internal file system check to find lost blobs.

# Search for lost data git fsck --lost-found # Look for blobs (file contents) git show [blob-hash] # Search for specific content git fsck --lost-found | grep "blob" | xargs -I{} sh -c 'git show {} | grep -q "unique string" && echo {}'
I need to completely rewrite commit history Extreme
Scenario
git rebase -i HEAD~10

You need to completely rewrite commit history (change messages, reorder, squash, or delete commits).

Solution: Use interactive rebase to rewrite history, then force push.

# Start interactive rebase for last 10 commits git rebase -i HEAD~10 # In the editor, change 'pick' to: # - 'reword' to change commit message # - 'edit' to modify the commit # - 'squash' to combine with previous commit # - 'drop' to remove the commit entirely # Save and exit, follow prompts for each change # Force push the rewritten history git push --force-with-lease # WARNING: This rewrites history - notify your team! # Anyone with the old history will need to reset their branches

Branch Management Scenarios

I need to recover a deleted branch Caution
Scenario
git branch -D feature

You accidentally deleted a branch that hadn't been merged yet.

Solution: Use git reflog to find the last commit on the branch and recreate it.

# Find the commit where the branch was last referenced git reflog abc1234 HEAD@{0}: checkout: moving from feature to main def5678 HEAD@{1}: commit: Final feature work # Recreate the branch from that commit git branch feature def5678 # If you can't find it, check remote tracking branches git fetch origin git checkout -b feature origin/feature
I need to rename a branch Safe
Scenario
git branch -m new-name

You want to rename a branch, both locally and on the remote repository.

Solution: Rename locally, push to remote, and delete the old remote branch.

# Rename the local branch git branch -m old-branch-name new-branch-name # Push the new branch to remote git push origin -u new-branch-name # Delete the old remote branch git push origin --delete old-branch-name # If someone else already has the old branch: git fetch origin git remote prune origin
Pro Tip

Before doing any destructive operations, create a backup branch: git branch backup/before-dangerous-operation. This gives you a safe point to return to if things go wrong.

Pro Tip

Create aliases for complex Git workflows. For example, add this to your ~/.gitconfig:
[alias]
cleanup = "!git fetch --prune && git branch --merged main | grep -v \"main\" | xargs -n 1 git branch -d"
prepush = "!git fetch origin && git rebase origin/main && npm test"
wip = "!git add -A && git commit -m \"WIP\" && git push"

Safety Note

Always be cautious with history rewriting commands like rebase, reset --hard, and push --force. These can cause work to be lost if used incorrectly. When in doubt, create a backup branch first: git branch backup/before-dangerous-operation.

Pro Tip

Create aliases for complex command combinations. For example: git config --global alias.sync-branch '!git fetch origin && git rebase origin/main && git push --force-with-lease origin' Then you can simply run: git sync-branch

Important Safety Note

Be extremely careful with force push (git push --force or git push --force-with-lease). Always use --force-with-lease when possible as it's safer. Never force push to shared branches like main or develop without team coordination.