A Few Git Tips
This weekend I had the opportunity to attend Scott Chacon’s Advanced Git class at Jumpstart Lab. Scott works for Github and maintains the Git project’s website. He’s also written a book, ProGit, and the handy reference site Git Reference.
Scott spent a good bit of time going over the fundamentals of Git–the different types of objects stored in its database and how they point to one another. I had seen all this before when I first started using Git, but I wasn’t ready to really understand it then. If you’ve ever felt that Git was a bit mysterious or scary I’d highly recommend going over the basics again. Try this article and these two sections of Scott’s book.
Here are some other useful tips I picked up:
- Ever go to commit a file and realize that only some of your changes are relevant to the current commit? Use
git add -p
to stage just parts of a file. – Don’t know how all of your branches relate to the current branch?
git branch --merge
shows all the branches that have already been merged into the current branch, and
git branch --no-merge
shows branches that have not been merged. – Ever work for a little while on master, then realize you really should have been in a topic branch? It’s not too late! Create your branch with
git branch myTopic
.
Then put master back to the state is was at in the last pull:
git reset --hard origin/master
.
You could also put the SHA of a particular commit if you don’t want to go that far back. Then switch back to your new branch with
git checkout myTopc
and keep working. – Not sure who the last person to change some particular piece of code was? Use
git blame
to show which user last touched each line of a file. Want to know how code has been copied between files? Use
git blame -C
to show when parts of a file were copied out of another file.
There are also a whole slew of shortcuts git uses for naming commits. The basic ways to reference a particular point in the history are by a branch name, tag name, or SHA-1 (full or prefix.) In addition, git provides the following relative specifiers, which can be based off of any branch, tag or SHA:
master~
is the parent commit of master.master~2
is the grandparent.master~3
is the great-grandparent, and so on.master^2
is the second parent of a merge commit.master~2^2
is the second parent of the grandparent of the commit.master@{yesterday}
is the last state of master yesterday.master@{3.weeks.ago}
is the state of master three weeks ago.HEAD@{1}
is the previous state of HEAD, which could be many commits away if there was a fast-forward merge.
Some commands, like log
or show
, can also take a range of commits.
git log master..myBranch
shows all commits since myBranch diverged from master. Leaving off either commit implies HEAD. So
git log origin/master..
shows how your local master has progressed since the last fetch. Or if you’ve just done a fetch,
git log ..origin/master
shows what’s new from origin.
Got any of your own tips to share? Did I get something wrong? Feel free to leave a comment.