git rebase main takes each commit on your branch, undoes it, fast-forwards to main, and re-applies your commits one by one on top. The result looks like you started your feature from the current main instead of an older one.
Each replayed commit gets a new hash — same content, different parent, different identity. That's the catch: rebase rewrites history.
Merge vs rebase: merge preserves what actually happened (with a merge commit); rebase rewrites the story to look linear. Neither is "better" — they're different tradeoffs.
The golden rule: never rebase commits you've already pushed and shared. Rewriting public history forces everyone else to reset their copy. Rebase your local feature branch before pushing the first time; after that, prefer merge.
git pull --rebase rebases your local commits on top of what was just fetched, avoiding a merge commit on every pull.