How to find what you are looking for using Git

Łukasz Gryl
Analytics Vidhya
Published in
7 min readFeb 22, 2021

Git is an incredible tool. A tool that most of us, programmers, can’t imagine working without today. But at the same time, it’s not the easiest one to use. It has tens of commands, hundreds of options, it forces the user to operate on a rather low level and to know its inner details. So it doesn’t come as a surprise that not all of us use it to its full potential.

So when some programmers are faced with the challenge of having to find something in their Git repository, they often resort to the search bar in their GUI Git client. Unfortunately, search functionality in such applications is usually extremely limited, and it does not prove useful in more complex scenarios.

That’s why in this article I present several commands that come in handy when searching for something in Git. The article is divided into real-life use cases to make it more practical and easy to use.

Where is a commit with a message mentioning …?

This is one of the more common scenarios. You know you’ve seen a commit mentioning, say, MessageBus, but you have no clue when it was committed, or even on which branch. Or maybe you’re just looking for all the commits mentioning some Jira ticket. Alternatively, you might be interested in knowing how many hotfixes were there in your project’s history.

In all of those examples, the perfect command to use is the git log. This command is so powerful and versatile that it is, in some form, the solution to most of the use cases presented in this article.

Solution:

git log [-i] [--all] --grep <phrase>

-i - ignore case; use it do a case-insensitive search

--all - search all refs; use it to search all commits, not only those accessible from the current branch

Example:

git log -i --all --grep MessageBus

What was … doing last month?

This one is useful if we want to see commits authored by a specific person, from a specific date range. Regardless of whether we just want to refresh our memory on what we were working on, or if it’s for reporting purposes, this command gives us exactly what we want.

Solution:

git log [ --pretty=fuller] --author <author name> --after <startDate> --before <endDate>

--pretty=fuller - after and before options filter commits by the author’s date, but the log, by default, displays the commit date; use the pretty option to display both author’s and commit date

Example:

git log --pretty=fuller --author “Junio C Hamano” --after “2021-01-01T00:00:00+01:00” --before “2021-02-01T00:00:00+01:00”

Who and when modified a file for the last time?

Sometimes we want to know whether the file we’re looking at was modified recently, or we just need to know when was it last edited, and who did it.

Solution:

git log -1 <filePath>

-<n> - number of commits to be displayed

Example:

git log -1 docs/README.md

What’s the history of a file?

In some cases it is very useful to see a file’s complete edit history, from the point it was created, through all of its modifications, up to the current point. We might be interested in seeing when it was created, or how often was it modified, or maybe who contributed to it the most.

This solution is just a generalisation of the previous one: we just need to drop the number of commits option.

Solution:

git log <filePath>

Example:

git log docs/README.md

What’s the history of a file, including renames?

The previous solution works great, but it has one downside: it shows the history of a file only from its last rename.

Fortunately, it’s trivial to fix this problem: we just need to add one option, --follow, to the command.

Solution:

git log [--summary] --follow <filePath>

--summary - show more information about the commits, in this case about the renames

--follow - continue listing commits even after the file renames

Example:

git log --summary --follow scripts/scripts.js

What’s the history of a deleted file?

If we try to use the previous command to see a history of a file that no longer exists, Git would respond with an error:

> git log deletedFile

fatal: ambiguous argument ‘deletedFile’: unknown revision or path not in the working tree.
Use ‘ --‘ to separate paths from revisions, like this:
‘git <command> [<revision>…] -- [<file>…]’

Git is telling us that it can’t figure out what exactly the “deletedFile” is. That’s because it is unable to look it up in the working directory to make sure we’re trying to provide a filename. After all, we could be passing a branch name as well. So we need to use -- to separate revision from the path.

Here’s a good example that might help to understand the need for the --. Imagine you had a file and a branch with the same name, for example, dev. If you wanted to list all the commits from the dev branch, you would use the following command:

git log dev --

But if you wanted to list all the commits where the dev file was modified, the command would be:

git log -- dev

Solution:

git log -- <filePath>

Example:

git log -- scripts/script.js

What’s the history of a deleted file in a path that I don’t remember?

The previous solution works like a charm if you know the exact path of a deleted file. Usually, however, we remember just the filename or only a part of it.

Luckily, the git log accepts regular expressions as well, so we can use a pattern instead of a full path.

Solution:

git log -- <regex>

Example:

git log -- *script.js

Who wrote this line!?

Let him who never shouted these words in anger cast the first stone. This time Git again has a perfect command for finding the answer to that question.

Accusingly-sounding git blame command shows us the content of a selected file, with information about the last edit for each line of it - with author, date and commit hash.

Solution:

git blame <filePath>

Example:

git blame index.html

Which commits added or removed this string/regex?

There are cases when git blame falls short - for example, we could be checking when (as well as by whom and why) some critical line was added, only to find out that the last commit modifying it was an indention fix.

Here’s where the so-called pickaxe command comes in. When we provide the -S option together with a phrase, Git will show us all the commits that added and/or removed lines that contain this phrase.

However, there are two catches when using the pickaxe:

  • it won't show a commit if the number of occurrences of a phrase did not change (for example: if commit added one line with that phrase, and removed another with the same phrase),
  • it doesn’t work with regular expressions.

The solution to those two downsides is very simple: just use -G instead of -S.

Note that both commands run quite slow. So if we have an idea of a specific file (or path) where the phrase occurred, we might narrow the scope of the search by providing the path at the end of the command.

Solution:

git log -S <phrase> [<filePath>]
git log -G <regex> [<filePath>]

Examples:

git log -S delegate GameViewController.swift
git log -G UI*Delegate GameViewController.swift

Is there a string … in the project?

We might be interested in knowing if a certain phrase appears in the currently checked out local repository.

Solution:

git grep [-i] <phrase>

-i - ignore case; use it do a case-insensitive search

Example:

git grep MyP4ssw0rd

Was there ever a string … in the project?

Further still, we might want to check if the given phrase ever appeared in our project.

Knowing that git grep accepts a list of commits to search through and that to get all commits’ hashes we use:

git rev-list --all

We might want to use the following command:

git grep <phrase> $(git rev-list --all)

Unfortunately, if your repository has a long history, that won’t work, and will give you the following error:

argument list too long: git

That’s because git grep can only accept a certain number of arguments, and git rev-list --all can easily yield the result that exceeds this limit. To work around this limitation, we need to use xargs.

Solution:

git rev-list --all | xargs git grep [-i] <phrase>

Example:

git rev-list --all | xargs git grep MyP4ssw0rd

We could use the pickaxe command for this scenario as well, but if we’re more concerned about if and where rather than when git grep will give us slightly better-presented results.

What’s the history of this method?

Sometimes we might be interested in the history of not the whole file, but only some part of it, like a single method. Git can do that too, and it will do its best to show only changes between those lines, even if that code was moved around in the past.

Solution:

git log -L <startLine>,<endLine>:<filePath>

Example:

git log -L 119,233:index.html

Summary

As you could see in this article, Git has much more to offer in terms of searching the repository then most of the GUI apps do.

I really hope that you learned something and that you will exploit the potential of searching the repository using Git commands more in the future. Or at least that I helped you to find the solution that you were looking for.

--

--