A step-by-step playbook for resolving merge or rebase conflicts safely. Run the steps in order -- skipping ahead is how clean working trees get clobbered. Every step has an exit ramp (--abort) so you can back out at any point until the final commit.
If anything is staged or modified, commit it, stash it, or discard it. Never start a merge with a dirty tree -- conflicts will mix your in-progress work with the merge resolution and you will not be able to tell them apart.
# Stash if you want to keep work-in-progressgit stash push -u -m "wip before merging main"
A conflict resolved against a stale main is wasted work -- the real conflicts are still ahead of you. --ff-only refuses to silently merge if your branch has diverged.
git rev-parse HEAD# write this SHA somewhere -- a sticky note, a scratch file, anywhere
If everything goes wrong, git reset --hard <that-sha> puts you back exactly where you started. git reflog works too, but a written-down SHA is faster under stress.
Git prints exactly which files conflict and what kind of conflict each is (content vs. add/add vs. delete/modify). Read this list. Do not start opening files until you know how many conflicts you have and where they are.
git status# Look for "Unmerged paths" -- that is your work list
# Get a clean list of just the conflict filesgit diff --name-only --diff-filter=U
<<<<<<< HEAD
your version (the branch you are merging INTO)
=======
their version (the branch you are merging FROM)
>>>>>>> main
During a rebase, the labels are inverted: HEAD is the base branch you are rebasing onto, and the >>>>>>> side is your incoming commit. This catches everyone off guard at least once.
# Show the full diff with both sidesgit diff# Or for one specific filegit diff -- path/to/file.ts# See who wrote each side and whygit log --merge --oneline -- path/to/file.tsgit log -p HEAD..MERGE_HEAD -- path/to/file.ts
Knowing why each side made a change -- not just what it changed -- is the difference between a real resolution and a guess that compiles.
# For a merge: what will the merge commit contain?git diff HEAD# For a rebase: how does my branch differ from before?git range-diff <starting-sha>..ORIG_HEAD <starting-sha>..HEAD
If the diff has files you did not touch or expect, something went wrong. Stop and investigate before committing.
# Merge: regular push is finegit push# Rebase: force-push, but ONLY to your own branches and ONLY with --force-with-leasegit push --force-with-lease
--force-with-lease refuses the push if someone else committed to the remote branch since you last fetched -- it is the difference between rewriting your own history and overwriting a teammate's commit. Never --force (without -with-lease) on a shared branch.