Skip to content

Instantly share code, notes, and snippets.

@eddiemoya
Last active September 6, 2018 08:55
Show Gist options
  • Save eddiemoya/5456992 to your computer and use it in GitHub Desktop.
Save eddiemoya/5456992 to your computer and use it in GitHub Desktop.
Flip the last two commits in a branch using git-rebase, git-cherry-pick, git-update-ref, git-name-rev, and git-rev-parse. Interesting exercise using quite a bit of plumbing commands.
#!/bin/bash
branch=$(git name-rev --name-only HEAD)
git rebase --onto HEAD~2 HEAD~1 HEAD
git cherry-pick ORIG_HEAD~1
git update-ref refs/heads/$branch $(git rev-parse HEAD)
git checkout --quiet $branch
# Instead of creating an independant bash script with the code above,
# consider simply creating a git alias using the command below.
#
# USAGE: git flip-last
git config --global alias.flip-last '!branch=$(git name-rev --name-only HEAD); git rebase --quiet --onto HEAD~2 HEAD~1 HEAD; git cherry-pick ORIG_HEAD~1; git update-ref refs/heads/$branch $(git rev-parse HEAD); git checkout --quiet $branch'
@fcamblor
Copy link

fcamblor commented Sep 6, 2018

FYI, I have a concern about your gist : if something fails during either rebase or cherry-pick, you don't help the user and, worst, you reset his actual branch to the currently-in-failure sha1

I fixed those concerns in my fork here

  • I use a temporary branch for my manipulations, resetting current branch only at the last step (only if everything went well before)
  • I prefer to reset + cherry-pick 2 commit instead of rebase then cherry pick. In that case, I only have 1 potential failing step (the cherry pick) instead of 2 in your case (1 during rebase, the other during cherry pick)
  • If something goes wrong, I warn the user and give him the command to execute to "resume" his work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment