Git recovery
Everything here has been hit for real on a Codrlabs project. The pitfalls listed are the ones that cost an afternoon, so they are written down rather than rediscovered.
Committed to main instead of a branch
Section titled “Committed to main instead of a branch”git reset HEAD~1 # undo the commit, keep the changesgit checkout -b feature/task-namegit add -A && git commit -m "feat: …"git push -u origin feature/task-nameForgot to branch before starting work
Section titled “Forgot to branch before starting work”Nothing is lost — the changes are still uncommitted in the working tree.
git checkout -b feature/task-namegit add -A && git commit -m "feat: …"git push -u origin feature/task-nameThe pull request has commits from another branch
Section titled “The pull request has commits from another branch”This happens when you branched from a feature branch instead of main. Your
pull request now shows somebody else’s commits as yours. Fix it with an
interactive rebase, dropping the commits that do not belong.
# 1. Be on the right branchgit checkout your-branch-name
# 2. Reset to exactly what is on the remote — this undoes any earlier# half-finished attempt, which is usually why the next step misbehavesgit fetch origingit reset --hard origin/your-branch-name
# 3. See what you actually have, duplicates includedgit log --oneline origin/main..HEAD
# 4. Start the rebasegit rebase -i origin/mainIn the editor that opens:
- Press
Escfirst — this matters in Vim. - Delete every line that does not belong to this pull request (
dddeletes a line), or change itspicktodrop. - Leave only the commits that are genuinely yours.
- Save and quit with
:wq.
What goes wrong here:
Ctrl+C,:q!or:qa!abort the whole rebase rather than saving your edits.- Skipping the
git reset --hardin step 2 leaves debris from a previous attempt, and the rebase then behaves inexplicably. - Being on the wrong branch entirely.
- Running
git pullafterwards, which merges the old history straight back in and creates a mess. After a rebase you push, you never pull.
If you get conflicts, that is the rebase working, not failing:
git checkout --theirs path/to/file # keep your branch's versiongit checkout --ours path/to/file # keep main's versiongit add .git rebase --continueWhen it finishes, verify before pushing:
git log --oneline origin/main..HEAD # should show only your commitsgit push --force-with-lease origin your-branch-nameRebase went wrong and you want out
Section titled “Rebase went wrong and you want out”git rebase --abortIf that does not restore things, reset to the remote and start again:
git reset --hard origin/your-branch-nameBringing a branch up to date with main
Section titled “Bringing a branch up to date with main”git fetch origingit rebase origin/maingit push --force-with-leaseRules that prevent most of this
Section titled “Rules that prevent most of this”- Always branch from an up-to-date
main, never from another feature branch. - One issue, one branch, one pull request.
- Commit before you reorganise anything. A commit is recoverable; a dirty working tree is not.
git log --oneline origin/main..HEADbefore every push — it shows exactly what your pull request will contain.--force-with-lease, never bare--force.
