Git and GitHub · Intermediate
Rebase, conflicts and recovering lost work
Why it matters
On a team, main moves while you work. You will need to bring your branch up to date, resolve conflicts and occasionally undo a mistake under pressure. Engineers who can do this calmly unblock everyone; engineers who cannot tend to lose work or break shared branches.
The concept
Merge combines histories with a merge commit. It never rewrites existing commits: safe on shared branches.
Rebase replays your commits on top of another branch, producing a straight history. It rewrites your commits (new ids), so only rebase branches that others are not building on, and push with
--force-with-lease.Conflicts happen when both sides changed the same lines. Git stops, marks the file, and waits for you to choose.
The reflog records every position your branches pointed to, locally, for about 90 days by default. Almost nothing committed is ever truly lost.
Worked example: main moved while you worked
Continuing from Everyday Git in fifteen commands, a teammate changes report.sql on main while your feature/zone-report branch is open:
git switch main
printf 'select count(*) from trips where fare_amount >= 0;\n' > report.sql
git commit -am "Exclude refunds from trip count"
git push
git switch feature/zone-report
git fetch origin
git rebase origin/main
git log --oneline --graph --all* 7768397 Add trips per pickup zone <- your commit, replayed on top of main
* 820410e Exclude refunds from trip count
| * 166b8aa Add trips per pickup zone <- the old copy, still on origin/feature/zone-report
|/
* aab2d4e Add trip count reportYour commit has a new id because it was rewritten. The remote branch still has the old one, so update it safely:
git push --force-with-lease # refuses if someone else pushed to this branch meanwhileWhen a conflict happens during a rebase or merge:
git status # lists files with conflicts
# edit each file: keep the right lines, delete the <<<<<<< ======= >>>>>>> markers
git add report.sql
git rebase --continue # or: git merge --continue
# changed your mind?
git rebase --abort # back to exactly where you startedRecovering "lost" work:
git reset --hard HEAD~1 # oops: the last commit is gone from the branch
git reflog # find it, e.g. "7768397 HEAD@{1}: commit: Add trips per pickup zone"
git reset --hard 7768397 # the branch points at it againCommon mistakes
Rebasing a shared branch such as
main. Everyone else's history breaks. Rebase only your own branches.git push --forcewithout lease. It can silently delete a teammate's commits. Use--force-with-lease.Resolving conflicts without running tests. A conflict-free merge can still be wrong; run the checks.
Panicking after
reset --hard. Check the reflog first.
Interview angle
"Merge or rebase?" Answer: merge preserves history and is safe on shared branches; rebase gives a linear history for your own feature branch before review. Say which your team preferred and why, and mention --force-with-lease. "How would you undo a commit that is already on main?" Use git revert, which adds a new commit that undoes it, instead of rewriting shared history.
Practice task
Create a conflict on purpose in a practice repository and resolve it both with merge and with rebase.
Delete a branch with unmerged commits, then recover it from the reflog.
Use
git revertto undo a commit onmainand read the resulting history.