Mastering Git Rebase --onto: Moving Feature Branches Safely
Master git rebase --onto to move branches without breaking history. Learn the syntax, avoid common pitfalls, and master git branch maintenance easily.
You’ve been there: you started a feature branch off of feature-a, but your lead dev decided that feature-a is actually a separate release. Now, your work is stranded on a branch that shouldn't exist, and you're staring at a merge conflict nightmare. While many devs reach for git cherry-pick to move those commits, that approach creates duplicates and loses context.
The real power tool for this situation is git rebase --onto. It's the surgical instrument of Git history manipulation, allowing you to transplant a range of commits onto a new base with total precision.
Why use git rebase onto?
Most of us learn git rebase as a way to update our local branch with the latest from main. But standard rebasing can be blunt. If you want to move a specific chunk of commits that started at a certain point and ended at another, standard rebase often drags along unwanted history from the "middle man" branch.
git rebase --onto solves this by letting you define the "upstream," the "new base," and the "tip" of your branch. It effectively says: "Take everything from this point to that point, and graft it onto this new location." It’s an essential skill for Git workflow optimization when you need to prune your dependency tree without leaving a trail of duplicate commits.
The syntax explained
The command structure looks intimidating, but it follows a logical path:
git rebase --onto <new-base> <old-base> <tip>
<new-base>: Where you want the commits to end up.<old-base>: The commit before the first commit you want to move (the exclusive start point).<tip>: The current branch you are on (the inclusive end point).
Let's say you have a history like this:
A --- B --- C (main)
\ \
D --- E (feature-a)
\
F --- G (my-feature)
You want to move F and G so they branch directly off main (commit C), leaving D and E behind.
Bash# While on 'my-feature' git rebase --onto main E my-feature
Git will take the changes in F and G (the commits since E) and replay them onto main. D and E remain untouched in their original branch.
A real-world scenario
I once had to pull a set of three commits out of a massive, stalled feature branch that was blocked by a pending API migration. I didn't want to rebase the whole branch because it would have triggered a cascade of conflicts.
Instead, I used git rebase --onto.
- I identified the commit hash right before my work:
abc1234. - I identified my current head:
my-work-branch. - I ran
git rebase --onto main abc1234 my-work-branch.
It finished in about 4 seconds. Because I was performing surgery on my local history, I didn't need to worry about disrupting the team's shared state—just as long as I hadn't pushed those commits yet. If you're struggling with complex history, you might also find Git interactive rebase useful for cleaning up the individual commits after the move.
Comparison: Moving Commits
| Method | Best For | Risk Level |
|---|---|---|
git cherry-pick | Moving single, isolated commits | Low (duplicates) |
git rebase --onto | Moving entire logical sub-branches | Moderate (history rewrite) |
git merge | Combining full feature branches | Low (adds merge bubbles) |
Common pitfalls and safety
The biggest danger is rewriting shared history. If you've already pushed your branch to a remote, git rebase --onto will force you to git push --force. Never do this on a branch that other people are actively committing to, or you'll cause a synchronization headache for the whole team.
If things go sideways, don't panic. Git tracks your movements in the reflog. You can always revert to your state before the rebase by running git reset --hard HEAD@{1}.
FAQ
Can I use this to move a branch to a different main branch?
Yes, that’s exactly what it’s for. It’s perfect for git branch maintenance when you realize a feature belongs in a different release cycle.
What if I have merge conflicts during the rebase?
Git will pause the process. Resolve the conflicts in your files, run git add <file>, and then git rebase --continue. It’s no different from a standard rebase.
Should I use this over git cherry-pick?
Use cherry-pick for one or two commits. Use --onto when you have a sequence of commits that represent a logical unit of work. It preserves the original commit metadata much cleaner than picking them one by one.
Final thoughts
I still find myself reaching for git cherry-pick when I'm being lazy, but git rebase --onto is objectively better for maintaining a clean, linear history. It keeps your repository readable and makes your PRs much easier to review.
Next time you find yourself with a branch that’s anchored to the wrong place, try the --onto flag. Just remember to check your reflog first. If you're managing complex projects and need help with Laravel bug fixes, maintenance & optimization, keeping your Git history tidy is often the first step in stabilizing the codebase.