My Git trail map
In my last article I said that I have started a little study by following thoughtbot’s trail maps. After Heroku, I’ve picked Git, and today I will write about the things I’ve learned from it.
My favorite part was the “Learn Git Branching” interactive tutorial. Its gorgeous animated visualizations help a lot in understanding the mechanics of rebase, merge, branch reset, and cherry-pick. It also has practical exercises at the end of every lesson.
I thought I knew Git good enough to use it, how could I not — I’m using it for the last few years, right? It turned out that I had some blind spots which I’m glad this tutorial covered. :) Here they are:
- what is
HEAD— this is something that I see a lot while working with Git, and somehow I accepted it lie around without actually understanding it. So although it’s a pretty simple concept — the revision where you’re currently on. It’s somewhat similar to the “cursor” concept in databases. The
HEADis said to be detached when it points to something that is not a branch, and when it is, you cannot commit; you can only commit onto a branch. It may be insignificant, and I would have probably been able to happily live without understanding it, but it feels a little better now when I know what it is. :)
git branch -f <branch_name> <revision>— resets the head of the given branch to the given revision. Now that I’m typing it I realize that it does what
git reset --hard <revision>when you’re on
<branch_name>. Not a big deal, but I like to have found about it.
- the difference between
^— this is something that I was wondering about, but because I could work without it, I never went on to find out about. Here is the formula I wrote in my notes:
HEAD~ == HEAD~1 == HEAD^1 == HEAD^. Other than that:
^<revision>reads as “parent of
<revision>”, and you can use it three times to mean “parent of parent of parent”, but it’s easier to just say ~3 instead, although it may mean something different when
<revision>is a merge commit.
- merge commit parents — another one of those that I didn’t fully
understand, but it turned out I was able to live without. Now I know
^1refers to the first parent of a merge commit, and
^2to the second. I have always preferred rebasing to merging, and this way I just avoided it. After this tutorial I just can’t not get it. :)
- you can chain multiple ~N\^N for — this is a geeky one: HEAD~2\^2 reads as “the second parent of the commit before the 3rd last” :)
reset— I knew and used both of them, but in this tutorial I have found a new way to look at them: use
resetto undo commits that are not published on any remote, and revert for the others.
cherry-pickaccepts multiple SHAs (!) — I think I have tried that at some point and it didn’t, so I’m glad I found out that it now does.
fetchand remote branch merging — this is definitely easier seen than read — and this is one that I think it’s bigger than others and I’m even more glad I “got.” I now understand where those merge commits come out when I pull, and more importantly: how to prevent them. :)
So, in the end, even if I knew how to do most of the things in the “Advanced” section of the trail, I’m glad I have walked through it.