Git is a fantastic tool, used by millions of people around the world. While Git GUIs can be useful tools, using git on the command line has a higher ceiling for productivity, especially when one can use aliases or refer to their own command history.
Today, I’m going to go over a few Git features that I use every day. Many of these will build on top of basic Git knowledge (add, reset, checkout, commit, merge, pull, push), so we should be familiar with these before proceeding.
Git hooks are scripts that are run before or after an action occurs. By adding files (with names matching the hooks in the githooks man pages) to a repositories
.git/git-hooks/ directory, scripts can be triggered to run on certain actions. The possibilities here are endless – linting before pushing, catching errors on commits, or automatically deploying websites, just to name a few. In turn, this helps the developer maintain a healthy codebase.
Git reflog (pronounced ref-log, not re-flog) is a very handy tool in the case of an accidental change. It records when the tip of the local branch was updated, such as on a commit, reset, merge, pull, checkout, and more.
While it’s fairly easy to reset or checkout an earlier revision if something like a merge goes wrong, it’s much more difficult to fix a deleted branch or a hard reset. This is where reflog comes in. Running
git reflog will show the local history of the repo, and allows the user to quickly revert back to another point in time. Pretty neat!
Many Git commands have a
-p / --patch available to use, which allows for interactive usage of the command. It’s great to selectively add, stash, or commit file changes!
“Interactive usage” shouldn’t be confused with
git add --interactive though, where the user can quickly stage, unstage, and revert file-changes. This also allows the user to open the patch menu for files.
The patch menu has a few option – which can seem confusing at first, but are quite natural after using it a few times:
y - stage this hunk n - do not stage this hunk q - quit; do not stage this hunk or any of the remaining ones a - stage this hunk and all later hunks in the file d - do not stage this hunk or any of the later hunks in the file g - select a hunk to go to / - search for a hunk matching the given regex j - leave this hunk undecided, see next undecided hunk J - leave this hunk undecided, see next hunk k - leave this hunk undecided, see previous undecided hunk K - leave this hunk undecided, see previous hunk s - split the current hunk into smaller hunks e - manually edit the current hunk ? - print help
Aliases are a huge time saver, especially for frequently used commands or for forgettable ones. There are two ways popular ways to do this.
.config file can store these aliases, which can be convenient for using unique aliases in different projects. Naturally, global aliases can be stored in
~/.gitconfig. To add an alias for status (or whatever you choose), run the command
git config alias.st "status". Adding the
--global flag will store it in the
~/.gitconfig rather than the local config.
Additionally, the aliases could be manually added to a config file underneath the
To see all aliases created this way, run
To run an aliased command, run
Shell builtin aliases
These method, while not entirely due to Git, is a convenient way to store Git aliases. Simply run
alias gst="git status"
Regardless of the method chosen, I recommend sticking to a single method for storing Git aliases. It’s much more convenient to run
alias | grep git or
git alias than to track down a command that could be in either.
Shell aliases are my personal preference, as I prefer typing something like
gst rather than
git st. It also allows for easy chaining of other shell commands (e.g. sed, cut, xargs, sort, uniq, grep, and more). However, I encourage you do go with the method that seems more natural to you.
I started out with these aliases, and have added others as time has gone on.
Recap / Quick Tips
- Add hooks to .git/hooks/ to maintain code health
- Use git reflog as a safety net when things go bad
git add --interactivefor a nice command-line staging interface
- Run add, stash, commit, and others with -p or –patch to interactively choose hunks
- Use aliases (either git or shell) to boost productivity
git stash save -- "your message here"to label a stash
git log --patchand
git log --statwill show more detailed log information
git cherry-pickto merge individual commits from one branch to another
git bisectto use binary search to find a specific commit
- Use a dash (-) to reference a previous ref.
git merge -or
git checkout -will reference the last branch or ref.
- When merging, use
git checkout--ours FILENAMEor
git checkout--theirs FILENAMEto keep changes from the local or incoming branch
- Remove a file from git, but not locally by running
git rm --cached FILENAME. This is useful when adding something to the
- HEAD references the tip of the branch. HEAD^ references the parent. HEAD~2 shows the parent of the parent. HEAD…HEAD~2 shows everything between HEAD and HEAD~2. In these examples, HEAD can be replaces with commit hashes.