Day 24: Commit, branch, merge, rebase fundamentals
Git is a graph, not a folder of snapshots
Every commit points to its parent(s), forming a directed acyclic graph. A branch is just a movable label pointing at one commit — creating a branch is instant precisely because it copies nothing, only a pointer. Understanding this graph model is what makes rebase, bisect, and cherry-pick (Day 25) feel obvious instead of magical.
Merge vs rebase
A merge creates a new commit with two parents, preserving both histories exactly as they happened — honest, but the history graph gets tangled with merge commits. A rebase replays your branch's commits one-by-one on top of a new base, producing a linear history — cleaner to read, but it rewrites commit hashes, which is why you never rebase commits that have already been pushed and shared.
git checkout -b feature/add-login
# ... make commits ...
git fetch origin
git rebase origin/main # replay your commits on the latest main
git push --force-with-lease # safe force-push: fails if remote has commits you haven't seenforce vs force-with-lease
Plain git push --force silently overwrites whatever is on the remote, even if a teammate pushed in the meantime. --force-with-lease refuses if the remote has moved since you last fetched — always prefer it.
Key terms
- Branch
- A movable pointer to a commit — cheap to create because nothing is copied.
- Merge commit
- A commit with two parents that combines two histories without rewriting either.
- Rebase
- Replaying a branch's commits onto a new base commit, producing linear history but new commit hashes.
Why should you avoid rebasing commits that have already been pushed and pulled by teammates?