This is part 1 in my Favourite Git Commands series.
Last year I wrote a post about how I intended to switch over to and master the tools I’d always meant to but somehow never got around to. Among these was git.
I’ve now been using git exclusively for the last year (even when
interfacing with SVN projects I do so using the awesome git-svn
bridge) and I love it. It took me a while to form a decent workflow and
break the old SVN habits, so over the next few days I thought I’d share
with you some of my favourite git commands.
I’m going to assume that you’ve used git at least once or twice, and
know what I mean by repo (where the git history is stored, i.e. the
.git
folder), HEAD (the top commit in the current branch), staging
area (where the files for the next commit are stored, also known as the
index or cache), and the working copy (the files that you’re modifying).
The --patch
option
My friend Jasper helped a lot when I first started getting into git,
and noted one of his favourite commands was git add -i
- an
interactive way of adding files to your staging area before commits. I
used this a lot, but found that mostly I was using the patch function,
and going through all the menus was unnecessarily slowing me down.
Enter:
git add --patch
Or git add -p
if you prefer. This command jumps straight to patch mode
on all your tracked files, asking you for each hunk whether you want to
add them to the staging area or not. I generally answer with one of the
following, though there are other options that can be useful:
y
- yes, add this hunkn
- no, skip over this hunks
- split this hunk into smaller hunkse
- edit this hunk, then add it (I normally use this to remove debugging lines)q
- I’m all done adding stuff, go away.
This ensures that I can keep my debugging and other temporary mods out of git, only adding the files I want to appear in git history. But sometimes I accidentally add a line I didn’t mean to, so then I use:
git reset --patch
Or git reset -p
if you prefer. This command is basically the opposite
of git add --patch
- it enables you to move specific hunks back out of
staging and into your working copy. It accepts the same options as its
sibling above.
Tip: removing one line from the middle of a hunk
You can use the e
dit command to open the hunk in your text editor,
then change all the +
at the beginning of lines for a space except on
the lines you want to remove. Remember this is removing a hunk, so a +
actually means “remove this line from the staging area”. (The spaces are
needed for context.)
When I have the staging area how I want it, I commit it (see below). But
then I’m left with all the lines I didn’t stage. Some of these I want to
keep whilst I work on the next commit, others I’m done with (mostly
console.log
/NSLog
statements, if I’m honest). So I want to
selectively delete modified lines from my working copy without having to
find them in my text editor. Enter:
git checkout --patch
Yes, or git checkout -p
. This command is more dangerous as it throws
away the work you select, with no history of it (since it was never
committed). You select the hunks you want to throw away using the same
options as its siblings above. You can also use it for surgery-like
removal of lines at any time using the e
option and the same tip as
git reset --patch
but be very careful!
git [add/etc] --patch [filenames]
All the above commands accept file or directory names as an argument, so you can just patch add/reset/checkout a small selection of files without worrying about modifications to other unrelated files. This is particularly powerful when paired with zsh’s globbing.