Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Since you want to do this often, I assume your going to want to reduce to a single step process. I'll make this a bit educational though and break it down.</p> <h1>IMPORTANT</h1> <p>Don't do this sort of thing on any commits that have already been shared with other developer, or pushed to a remote. Rewriting shared history is a recipe for disaster.</p> <p>That public service announcement aside...</p> <h2>Step 1</h2> <pre><code>A---B---C---D (master, HEAD, ORIG_HEAD) git rebase --quiet --onto HEAD~2 HEAD~1 HEAD </code></pre> <p>This takes whatever is in HEAD that isn't in HEAD~1, and applies it to HEAD~2. After running this rebase, you will have this history. Keep in mind that <code>git-rebase --onto</code> will throw you into a headless state. (I've got <code>--quiet</code> in there so the final command doesn't spit a wall of text to your screen).</p> <pre><code>A---B---C---D (master, ORIG_HEAD) \ D' (HEAD) </code></pre> <p>Now we need to get <code>C</code> applied after <code>D'</code>, for this we can use <code>git-cherry-pick</code>. When a <code>git-rebase --onto</code> is performed as it was above, the original commit history before the rebase is saved in <code>ORIG_HEAD</code> because git wont change it until you do some other activity. This is useful in case you screw up a rebase, but we'll use it here to cherry-pick.</p> <h2>Step 2</h2> <pre><code>git cherry-pick ORIG_HEAD~1 A---B---C---D (master, ORIG_HEAD) \ D'---C' (HEAD) </code></pre> <p>The state of HEAD is now exactly as you wanted, with just two commands. I assume this will usually take place from within a branch, and that you'll want to update that branch with the new order of commits. If I'm wrong about that, then that's it and your done. If you do want update the branch you were on, there are a couple ways to do that. </p> <p>The simplest to do manually would be to do the following...</p> <pre><code>git log -1 ###copy the the SHA1 git checkout master git reset --hard &lt;SHA1&gt; </code></pre> <p>However the whole point is automation, and there ways of doing this that are less obvious, but require fewer commands. </p> <h2>Step 3</h2> <pre><code>git update-ref refs/heads/master $(git rev-parse HEAD) </code></pre> <p>By using <code>git-rev-parse</code>, I get only the commit of HEAD and nothing else. Applying that to `git-update-ref, I can "reset" the master branch without having to check it out first. Now that master is set properly, I can go ahead and checkout master (the point of the update-ref is to reduce the number of steps involved for the eventual alias/bash script).</p> <h2>Step 4</h2> <pre><code>git checkout --quiet master </code></pre> <p>Again, I pass <code>--quiet</code> so as to reduce the amount of text dumped on the screen after each command.</p> <h2>Bash Script</h2> <p>If you wanted to do this as a bash script, you could automate the entire process even further, and make it work dynamically on whatever branch you want, not just master.</p> <pre><code>#!/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 </code></pre> <h2>Git Alias</h2> <p>That said, this is just as easily dumped into a git alias without having to actually create a file for the bash script. Creating the file and setting up the alias isn't hard by any means, but it's another thing to understand, and many people don't. Here's a simple git alias, run this command once..</p> <pre><code>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" </code></pre> <p>Now anytime you want to flip your last two commits, just use...</p> <pre><code>git flip-last </code></pre> <h2>GitHub Gist</h2> <p>This was an interesting little script to write, I've thrown it up on a <a href="https://gist.github.com/eddiemoya/5456992" rel="noreferrer">github gist</a>. Feel free to fork it, make changes, star it, whatever.</p> <p><a href="https://gist.github.com/eddiemoya/5456992" rel="noreferrer">https://gist.github.com/eddiemoya/5456992</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload