Git for team projects: commits, branches, rebase and incident recovery Intermediate
This page maps the Git cluster: which question each part answers, the order to read them in, and the sensible defaults.
The problem
Section titled “The problem”Three months after a release, production computes prices wrong. git log has 40 commits named fix, wip, update, and one 3,000-line commit mixing a refactor with a logic change. revert takes another feature down with it, and bisect is useless because half the commits do not build.
Git does not break projects. Git habits do. This cluster collects the rules that turn commit history into a debugging tool instead of a junkyard.
Reading flow
Section titled “Reading flow”Loading diagram…
In this cluster
Section titled “In this cluster”| Part | The question it answers |
|---|---|
| Commit messages & atomic commits | How do you write a message? What should one commit contain? |
| Branch, merge, rebase | Trunk-based or GitFlow? Merge, rebase or squash? How do you force push safely? |
| Recovery | Accidentally reset --hard, pushed a bug to main, need to find the commit that caused a bug — which command? |
| Secrets, PRs and checklist | What do you do first when a secret leaks? How big should a PR be? What do you review? |
| Common mistakes | Common wrong commands/habits, side by side with the right way |
Decision summary
Section titled “Decision summary”| Question | Default choice | Reason |
|---|---|---|
| Commit message | Conventional Commits, subject ≤ ~50 characters, imperative mood | Readable in git log --oneline, generates changelogs and SemVer automatically |
| Commit size | Atomic: one logical change, build and tests pass | revert, cherry-pick, bisect work |
| Branching | Trunk-based, short-lived branches (≤ 1-2 days) + feature flags | Fewer conflicts, CI reflects the real state of main |
| Merging a PR | Squash merge for small PRs; a merge commit when the PR consists of deliberate commits | One PR = one commit that is easy to revert |
| Syncing your branch | git rebase origin/main when only you use the branch |
Linear history, no junk merge commits |
| Pushing after a rebase | --force-with-lease, never --force |
Does not overwrite commits someone else just pushed |
Incident on main |
git revert, not reset + force push |
Does not rewrite history others are using |
| Leaked a secret | Rotate first, rewrite history later | Clones, forks and caches already have the secret; a rewrite cannot recall them |
Self-check:
- You just ran
reset --hardand lost 3 unpushed commits — which command recovers them, and can it recover files that were nevergit added? - Why can
--force-with-leasestop protecting you when your IDE runsgit fetchautomatically? - What exit code should a
git bisect runscript return when the project does not build at the commit being tested? - Which part of SemVer does the commit
feat(api)!: remove legacyId fieldbump?