These are the commands I use on a daily basis. Hopefully this helps explain and put to rest the fear of rebase.

I have aliases for these that mostly came from Phil Haack.

The below commands assume your mainline branch is named 'main'. Adjust accordingly if it's called 'master,' 'trunk', etc.

# Start day getting latest
git checkout main
# Create a new branch
git checkout -b features/my-feature
# work for a half hour
git add -A
git commit -m "Did some work"
# push branch to remote in case I die
git push --set-upstream origin features/my-feature
# work another couple of hours, occasionally syncing to remote
# (one liner)
git add -A && git commit -m "Did some other work"
git push
# ready to submit PR. I want my code to be *after* the latest, so . . .
git checkout main
git pull [gets latest changes]
git checkout feature/my-feature
git rebase main
# deal with any merge conflicts, then squash and force push
git rebase main --interactive [I squash all commits into one]
git push --force
# I'm done. Create the pull request.


Isn't rebase bad and you should never ever do it because everyone says so?

No. Rebase is good and you're listening to the wrong people. It's what significantly reduces merge conflicts in your pull requests. What's bad is not understanding what rebase does and what problems it could cause.

When rebasing onto main, you're saying, "If I merge my changes into main now, they'll be in the middle of what's already committed. I want them at the end. So take my changes and apply them to the end of main as if I just made them."

From Git's point of view, these are new commits, so they get new file hashes. That's why you have to force-push them, overwriting the remote branch.

This is OK as long as:

  1. You do not ever rebase main onto a branch and then push main.
  2. If someone else is working on your branch with you, you tell them to git pull --force.

The first one you should never, ever even think of doing. The second one is rare because developers tend to work indepedently on short-lived branches.

When it comes to merge vs rebase, the directions of change are always:

Merge from branch into main. Rebase branch onto main.

When you "merge from", you start in main. When you "rebase onto" you start in the branch.

What about merge conflicts?

That's a whole other topic. What matters is using a good diff/merge tool. The one I use, KDiff3, is really old but I like it best.