A Hacker’s Guide to Git is now available as an e-book. You can purchase it on LeanPub.
Git is currently the most widely used version control system in the world, mostly thanks to GitHub. By that measure, I’d argue that it’s also the most misunderstood version control system in the world.
This statement probably doesn’t ring true straight away because on the surface, Git is pretty simple. It’s really easy to pick up if you’ve come from another VCS like Subversion or Mercurial. It’s even relatively easy to pick up if you’ve never used a VCS before. Everybody understands adding, committing, pushing and pulling; but this is about as far as Git’s simplicity goes. Past this point, Git is shrouded by fear, uncertainty and doubt. (Read more)
Most Bower packages will be fetched using a git:// URL, which connects on port 9418. This can be problematic if you’re behind a firewall which blocks this port.
You can get around this quite easily by telling Git to always use https:// instead of git://:
git config --global url.https://.insteadOf git://
Quite often I’ve accidentally typed “git” twice. Usually this is fine, and Git just does something like this:
$ git git diff
git: 'git' is not a git command. See 'git --help'.
Did you mean this?
But I recently turned on Git’s autocorrect feature, to see what it was like (
git config --global help.autocorrect 1). The results were… interesting:
$ git git diff
WARNING: You called a Git command named 'git', which does not exist.
Continuing under the assumption that you meant 'init' in **0.1 seconds** automatically...
fatal: internal error: work tree has already been set
Current worktree: /nfs/personaldev/vagrant/mobileweb-v2
New worktree: /nfs/personaldev/vagrant/mobileweb-v2/diff
This is really bizarre behaviour. The fact that it wants to autocorrect it to
git init is sort-of okay. But rather than giving me the option to confirm that this is what I want, Git gives me a whole 0.1 seconds to hit Ctrl+C before it automatically runs the command for me.
git init isn’t a very destructive command. I was lucky that the only side effect of this was that Git created a new directory called
diff. I can’t help but wonder what would’ve happened if Git decided to autocorrect to a more destructive command like
The lesson here? Don’t use Git’s autocorrect. It really sucks.
Update: m_bright pointed out that the value of (Read more)
help.autocorrect is actually how many tenths of a second Git will wait before automatically executing the command. So something like
git config --global help.autocorrect 10 would give you 1 second before the command is executed, which is probably slow enough to let you cancel any mistakes, and quick enough to still be useful.
There are often times when you want to modify a file but not commit the changes, for example changing the database configuration to run on your local machine.
Adding the file to .gitignore doesn’t work, because the file is already tracked. Luckily, Git will allow you to manually “ignore” changes to a file or directory:
git update-index --assume-unchanged <file>
And if you want to start tracking changes again, you can undo the previous command using:
git update-index --no-assume-unchanged <file>
Easy! (Read more)
Today I found out just how easy it is to convert an SVN repository to Git without losing any commit history. Note that you will need git-svn (
apt-get install git-svn on Debian/Ubuntu).
git svn clone http://mysvnrepo.com/my-project my-project
git remote add origin firstname.lastname@example.org:/my-project.git
git push origin master
Et voilà, my-project.git has the full commit history of the my-project SVN repository.
If anybody knows whether SVN branches can be converted to Git branches, please get in touch! (Read more)
Name and email address
Each commit you make has your name and email address attached to it. Git will automatically configure these based on your username and hostname, but this information is usually not a good identifier. It is a good idea to set your real name and email address so that your commits can be identified easily.
git config --global user.name "Your Name"
git config --global user.email email@example.com
Global ignore file
Often there are files or directories that you want Git to ignore globally. These are probably created automatically by your IDE or operating system. Git’s
core.excludesfile config allows you to write a global .gitignore so that you don’t have to fill local .gitignore files with clutter.
git config --global core.excludesfile /path/to/.gitignore_global
Git’s (Read more)
archive command is basically the equivalent of SVN’s
export – it dumps a copy of the entire repository without any of the version control files, making it perfect for deploying to a testing or production server.