Useful Git Commands and Configuration
These are a few git commands and configuration tweaks that I’ve found that are incredibly helpful in managing a repository via the command line. Some things will always be a bit easier in a GUI but being able to quickly search and interact with the repo in the terminal can often speed development up.
Git Aliases
Git Aliases let you setup a shorthand for a command in the git configuration. They make commonly used commands that are lengthy easier to remember and they make interacting with the repository via the command line less verbose. Aliases can be added through the command line or directly in the configuration files, they can be either global or local in scope.
For example, aliasing the term last to see the most recent commit with log -1 HEAD can be setup with the command line:
git config --global alias.last 'log -1 HEAD'
The --global flag sets this as an alias available to all the repositories on your system. To add this same alias to a configuration file make an [alias] section at the bottom of your .git/config file.
[core]
...
[alias]
last = log -1 HEAD
Git Scripts
Aliases are helpful but kind of basic, sometimes you need more functionality. I’ve seen developers horde bash aliases and functions in their local configuration with really useful functionality. Git has a lesser known feature that makes these functions and aliases more portable where it will automatically read files (in your $PATH) that start with git- and turn them into aliases, this can let everyone on the project easily share scripts customized for the repo. You can also create complex aliases using almost any language. I usually add a bin/git/ folder in the repo and then include that folder in my $PATH.
For example, to make an alias to search commit messages with some standard flags using git cmsearch , create a file in a folder on your $PATH named git-cmsearch and give it execute permissions. The script files need execute permissions to run.
#!/bin/bash -e
git log --grep $1 -i --oneline --all
Which then becomes available with:
git cmsearch "searchString"
Git Workflow Hooks
I don’t use workflow hooks as often as I used to since they’re built into Bitbucket and Github and are easy to configure in the repository settings. That functionality to trigger an action at a specific time, ie. ‘commit pushed to master’ can be scripted on your machine. Hooks are kept in the .git/hooks folder. If you open a git repo on your computer you should have that folder filled with samples. I still use local hooks to run a build/test on pre-commit before pushing on some projects and saving the results to a log file. Like git scripts you can code these in almost any language.
Ignore File Permission Changes
There are a couple of go-to defaults in the configuration that I set to avoid issues and make interacting with the reposiotry a little easier. Ignoring file permissions is one.
git config core.fileMode false
Unless necessary I ignore file permission changes to prevent myself from accidentally pushing permission changes upstream. Add the --global flag to ignore globally.
Adding Notes to Git Commits
Notes in git provide a non-invasive way to attach information to a git object. An object in git is a blob (file), tree, commit or tag. I’ve only ever added notes to commits. I’ve found the best use of notes is to add text to an existing commit without ammending the original commit and changing its hash. This is useful to attach searchable keywords or text to a thing you know you’ll be looking for later. Git notes are searchable with the log command and show in the git log results.
git notes add -m 'Note Message' 0baf9e0d7c
Git Diff
The git diff commands highlights changes in a file between commits or branches.
Run a diff on a file across different branches:
git diff firstBranch secondBranch -- path/to/file.txt
Run a diff comparing a file across different commits:
git diff 546a62f3 fb5b387 -- path/to/file.txt
Searching Commits with log
The log command is a very powerful search tool. It can be used to search commit messages or code broadly over the whole repo or hypertargetted to a file or date range. This is easily the one of the most important parts of the git command swiss army knife. It’s also one of the deepest commands as far as number of potential options and complexity. I’ve found that knowing a few basic options will let you find 99% of the commits you’re searching for.
Search Commit Messages.
Git enables searching through commit messages. This can particularly useful if you know a term in the commit message, for example a ticket number. The --grep flag lets you search with a regular expression. If you’re looking to search for an exact string and not a regular expression append the --fixed-strings flag.
git log --grep "Search String" -i --oneline --all
The --all flag here is telling git to search through all the commits in the repository and the --oneline flag limits the search results to a single line making it easier to parse through the results in the terminal. The -i flag here just specifies that the search string is case insensitive, I usually default to using it just in case the variable/file/string has an unexpected case.
Search Commit Contents for a Pattern.
The -G flag takes a regular expression and searches the patch text for each commit and return commits that have matches.
git log -G"Search.Regex" -i --oneline --all
This is handy if you’re searching for a function name or for code that you know uses a specific string.
Limiting the search to changes within a specific file.
The log command takes a trailing optional argument, the filename(s). Use the repeatable – flag to add file paths to limit the returned commits.
git log -G"Search.Regex" -i --oneline --all -- *file1.txt -- specific/path/file2.txt
Prepending the filename with * let’s you target deep in the folder structure without needing to know/type the path out.
Other useful log flags.
--author=<pattern> or --committer=<pattern> - Use these flags to search for your own commits or the person you know pushed the change.
--branches[=<pattern>] - Limit search to specific branches.
--after='JUN 10 2015' and --before='JUN 20 2015' - Limit search by date.