How to tell if a file is git tracked (by shell exit code)?
Asked Answered
S

10

474

Is there a way to tell if a file is being tracked by running some git command and checking its exit code?

In other words: is git tracking a file?

Saw answered 8/3, 2010 at 22:31 Comment(1)
I think the point is, what is the criteria to decide a file as tracked or untracked. There should be some kind of tracked file collection to search.Melli
C
628

try:

git ls-files --error-unmatch <file name>

will exit with 1 if file is not tracked

Colure answered 9/3, 2010 at 5:12 Comment(9)
At least with my older (1.6.0) version of git, you need to put the --error-unmatch option before the filename to get an error. Somehow the option is only applied to filenames that follow it.Astaire
Actually, the problem seems to be that GNU getopt option permuting is not enabled, and when appearing after a filename (or after --) the --error-unmatch is treated as just another (not in the index) filename, and has no effect.Astaire
git ls-files | grep <PATTERN>? example: git ls-files | grep Main.hTabor
[A naive way]Make a small change in the file (add/remove a space). And see if the file is being listed when 'git status' is typed. A silly way, but may save time.Expectation
But I added and commit it with "git add -A && git commit -m "blah" command. Even see whole files with "git ls-tree --name-only -r sha1" command.Serafina
The -o | --others option will just untracked files in the output. Example: $ git ls-files -o $ touch delete-me.sql $ git ls-files -o delete-me.sqlCupp
FYI for newer users: After running the above, you can use echo $? in BASH to print the exit code of the previously entered command. If this prints 0, there was no error, meaning the file was tracked by Git. If it prints 1, then the file was not tracked by Git.Swept
Be aware the match will be case-sensitive even if you are on Windows.Gnu
this will not exclude STAGED files for commit.Campman
C
110

If you don't want to clutter up your console with error messages, you can also run

git ls-files file_name

and then check the result. If git returns nothing, then the file is not tracked. If it's tracked, git will return the file path.

This comes in handy if you want to combine it in a script, for example PowerShell:

$gitResult = (git ls-files $_) | out-string
if ($gitResult.length -ne 0)
{
    ## do stuff with the tracked file
}
Calliper answered 17/12, 2015 at 8:32 Comment(1)
I think file_name needs to be an exact match (full path + filename), but can be used with wildcards: git ls-files *foo.rbGredel
M
22

EDIT

If you need to use git from bash there is --porcelain option to git status:

--porcelain

Give the output in a stable, easy-to-parse format for scripts. Currently this is identical to --short output, but is guaranteed not to change in the future, making it safe for scripts.

Output looks like this:

> git status --porcelain
 M starthudson.sh
?? bla

Or if you do only one file at a time:

> git status --porcelain bla
?? bla

ORIGINAL

do:

git status

You will see report stating which files were updated and which ones are untracked.

You can see bla.sh is tracked and modified and newbla is not tracked:

# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#       modified:   bla.sh
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       newbla
no changes added to commit (use "git add" and/or "git commit -a")
Monteith answered 8/3, 2010 at 22:36 Comment(5)
Sorry I should've been clearer. Status is okay but I'd rather check an exit code than parse output.Saw
git status --porcelain is your friend if you need to parse output by script, have a look at the linked doc it show some other useful optionsMonteith
Hihi, does not work with very old Git: git status --porcelain error: unknown option porcelain' Version is 1.6.0 :-)Samualsamuel
@user465139 that is correct... you need git 1.7.0 or newer (the porcelain option wasn't added until then).Gargantuan
Does not work in git 2.39 ... git status --porcelain bla returns nothing, regardless of whether bla is tracked or notPerforated
C
13

Try running git status on the file. It will print an error if it's not tracked by git

PS$> git status foo.txt
error: pathspec 'foo.txt' did not match any file(s) known to git.
Conics answered 8/3, 2010 at 22:34 Comment(6)
Wow. I must have been running it on a directory and it acted like it was checking the entire repo. Thanks.Saw
Actually, if I run git status trackedfile I get exit code 1 (expected 0 to be useful) but it doesn't give me "error:" in the output. I'd rather parse an exit code than string output.Saw
I find that no error is raised if I run git status on a file which exists in my git working copy but which is excluded by .gitignore. (I.e. this answer won't do.)Lariat
Please note that it does not work well if the file is in the ignore list, i.e. in the file .gitignoreOndrea
That doesn't work. It always prints the same thing, even if the file doesn't exist. $ git status notthere : On branch master nothing to commit, working directory cleanAirmail
Doesn't work in more recent versions of git (e.g. 2.9.0.windows.1)Tinkle
R
7

I don't know of any git command that gives a "bad" exit code, but it seems like an easy way to do it would be to use a git command that gives no output for a file that isn't tracked, such as git-log or git-ls-files. That way you don't really have to do any parsing, you can run it through another simple utility like grep to see if there was any output.

For example,

git-ls-files test_file.c | grep .

will exit with a zero code if the file is tracked, but a exit code of one if the file is not tracked.

Rupp answered 8/3, 2010 at 23:25 Comment(0)
P
7

I suggest a custom alias in your .gitconfig.

You have two ways you could do it:

  1. With a git command:
    git config --global alias.check-file <command below>
  1. Editing ~/.gitconfig and adding this line in the alias section:
    [alias]
        check-file = "!f() { if [ $# -eq 0 ]; then echo 'Filename missing!'; else tracked=$(git ls-files ${1}); if [[ -z ${tracked} ]]; then echo 'File not tracked'; else echo 'File tracked'; fi; fi;  };  f"

Once you launch the command (1) or save the file (2), you can test it like so:

$ git check-file
$ Filename missing 

$ git check-file README.md
$ File tracked 

$ git check-file foo
$ File not tracked
Poynter answered 16/5, 2017 at 8:51 Comment(0)
H
5

Just my two cents:

git ls-files | grep -x relative/path

where relative/path can be easily determined by pressing tab within an auto-completion shell. Add an additional | wc -l to get a 1 or 0 output.

Hobnail answered 8/2, 2017 at 15:36 Comment(1)
Depending on the path (e.g. if it contains a dot), you should add grep option --fixed-strings.Hulda
B
3

using git log will give info about this. If the file is tracked in git the command shows some results(logs). Else it is empty.

For example if the file is git tracked,

root@user-ubuntu:~/project-repo-directory# git log src/../somefile.js
commit ad9180b772d5c64dcd79a6cbb9487bd2ef08cbfc
Author: User <[email protected]>
Date:   Mon Feb 20 07:45:04 2017 -0600

    fix eslint indentation errors
....
....

If the file is not git tracked,

root@user-ubuntu:~/project-repo-directory# git log src/../somefile.js
root@user-ubuntu:~/project-repo-directory#
Battle answered 22/2, 2017 at 7:34 Comment(0)
C
2
if git rev-parse -q --verify :path/to/file >&-
then echo it\'s tracked
else echo it\'s not
fi
Catto answered 7/3, 2023 at 16:51 Comment(0)
S
-1

I would prefer git log -1 --oneline to git ls-files because git log command doesn't traverse directory, so the output is similar irrespective of whether path being checked is a file or directory.

Here is sample output for git ls-files:

vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git ls-files untracked-file # Untracked file shows no output
vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git ls-files form/data.json # tracked file shows its name again
form/data.json
vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git ls-files form # For directory entire directory is traveresed
form/Traffic_Params_2M_IS_cont_GVolte_EATF.xls
form/data.json

Sample output for git log -1 --oneline:

vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git log -1 --oneline untracked-file # Untracked file shows no output
vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git log -1 --oneline form/data.json # tracked file shows one-line output
e8e9e0f CONTAINERS-767 MT and release change for 21.8
vinegupt@bhoscl88-04(/imsgit_local/work/vinegupt/ims_21.8/ims_oam/MT)$ git log -1 --oneline form # Only directory info is given no traversal
e8e9e0f CONTAINERS-767 MT and release change for 21.8
Sibel answered 11/8, 2021 at 18:31 Comment(1)
This doesn't appear to work. At least for my git setup. e.g. PAGER= git log -1 --oneline -- not-a-real-file; echo $? returns 0, as does checking an actual file.Wheal

© 2022 - 2024 — McMap. All rights reserved.