Rebasing history

Detaching commits and replaying them on top of main

git rebase offers an alternative to git merge: instead of creating a union commit, it "detaches" your local commits, advances your branch base to the tip of main, and replays your commits one by one with brand-new hashes.

Watch commits D and E detach and stack cleanly on top of C.
State: Divergent branches (before rebase)
main: A → B → C (tip de main)
feature: A → B ──┐ (fork)
└──→ D → E
Architecture decisions

Merge vs Rebase: Technical criteria and tradeoffs

Neither is universally better: they solve different engineering needs. Understand real tradeoffs to make informed choices based on team standards.

git merge

Historical Union

  • ✓ Preserves exact chronological truth
  • ✓ Never rewrites existing SHA hashes (safe)
  • ✕ Creates noisy merge commits ("Merge branch...")
  • ✕ Branch graph becomes a tangled web in large teams
When to use:

To merge completed Pull Requests into main and preserve team context.

git rebase

Linear Highway

  • ✓ Clean, readable, 100% linear history
  • ✓ Makes git bisect effortless to find bug regressions
  • ✕ Rewrites commit SHA hashes
  • ✕ Dangerous if applied to shared public branches
When to use:

In private local branches before opening PR to stay aligned with main.

Team safety

The Golden Rule: NEVER rebase public shared branches

Rewriting history on a branch where teammates are basing their work forces the entire team to abandon their trees and reconstruct branches manually. Breaking this rule damages technical trust.

🟢

Safe Case: Your private local branch

You are working on feat/my-task on your machine. Nobody else shares it. Running git rebase main is 100% safe, clean, and encouraged.

git switch feat/mi-tarea
git rebase main
🛑

Forbidden Case: Public shared branches (main / develop)

Rebasing main and forcing push with git push --force overwrites the server tree. Teammates’ commits become orphaned and desynchronized.

git push --force origin main # ✕ ¡NUNCA HAGAS ESTO!
Commit-by-commit resolution

Conflicts in Rebase: Do NOT use git commit here!

The most common beginner trap: when fixing a conflict during rebase, they run git commit and break the sequence. In rebase, after staging with git add, you resume with git rebase --continue.

1
Git pauses on conflicting commit

Notice appears: "Resolve all conflicts manually, mark them as resolved with git add...".

2
Edit file and remove markers

Remove <<<<<<<, =======, >>>>>>> and test your code.

3
git add <archivo>

Stages the resolved file into index.

4
git rebase --continue

DO NOT run git commit! This tells Git to apply the rebased commit and resume.

🛟 Something went wrong? Revert to pre-rebase state with: git rebase --abort
Commit semantics

Atomic commits and the Conventional Commits standard

A professional repository is defined by clear history. The Conventional Commits standard structures prefixes to enable automated changelogs and semantic versioning.

Build your standardized message:
Commit preview:
feat(auth): validate JWT bearer token expiration

✓ feat triggers a MINOR bump in SemVer (0.1.0 -> 0.2.0)

Repository hygiene

Rigorous .gitignore hygiene and git rm --cached

Never commit dependencies, compiled binaries, or secret environment variables. If you already accidentally committed a sensitive file, git rm --cached removes it from index without deleting it locally.

Standard .gitignore layout
# Dependencias
node_modules/
vendor/

# Variables de entorno y secretos
.env
.env.local
*.pem

# Compilación y builds
dist/
build/
*.class

# Archivos del sistema y del editor
.DS_Store
.idea/
.vscode/
The technical fix: git rm --cached

If you added .env to .gitignore but Git still tracks it, it was committed before. To stop tracking without deleting your local copy on disk:

git rm --cached .env
git commit -m "chore: stop tracking .env secret"

💡 File stays intact on your computer but is purged from the public repo.