Ever wanted to exclude some files when running git log? This post is what you want!
If you’ve used a glob pattern to run a particular git command on a specified list of files, you’ve used a simple version of pathspec. If you’ve never used it, then this post is for you. Skip to the advanced usage section if you’re familiar with the glob pattern but aren’t familiar with the optional flags that the pathspec accepts.
Some of the commonly-used Git commands that accept a pathspec are:
add log checkout clean diff grep ls-files rm
The pathspec is specified after the command arguments,
separated by a double dash
The following command will add all the Ruby files under
git add -- lib/*.rb
This command would reset all the changes made on all the Ruby files
git checkout -- lib/*.rb
I use this technique a lot to cleanup all the untracked temporary files lying inside a repository. A pathspec filter can be used to clean specific files without removing all untracked files. For example, to delete all the untracked files under lib directory:
git clean -f -- lib/*.rb
Another useful use-case is where I want to see the diff of a particular file across different branches. Consider this branch structure:
A---B---C topic / D---E---A'---F master
Let’s say both branches have a
README.md which has different content
master branches, and we’re currently at the commit
C. It’s a common need to find out the changes made to the file between
the branches. One way to achieve this is by the following command:
git diff topic..master -- README.md
topic...masteris the revision list. This directive means “from the head commit on
topicbranch to the head commit of the
- The revision list and the file name—the pathspec we want here—has to
be separated by
--. By adding the file name, we’ve filtered the diff output to include changes only from that file.
Apart from the simple glob patterns, the pathspec can also take optional
flags that would make it work in a slightly different manner. These
flags are of the form
token here is one of the
The tokens can also be mixed:
The documentation for each of these switches is available in the git
glossary. For the sake of an example, let’s look at two of
top switch switches the context of the git command
you’re running by considering the glob pattern you specify as if it was
run from the root of the git repo.
exclude can be used to blacklist some of the files from being included
by the git command.
Consider the following directory structure:
~/test master(dirty) $ tree . ├── about.html ├── css │ ├── main.css │ └── styles.css └── index.html 1 directory, 4 files
index.html isn’t yet added to the git tree.
If we were to
git log -p on the master branch, but wanted to avoid
paging though changes in
about.html, we could do something like:
~/test/css master(dirty) $ git log -p -- . ":(exclude)about.html"
Now, if we are in the
css directory, and we want to clean all the
HTML in the repo except
usual way is to change directory one level up, and then remove the
rm command or some other way. A more easier way would
~/test/css master(dirty) $ git clean -f -- ../ ":(top,exclude)about.html" Would remove ../about.html
These switches can be pretty handy when you’d want to exclude a certain pattern of files from a git command.