git grab bag

Time to flush my buffers again before the new year. Happy new year, everyone!

In no particular order here are some useful git things I've run across recently.

git stash --keep-index

git's index (or staging area) is useful, but it comes with a
liability: you run into the danger of committing a state that doesn't work
(compile, pass tests, etc.) because you never actually "saw", on your disk,
the stuff that was going to be committed, in isolation.

That's what git stash --keep-index is for: it stashes the changes you
haven't staged for commit, so you are left with only what will get
committed. Do your builds/testing/verification, then git stash pop
to continue working.

git clone --reference

If you're trying to clone a large remote repo, it's a waste of time to
re-download objects that are already present in another repository on your
local disk or local network. You can use the --reference option to
obtain objects from this local repository when possible (any objects not
found are pulled as usual from the real source):

git clone --reference LOCAL.git REMOTE.git my_new_clone

(This is sort of like cloning LOCAL.git, changing its remote to
point to REMOTE.git, and fetching again, but much easier, and
doesn't pollute your clone with branches and commits that are only present
in LOCAL.git but not in REMOTE.git. From a content
perspective it is exactly a clone of REMOTE.git.)

Note: if LOCAL.git is on the same filesystem, git sets up
the alternates file so that object IDs can be resolved just
using the object files in LOCAL.git. This may be undesirable
because you won't actually have the objects in your new repo(!) and references in your new repo alone will not(!) be sufficient to keep the
objects from being GC'd if LOCAL.git changes. To break this
dependency, forcing the required objects to actually be copied into your new
clone, do the following:

git repack -a; rm .git/objects/info/alternates

gfind

To make git print out all the files it is tracking:

git ls-tree -r --name-only HEAD

This is a useful base for searching your codebase, since it automatically
lets you search all of your actual code and avoid looking at compiled code,
generated code, downloaded libraries and documentation, etc.

I have aliased this to gfind and do things like this to search
within a repo:

gfind | xargs grep FOO

git-filter-branch

git-filter-branch is your general purpose tool for rewriting
repositories wholesale, for example, to extract a single subdirectory
retaining all its history, or to excise a subdirectory, file, secret key,
password, etc. that you've put in the repository.

Matthew McCullough has put
together a
good starting point with examples of how to use this tool.
(Unfortunately, some of the links are broken; I will post alternate links
once I find track down copies.)

git diff --color-words

Word based diffs in git! Great for LaTeX, Markdown, etc. More
info here.