# DANGEROUS — overwrites remote without checking:git push --force origin main # DON'T DO THIS# SAFER — fails if someone else pushed since your last fetch:git push --force-with-lease origin feature/my-work
Note NEVER force push to main/master or any shared branch. It rewrites remote history and other developers' work will be lost or corrupted. If you must force push (e.g., after rebase on a personal branch), always use --force-with-lease which checks that the remote hasn't changed since you last fetched.
force pushsafe force pushpush rejectedforce push dangerforce with lease
Detached HEAD State
syntax
# You're in detached HEAD when:git checkout <commit-hash>
git checkout <tag>
# To fix — create a branch:gitswitch -c <new-branch>
example
git checkout a1b2c3d
# Warning: you are in 'detached HEAD' state.# If you made commits here and want to keep them:gitswitch -c rescue-branch
# If you just want to go back to a branch:gitswitch main
Note Detached HEAD means you're not on any branch. Commits made here will be garbage-collected if you switch away without creating a branch. If you accidentally left commits behind, find them with git reflog.
detached headnot on any branchlost commits detachedfix detached head
Merge vs Rebase: When to Use Which
syntax
# Merge: preserves history as it happenedgit merge feature/branch
# Rebase: creates linear historygit rebase main
example
# Team rule of thumb:# - Rebase your local/personal feature branch onto main regularlygitswitch feature/my-work
git rebase main
# - Merge the feature branch into main when donegitswitch main
git merge --no-ff feature/my-work
Note The golden rule: NEVER rebase commits that exist on a remote branch others are using. Rebase rewrites history (new hashes), while merge preserves it. Use rebase to keep your feature branch up-to-date privately; use merge to integrate completed work publicly.
merge vs rebasewhen to rebasewhen to mergerebase or merge
# Find the lost commit:git reflog
# Look for the entry before the mistake:# a1b2c3d HEAD@{5}: commit: Important work# Option 1: Reset to that point:git reset --hard a1b2c3d# Option 2: Cherry-pick just that commit:git cherry-pick a1b2c3d
# Option 3: Create a branch from it:git branch recovery a1b2c3d
Note Reflog entries expire after ~90 days by default. As long as the commit is in the reflog, it hasn't been garbage-collected and you can recover it. If you ran git gc manually, some commits may be permanently lost.
recover commitlost commitundo hard resetfind deleted commitaccidentally deleted branch
# File was tracked before adding to .gitignore:git rm --cached .envgit rm -r --cached node_modules/git commit -m "Stop tracking ignored files"
output
rm '.env'
rm 'node_modules/package-lock.json'
...
Note .gitignore only prevents UNTRACKED files from being added. If a file is already tracked, .gitignore has no effect on it. You must remove it from tracking with git rm --cached (the file itself stays on disk). This is one of the most common Git gotchas.
gitignore not workingfile still trackedignore already tracked filestop tracking file
Undo a Commit That's Already Pushed
syntax
git revert <commit>
git push
example
# The safe way — create a new commit that reverses the changes:git revert a1b2c3d
git push origin main
# If you need to undo multiple commits:git revert a1b2c3d..f4e5d6g
git push origin main
Note NEVER use git reset + force push on a shared branch. Use git revert instead, which creates a new commit that undoes the changes while preserving history. Everyone who pulled the original commit won't have conflicts.
undo pushed commitrevert published commitfix mistake on mainundo after push
Accidentally Committed a Secret
syntax
git filter-repo --invert-paths --path <secret-file># Then: rotate the credential immediately
example
# Step 1: ROTATE THE SECRET IMMEDIATELY# (It's in the remote history even if you delete it)# Step 2: Remove from all history:
pip install git-filter-repo
git filter-repo --invert-paths --path .env# Step 3: Force push the rewritten history:git push --force --all# Step 4: Tell all collaborators to re-clone
Note CRITICAL: Even if you delete the file in a new commit, the secret is still in the Git history and anyone can find it. The FIRST thing to do is rotate/revoke the compromised credential. Rewriting history with filter-repo is step two. GitHub also has a 'secret scanning' feature that alerts you.
committed secretremove password from gitleaked credentialsecret in historyremove sensitive file
Committed to the Wrong Branch
syntax
# Move last commit to a different branch:gitswitch <correct-branch>
git cherry-pick <commit>
gitswitch <wrong-branch>
git reset --hard HEAD~1
example
# Oops, committed to main instead of feature branch:git log --oneline -1 # Note the hash: a1b2c3dgitswitch feature/payments
git cherry-pick a1b2c3d
gitswitch main
git reset --hard HEAD~1
Note If the wrong branch hasn't been pushed yet, reset is safe. If it's already pushed, you'll need git revert on the wrong branch instead of reset, to avoid force-pushing shared history.
wrong branchcommitted to wrong branchmove commit to another branchmisplaced commit
# If not yet pushed — remove and recommit:git rm --cached data/huge-dataset.csvecho'data/*.csv' >> .gitignore
git commit -m "Remove large file, update gitignore"# If already pushed — rewrite history:git filter-repo --strip-blobs-bigger-than 50M
Note Git stores every version of every file forever. A 500MB file committed once bloats the repo permanently (even after deletion) unless you rewrite history. Use Git LFS for large files, and add size limits to your .gitignore proactively.
large filebig file in gitreduce repo sizegit lfsbloated repo