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
and detachedHEAD
— 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. TheHEAD
is 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 whatgit reset --hard <revision>
when you’re on<branch_name>
. Not a big deal, but I like to have found about it.- the difference between
~
and^
— 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
that
^1
refers to the first parent of a merge commit, and^2
to 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” :)
revert
vs.reset
— I knew and used both of them, but in this tutorial I have found a new way to look at them: usereset
to undo commits that are not published on any remote, and revert for the others.cherry-pick
accepts 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.- clarified
fetch
and 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.