Every developer has their own favorite Git tricks they use daily. Here are some of my favorite ones I have been using for as long as I can remember.
First of all, I should mention that most of these commands are bundled in my git-toolbelt project. If you like to use them, all you need to do is install it like so:
$ brew install nvie/tap/git-toolbelt
Quickly opening modified files ¶
While working on a branch, I often find the need to re-open the files I was working on. The Git toolbelt project contains a command to show you all locally modified files. It will only report files that still exist locally, so this overview won't include deleted files.
$ git modified controllers/foo.py README.md
This is super useful to quickly open all locally modified files in your editor. Definitely one of my most-used commands throughout the day:
$ vim $(git modified)
After quitting your editor, you can easily re-open the files you're working on this way.
To also include any files modified in the index (files that are
already), use the
$ git modified -i
You can also pass it a commit SHA, which will open all files modified in that commit:
$ git modified HEAD~1
I have the following aliases set up in my shell, for quickly opening a specific set of files:
vc: vim locally modified files (not indexed)
vca: vim all locally modified files (including the ones indexed)
vch: vim files modified in the last commit (HEAD)
vc HEAD~1: vim all files modified in the second-last commit
Fixing up the last commit ¶
You're probably familiar with
git commit --amend to incorporate the
currently-staged changes into the lastcommit, effectively rewriting the last
commit. The toolbelt offers a similar command called
git fixup, which will
do the same, but without prompting for the commit message. So it's like
a quicker version of
$ git fixup
This is a great way to build up a commit incrementally. A very typical flow for me looks like:
$ git add -p # Pick bits to commit $ git commit $ git add -p # Pick more bits $ git fixup # Add those to the last commit
"Emptying" the last commit ¶
Sometimes I make a mistake and I accidentally commit too much, or something I didn't intend to commit. For example, an extra file I accidentally added, or a patch within a file that I didn't want to include. Here's how I fix that:
$ git delouse
This "empties" the last commit. Think of "emptying" as keeping the commit message and the author/date info, but "moving" all of its changes back into the work tree.
- Soft-resets the last commit, which means it will remove the last commit from the branch, and put back the contents of that commit into the work tree (basically reverting to the state right before committing). File contents aren't changed by this, only the Git commit disappears.
- Add an empty commit with the same commit message and author details as the commit that was just removed.
The net result of these actions are that it appears as if the last commit on the branch is "emptied" back into your work tree. This command is non-destructive, since all of your files remain untouched. They are now just local changes again.
This allows re-adding all changes again. Just use
git add -p to select the
bits to commit, and then
git fixup (see previous section) to keep changing
the last commit, effectively rebuilding it up from scratch.
git delouse kept the commit message and author information around in
that empty commit, the original commit info is never lost, and you don't have
to re-enter the commit message whenever you run
git fixup, which makes this
whole process super cheap.
$ git commit -m 'Add login screen' # Oops! Checked in a secret key with that... let's fix this mistake! $ git delouse # Retry adding stuff $ git add -p # This time, don't add the secret key $ git fixup # Rewrites the previous commit
And if you make a mistake, you can just run
git delouse again and start over,
as often as you want. Since none of these commands destroy your local changes,
this allows you to carefully craft your commit contents without the risk of
losing any data.
Splitting up a commit into pieces ¶
It's also a great way to split up a commit! For example, suppose you are adding a bugfix but you also renamed a variable to have clearer meaning. When submitting the code for review, you realize that the variable rename adds a lot of noise to the actual change. You may then decide it's a good idea to split up this commit into two pieces: one that atomically just changes the variable name everywhere, and one that fixes the bug. You can then point to the bugfix commit when asking for a code review.
How would that work?
$ git commit -m 'Bugfix for login screen' # Oops, I should've split this one up. Let's start over! $ git delouse $ git add -p # Just pick the bugfix bits $ git fixup $ git add -p # Now pick the var rename bits $ git commit -m 'Rename variable name to be clearer'
These three commands have become indispensable in my day-to-day Git routine. If you like it, let me know!