git: obtain the benefits of `git rebase –interactive` for cherry picks
I’d like to be able to do this:
git cherry-pick --interactive hash-0..hash-n-1 # fantasy command
and obtain the same workflow as interactive rebase: an editor buffer comes up, containing:
pick hash-0 pick hash-1 pick hash-2 ... pick hash-n-1
where I can delete any unwanted commits,
squash them together, or
edit to pause between the picks to do some manual fixup (like
commit --amend) and all that.
Note how the
pick of interactive rebase is tanalizingly like
Now the above operation can be done by performing the cherry-pick first, and then the interactive rebase, which is inconvenient. That is:
$ git tag old-head # mark starting point for later rebase $ git cherry-pick hash-0..hash-n-1 # get everything first $ git rebase --interactive old-head # okay now rebase "in-branch" to fix it up
It’s not only inconvenient because of the two steps but because it may require resolving conflicts in commits you don’t even want that will be discarded in the rebase stage.
3 Solutions collect form web for “git: obtain the benefits of `git rebase –interactive` for cherry picks”
Okay, figured out a nice hack.
Start a trivial
rebase --interactive HEAD^ over one commit in your current branch. You get something like:
pick 1efd396b * Fixed a bug in frob function
Now, just paste in additional hashes that you want to pick:
pick 1efd396b * Fixed a bug in frob function pick f01934db * Awesome feature added pick 6fd109c1 * Refactored the widgets layer squash 3900fd77 * Refactored the widgets layer s'more
Save and exit, and wee: the
rebase mule obligingly takes the additional cruft you loaded on its back and incorporates it into the current branch according to the commands.
You can actually do an empty rebase with:
git rebase --interactive HEAD
you get a buffer containing
You don’t have to delete that; just add your picks after that.
Addendum: To produce the pick lists for this method, use
git log --oneline --reverse from..to, then trim the output needed and prepend the rebase commands to each line:
Okay, following up on Carl Norum’s suggestion, I looked into the
--onto argument of
The use case can be satisfied like this, which is an improvement, though still involves a somewhat excessive number of steps.
The primary issue is that rebase needs a current branch to pick from so we have to shift our coordinates to a temporary branch, and then manipulate our original branch head afterward and delete the temporary branch.
The flow looks like this:
# We are originally on "mybranch" # We create a temp-branch pointing to the last commit to be picked: hash-n-1 $ git checkout -b temp-branch hash-n-1 # create branch at last hash # Then we rebase from the point before the first hash, onto our original branch $ git rebase --interactive hash-0^ --onto mybranch # The above rebase should make "temp-branch" into the very object that # we want "mybranch" to be. If it looks that way, then all that is left is # make it so: $ git checkout mybranch $ git reset --hard temp-branch $ git branch -D temp-branch
git rebase --interactive hash-0^ --onto mybranch uses the commit before
hash-0 as the “upstream” for the rebase, taking all the commits from the current branch (based on
hash-n-1) which are not in the upstream. Those commits are, of course,
hash-n-1. They are rebased onto the
mybranch head, but it is the current
temp-branch which is
reset --hard to track the result. So we just have to assign that pointer to
mybranch and delete
It’s fairly clumsy, but eliminates the duplicate cherry-picking, and is easy to recover from at any time just with
git reset --hard mybranch.
(Can this still be improved.)
Perhaps a better answer is out there, but this might work for you
git cherry | awk '$0=$2' > cherry.txt "$EDITOR" cherry.txt git cherry-pick --stdin < cherry.txt