5 Git Fundamentals

5,527 reads

I’m starting a series on some of the git tips and tricks that I’ve learned during the half-decade that I’ve been using it. We’ll skip the everyday basics push, pull, log, status, diff, commit and start off with the fundamentals that will help you utilize the true power and convenience of version control.

Let’s begin by creating a .gitconfig file in your home directory. This file is the basis for all your git configurations, customizations, and aliases. In case you’re curious, I have posted a link to mine at the end.

[user]

email = email@gmail.com

name = Jorge Yau

[core]

editor = vim

ignorecase = false

[push]

default = simple

[color "diff"]

meta = yellow bold ul

frag = cyan bold ul

old = red bold

new = green bold

[color "status"]

added = green bold

changed = yellow bold

untracked = red bold

[grep]

break = true

heading = true

lineNumber = true

[alias]

g = grep --extended-regexp --break --heading --line-number

Once the file exists, git will preload and use these configurations for all further commands. Try running a git diff inside a repo and notice how the colors have changed.

I also have included a git alias, which is basically a shorthand for a command. In this case, git grep with all the additional flags can be executed as git g .

# This longer command:

$ git grep --extended-regexp --line-number --break --heading

# Is the equivalent of:

$ git g

Also notice how there’s a section for [grep] — this is where you can specify default options and arguments that will be applied every time you run git grep . If you include the same option in an alias, it will override the default option. Lastly, sections can have subsections, e.g. [section “subsection”]

There are hundreds of settings for every command, each with an expansive number of options that you can customize — read the official gitconfig documentation to discover what’s possible.

While gitignore files are ubiquitous, did you know that you can globally ignore file patterns by creating a .gitignore_global file in your home directory and adding it to your .gitconfig under the core section. I recommend putting software remnants, IDE and OS related files here.

.idea*

**~

.DS_Store

Then either add this line to your .gitconfig file:

[core]

excludesfile = ~/.gitignore_global

Or run this command, which automatically appends it to your .gitignore

git config --global core.excludesfile ~/.gitignore_global

Speaking of grep, git grep is my preferred choice for searching through a codebase over alternatives like GNU grep or ack. It’s fast, comes with git, and ignores files in your .gitignore by default.

# Here's how to use it with more options below.

$ git grep 'debugger'



# Show the count of occurrences found for each file.

$ git grep --count 'debugger'





# Ignore case sensitivity.

$ git grep --ignore-case 'debugger'





# Search through untracked files.

$ git grep --untracked 'debugger'





# Quiet mode. Exits 0 if match found. Useful for scripts and hooks.

$ git grep --quiet debugger

Speaking of grep, the git ls-files command is without a doubt one of the most useful git commands. Very frequently, I use it with grep and sed to perform a bulk find-and-replace or code trimming — occasionally using regex with captured groups (more on this topic in the future). However, I also want to ignore third-party files such as the node_modules directory, which is just not as sexy with regular grep or even ack.

$ grep -E debugger . -rl --exclude-dir={*components*,*node_modules*}

$ ack debugger -l --ignore-dir={components,node_modules}

What if I need a list of all files in the repository — there’s no simple way to accomplish that with regular bash. Well, thankfully git ls-files will list all files in the repository while also excluding the file patterns in your gitignore.

$ git ls-files

.dockerignore

.eslintignore

.eslintrc.yml

.gitignore

.gitlab-ci.yml

.scss-lint.yml

Dockerfile

README.md

...

You can then pipe in the results to grep to filter for certain files. In this case, I’m filtering for all JavaScript files in my repository — the $ is to make sure that .json files are excluded.

$ git ls-files | grep -E \.js$

Git and grep are often paired together in many other commands. If you want to search through your commit messages you can use git log --grep . Searching through commit messages from what I’ve seen is a seldomly used but exceptionally useful feature for tracking down bugs, tracing feature developing, and analyzing your codebase. More on that to come.

# Search for 'bug' in the git commit message history.

git log --grep 'bug'

# I recommend using this flag to ignore merge commits.

git log --no-merges --grep 'bug'

# Refine your searches to a particular author.

git log --grep 'bug' --author 'codenameyau'

I have an alias to pretty print the shortened commit hash, the date, the author, and the commit message in one line. You can use it like so:

# Put this inside your ~/.gitconfig

[alias]

search = log --no-merges -i -E --pretty='%h (%ad) - [%an] %s %d' --date=format:'%b %d %Y' --grep





# Then run the command like so:

$ git search 'bug'

# Pipe it to wc to get the number of occurences for 'fix' or 'bug'.

$ git search 'fix|bug' | wc -l

Git search in action.

In order for git search to be useful, it’s best to have contextual but concise commit message under 80 characters. One very helpful convention is to include a hash (#) followed by the issue number. This will automatically link the commit to the issue for repository managers like GitHub, and it makes documenting and investigating issues much more feasible.

$ git commit -m "#123 - Fix bug with useful git commit message"

Bonus tip: once you’ve grasped the basic fundamentals, definitely check out the git-extras repository. It is an extension of git with extremely useful commands (I’m looking at you obliterate).

https://github.com/tj/git-extras/blob/master/Commands.md

As promised earlier, here’s a link to my .gitconfig file.

If you learned something from this article or simply enjoyed it, please recommend it. I would greatly appreciated it!

Here are some other articles in my Git Fundamentals series

Tags