Some git-fu I’ve been finding particularly useful recently:
- Untangling concurrent changes into multiple commits:
git add -pis the greatest thing since sliced bread. But did you know it features an ‘s’ command which allows you to split a hunk into smaller hunks? Now you can untangle pretty much anything. - Splitting a previous commit into multiple commits: I’ve been finding this one
useful for quite a while. Start with a
git rebase -i, mark the commit(s) asedit, and once you get there, do agit reset HEAD^. All the changes in that commit will be moved out of the staging area, and you cangit add/git committo your heart’s content. Finish with a quickgit rebase --continueto the throat. - Fixing your email address in previous commits: I often make a new repo and
forget to change my email address. (For historical, and now silly, reasons, I
like to commit to different projects from different addresses, and I often
screw it up.) Here’s how to do a mass change:
git filter-branch --env-filter "export GIT_AUTHOR_EMAIL=your.new.email.address" commit..HEAD, where commit is the first commit to be affected. Of course, changing the email address of a commit changes its id (and the id of all subsequent commits), so be careful if you’ve published them. (Also note that using--env-filter=...won’t work. No equal sign technology.) - A
git logthat includes a list of files modified by each commit:git log --stat, which also gives you a colorized nice histogram of additions/deletions for each file. This is a nice middle ground betweengit logandgit log -p. - Speaking of
git log -p, here’s how to make it sane in the presence of moves or renames:git log -p -C -M. Otherwise it doesn’t check for moves or copies, and happily gives you the full patch. (These should be on by default.) - Comparing two branches: you can use
git log --pretty=oneline one..twofor changes in one direction (commits that ‘two’ has that ‘one’ doesn’t); andtwo..onefor the opposite direction. You can also use the triple-dot operator to merge those two lists into one, but typically I find it useful to separate the two. Or you can check out git-wtf, which does this for you. - Preview during commit message:
git commit -vwill paste the diff into your editor so you can review it while composing the commit message. (It won’t be included in the final message, of course.) gitk: don’t use it. You’ll get obsessive about merge commits, rebasing, etc., and it just doesn’t matter in the end. It took me about 4 months to recover from the bad mindset thatgitkput me into.
Thanks for writing this up. git seems to offer as many obscure tricks and customizations as vim.
I’m still at the stage where I switched to git, but I’m not as proficient with git as I was with svn.