rebase
Rebase is one of the most powerful feature of git, and probably most dangerous one too.
As it rewrites history, you have to ensure the history you'll be writing makes sense, and doesn't loose some bits.
If you happen to actually loose some things,
git reflog might help you find them back.
Anyway, back to rebase. Imagine you have this bunch of commits you want to publish, but hey, the first one on your pile needs a tweaking in the comment.
So you have:
trunk -> A -> B -> C
trunk is what's in Subversion, and A, B and C are your local commits. A needs some tweaking. Easy:
- Tweak what you want, and write it how you'd like it
- Commit it, this will give you D
- Rewrite history up to A:
git rebase -i HEAD~4 (or you could use git rebase -i A, if A is a SHA1)
This should open your favorite editor with this:
pick A Item...: the comment for A
pick B Item...: the comment for B
pick C Item...: the comment for C
pick D blah
So edit this list, and rewrite it like that:
pick A
squash D
pick B
pick C
This will squash (merge) commits A and D into one commit, and leave the rest as is, which is exactly what we want!
Now, you just have to
dcommit, and nobody will ever know about A.
As you'll be squashing commits, it will ask you for a commit message of the newly created merge commit. Usually, you'll want to keep the first one only, but you're free.
Bisect
Git offers a really powerful tool: bisection!
When you have something that has changed, and you want to know which commit did it, then you'll need bisect.
Here is an example I used today, but I've used it many times to find the root cause of a failing unit test.
Foswiki:Main.MichaelDaum found out that his
NatSkinPlugin was missing the dependencies field in the topic. Normally, this is just a matter of adding a %$DEPENDENCIES% inside the plugin's topic, thus the idea was to find out when this was lost.
So bisect!
- First, tell git you want to bisect:
git bisect start
- Then, tell it your current code is bad:
git bisect bad
- Pick a checkout where the code was known to be good. Here it was tricky, thus we simply picked the first checkin of this plugin:
PAGER=tail git log NatSkinPlugin
a more clever way to do this is:
git rev-list --topo-order HEAD NatSkinPlugin|tail -1
- Checkout this code (here both command on my git returned b971f71abc07e398ff6e0449991da21a2aacc263 as the revision):
git checkout b971f71abc07e398ff6e0449991da21a2aacc263
grep -r %\$DEPENDENCIES% NatSkinPlugin/
git bisect good
This will output some text, the number or revisions left to test, and the current one it's testing, and it will checkout you to the one that needs testing.
git bisect run grep -r %\$DEPENDENCIES% NatSkinPlugin/
This should output the information about the last commit:
a81d4f3479b6e3fd2dc2934a90c1a0f1985e9220 is first bad commit
commit a81d4f3479b6e3fd2dc2934a90c1a0f1985e9220
Author: MichaelDaum
Date: Thu Jan 8 10:52:53 2009 +0000
Item697: reverted SYSTEMWEB to TWIKIWEB for foswiki/compat plugins
git-svn-id: http://svn.foswiki.org/trunk@1871 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
:040000 040000 c862145efc23fce6dc7f88ca2ef03389b0482ea5 b719f8955685d5e9837af30c31696ae567493e63 M NatSkinPlugin
You may then review that
Foswikirev:1871 was indeed the bad commit.