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
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).
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.
git add --patch
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 hunk
n- no, skip over this hunk
s- split this hunk into smaller hunks
e- 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
git reset -p if you prefer. This command is basically the opposite
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
Tip: removing one line from the middle of a hunk
You can use the
edit 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
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
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.