176

Is there a way to rebase a single commit from a branch onto another branch?

I have this branch structure:

-- -- -- -- -- (Master) \ -- -- -- -- -- XX (Feature-branch) 

All I want to do is to rebase the last commit of Feature-branch onto master and rollback Feature-branch one commit.

-- -- -- -- -- XX (Master) \ -- -- -- -- -- (Feature-branch) 

How do I do that?

3
  • 3
    If you can rebase any number of commits then why do you ask about rebasing a single one? If I could ask questions in SO, I would ask what is the difference between rebasing (a single commit) and cherry-picking. Commented Jun 4, 2013 at 13:03
  • 20
    Because I didn't know that cherry-picking existed, and I do "Faff about on branch", "Get request for fix on different branch", "fix it", "Commit to wrong branch", "D'OH!" enough that asking the question was useful. Commented Apr 1, 2014 at 23:38
  • Because the command syntax to rebase a single commit from a stack is far from obvious. Commented Aug 26, 2022 at 2:08

4 Answers 4

168
git rebase --onto master branch~1 branch 

This says "rebase the range of commits between last-before-branch and branch (that is, XX commit) on the tip of master branch"

After this operation branch tip is moved on commit XX, so you want to set it back with

git checkout branch git reset --hard branch@{1}^ 

Which says "reset the branch tip to the commit before its previous state"

So a cherry pick is a simpler solution...

Sign up to request clarification or add additional context in comments.

5 Comments

This doesn't seem to work for me, I lose the commits before XX and the branch is rebased to master with a single commit, but I never used --onto before so I may be doing something wrong. BTW the OP said rebase but it seems like he wants to do a cherry-pick.
my error, rebase does indeed move the branch on master, it has to be reset
What is the practical difference between this solution and the one by tewe?
@Lii the only I can see is that it uses 3 steps instead of 4
@Lii This one is much more generic. I had a branch where I wanted to rebase to master, and I only wanted to rebase all but the first 4 commits (let's call the 4th one X). So I only had to do: git rebase --onto master X branch
162

You can cherry-pick XX to master.

git checkout master git cherry-pick <commit ID of XX> 

And remove the last commit from the feature branch with git reset.

git checkout Feature-branch git reset --hard HEAD^ 

9 Comments

how can a question specifically called 'git rebase ...' have the accepted answer than contains a cherry-pick, which is a totally different concept and sometimes per se considered unclean?
Not sure if this is relevant, but the commit I wanted to rebase had some files that were moved, and cherry-pick made them appear as if they were deleted from the old location and created at the new location. I suppose rebase would have taken care of that, but by now I've pushed upstream so I can't test that. In any case, beware if you have a similar situation.
Note: to push you changes in Feature-branch to origin you'll need to git push -f origin Feature-branch as your Feature-branch is now considered to be 1 commit behind the origin/Feature-branch.
What is the practical difference between this solution and the one by CharlesB?
@Bondax: Because they’re not totally different concepts by any means. They‘re closely enough related that if you know rebasing, but have never heard the term “cherry-picking”, it’s pretty natural to come up with the idea of cherry-picking and describe it as “rebasing a single commit”.
|
119

It's pretty simple to do actually. The solution is to do an interactive rebase and "drop" all of the commits you don't want to include in the rebase.

git rebase -i <target_branch> where target_branch is the branch you want to rebase on to

Then you will edit the file that is opened and pick the commits you do want and drop (or d for short) all the commits you don't want to bring along.

9 Comments

IMO a much better solution, and it actually addresses the question.
This should be the accepted solution given how general, intuitive, and short it is.
+1 git rebase -i is my favourite Git command. It is so flexible and in the same time so simple and clear exactly what is happening. You don't have to memorize any other rebase command if you learn git rebase -i.
Be aware that the commits you do not pick are "lost" unless they are on a different branch. Or "left behind" like git calls it.
@PabloArias " intuitive, and short it is" is clearly overstatement. "Then you will edit the file that is opened..." part of the answer does not make this answer a short and intuitive solution. tewe's answer requires fewer steps, less typing and fewer places to make an error.
|
0

@Charles response is correct. Anyway I ended up using this so many times, most of all to rebase specific config on a project

 * a8f9182 (HEAD -> production) production configuration | * daa18b7 (pre) preproduction configuration |/ | * d365f5f (local) local configuration |/ * 27d2835 (dev) amazing new feature that will save the world * | 56d2467 (master) boring state of the art for project |/ 

that I create a new command for it:

 $ cat ~/bin/git-rebaseshot COMMIT=$1 DEST=${2:-HEAD} git rebase ${COMMIT}^ ${COMMIT} --onto $DEST 

normally you want to autocomplete branch names for that command, so add it sourcing this function (adding to .bashrc or .profile):

 _git_rebaseshot () { __gitcomp_nl "$(__git_refs)" } 

git autocomplete will search for it

you can use this command like this:

# rebase config on prepro on actual HEAD $ git rebaseshot prepro # rebase config on local onto dev $ git rebaseshot local dev # rebase production config on master $ git rebaseshot pro master 

When you divide features correctly, possibities are endless.

 * a8f9182 (HEAD -> postgres) BBDD config * a8f9182 (local) local config * a8f9182 (debug) log level config * a8f9182 (dev) new feature | 

I guess this is what quilt people like to do.

this command will work anyway with whatever sha/ref you provide:

$ git rebaseshot <Feature branch> master $ git rebaseshot <commit of XX> master 

3 Comments

// , Can you link to any project where we can see this in action?
For its nature, branches avaliable for rebaseshot are not commited outside local repo. Just create several branches on top of master (log level, database connection, configuration) and use command between them. Is plain to see the effect.
// , I ran into some problems. I'll try it again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.