362

I am writing a series of scripts for Git management in zsh.

How do I check if the current directory is a Git repository? (When I'm not in a Git repo, I don't want to execute a bunch of commands and get a bunch of fatal: Not a git repository responses).

5
  • Have you looked at the bash completion file (in contrib/completion/git-completion.bash ) for inspiration? I use the __git_ps1 command as part of my bash prompt. In fact most of it will source within zsh. The __gitdir function is probably the one you want. Commented Feb 1, 2010 at 21:49
  • 3
    @jabbie: why don't you make that an answer? Commented Feb 1, 2010 at 21:52
  • Have you checked functions already in zsh distribution? Commented Feb 4, 2010 at 18:57
  • 1
    possible duplicate of Determine if directory is under git control Commented Dec 12, 2014 at 19:50
  • 1
    Note: none of the current answers consider the $GIT_DIR or $GIT_WORK_TREE environment variables, or how they interact. Commented Dec 17, 2018 at 5:27

16 Answers 16

299

You can use:

git rev-parse --is-inside-work-tree 

Which will print 'true' to STDOUT if you are in a git repos working tree.

Note that it still returns output to STDERR if you are outside of a git repo (and does not print 'false').

Taken from this answer: https://stackoverflow.com/a/2044714/12983

Sign up to request clarification or add additional context in comments.

7 Comments

This will still print false for a bare repository that has no working tree
This does not consider the sub-directory. I need to verify does git rev-parse --show-toplevel matches with the subfolder I am checking
The chosen answer didn't even print out anything. This one worked.
Can we do something like: if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then like William Pursells answer?
@ScottyBlades In context, I would assume that means the chosen answer reports the result in its exit status and intentionally doesn't print anything, to be more directly/easily usable in shell scripts. Was that not the case?
|
217

Copied from the bash completion file, the following is a naive way to do it

# Copyright (C) 2006,2007 Shawn O. Pearce <[email protected]> # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). # Distributed under the GNU General Public License, version 2.0. if [ -d .git ]; then echo .git; else git rev-parse --git-dir 2> /dev/null; fi; 

You could either wrap that in a function or use it in a script.

Condensed into a one line condition suitable for bash and zsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1 

14 Comments

@William Pursell Why fork when you don't need to? Mainly for speed in the trivial case.
The answer should be updated to use git rev-parse --is-inside-git-dir. I personally use git rev-parse --is-inside-work-tree before set my PS1.
@juliohm --is-inside-git-dir will only return true if you are actually inside the .git directory of a repository. I don't think the OP is looking for that.
Neither --is-inside-work-tree nor --is-inside-git-dir will work when you are outside of a git repo. see: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
This will fail if the git directory is something other than .git. For robustness, omit the [ -d .git ] and just use git rev-parse ....
|
77

Use git rev-parse --git-dir

if git rev-parse --git-dir > /dev/null 2>&1; then : # This is a valid git repository (but the current working # directory may not be the top level. # Check the output of the git rev-parse command if you care) else : # this is not a git repository fi 

edit: git-rev-parse now (as of 1.7.0) supports --show-toplevel, so you could do if test "$(pwd)" = "$(git rev-parse --show-toplevel)" to determine if the current directory is the top-level dir.

10 Comments

@MImamPratama The > /dev/null redirects stdout to the bit bucket. The 2>&1 sends stderr to the same place.
the --show-toplevel really solved my issues! Thanks a lot.
Why does 2> /dev/null not work?
@ocodo: git rev-parse --is-inside-work-tree prints "true" or "false" to stdout. It prints error messages (such as fatal: not a git repository) to stderr.
|
37

Or you could do this:

inside_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)" if [ "$inside_git_repo" ]; then echo "inside git repo" else echo "not in git repo" fi 

2 Comments

I like this one because it works from a sub directory too
22

Based on @Alex Cory's answer:

[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] 

doesn't contain any redundant operations and works in -e mode.

  • As @go2null noted, this will not work in a bare repo. If you want to work with a bare repo for whatever reason, you can just check for git rev-parse succeeding, ignoring its output.
    • I don't consider this a drawback because the above line is indended for scripting, and virtually all git commands are only valid inside a worktree. So for scripting purposes, you're most likely interested in being not just inside a "git repo" but inside a worktree.

8 Comments

this fails inside of a bare git repo
Rather than checking the output, it is better practice to check the return value. Do not invoke [ at all. Just do if git rev-parse --is-inside-work-tree; then ... (with redirections as desired.)
@WilliamPursell checking the exit value doesn't work here: stackoverflow.com/questions/2180270/…
@Ivan_pozdeev Depends on your definition of "work". In this case, I would say that checking the return value does work, while checking the output does not. In either case, from the perspective of best practice for writing code in the shell, it is more appropriate to check the return value.
@WilliamPursell if you read the linked comment, you'd know what I meant by "doesn't work" here.
|
10

Not sure if there is a publicly accessible/documented way to do this (there are some internal git functions which you can use/abuse in the git source itself)

You could do something like;

if ! git ls-files >& /dev/null; then echo "not in git" fi 

Comments

9

This answer provides a sample POSIX shell function and a usage example to complement @jabbie's answer.

is_inside_git_repo() { git rev-parse --is-inside-work-tree >/dev/null 2>&1 } 

git returns errorlevel 0 if it is inside a git repository, else it returns errorlevel 128. (It also returns true or false if it is inside a git repository.)

Usage example

for repo in *; do # skip files [ -d "$repo" ] || continue # run commands in subshell so each loop starts in the current dir ( cd "$repo" # skip plain directories is_inside_git_repo || continue printf '== %s ==\n' "$repo" git remote update --prune 'origin' # example command # other commands here ) done 

3 Comments

Not sufficient. Inside .git, it will succeed but print false.
@ivan_pozdeev: If git rev-parse --is-inside-work-tree returns true or false then it is inside a git repo, and that is what the function returns. that is, the function is correct
to expand, see the description in the answer, the value returned from git is ignored, the errorlevel is what is used.
9

Why not using exit codes? If a git repository exists in the current directory, then git branch and git tag commands return exit code of 0 (even if there are no tags or branches); otherwise, a non-zero exit code will be returned. This way, you can determine if a git repository exist or not. Simply, you can run:

git tag > /dev/null 2>&1 

Advantage: Portable. It works for both bare and non-bare repositories, and in sh, zsh and bash.

Explanation

  1. git tag: Getting tags of the repository to determine if exists or not.
  2. > /dev/null 2>&1: Preventing from printing anything, including normal and error outputs.

TLDR (Really?!): check-git-repo

As an example, you can create a file named check-git-repo with the following contents, make it executable and run it:

#!/bin/sh if git tag > /dev/null 2>&1; then echo "Repository exists!"; else echo "No repository here."; fi 

3 Comments

The && [ $? -eq 0 ] is redundant, especially if you're already in an if.
does git tag work even when there are no tags?
@jave.web, yes. Thanks for mentioning, added as a side-note.
7

Another solution is to check for the command's exit code.

git rev-parse 2> /dev/null; [ $? == 0 ] && echo 1 

This will print 1 if you're in a git repository folder.

4 Comments

Note that this will have rc 0 even if you're inside the .git directory -- which you may or may not want.
Git's written sanely so you can just close files you don't want, git rev-parse 2>&-.
[ $? == 0 ] is redundant here; that's the implied test that && already does. The above command is equivalent to git rev-parse 2>/dev/null && echo 1.
[ $? == 0 ] is not exactly redundant. If you are using a version of [ that supports ==, then it is exactly equivalent to git rev-parse 2> /dev/null && echo 1. But if you are using a version of [ that does not recognize ==, then this version is an error.
3

# check if git repo

if [ $(git rev-parse --is-inside-work-tree) = true ]; then echo "yes, is a git repo" git pull else echo "no, is not a git repo" git clone url --depth 1 fi 

2 Comments

This is not best practice. If run outside of a working directory, you'll get "fatal: not a git repository (or any of the parent directories): .git" written on stderr, and "no, is not a git repo" on stdout. There's no need to invoke [ here at all. Just do: if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
In my case, I'm comfortable with this, and I want to track this glitch in my logs. Cheers!
3

This works for me. You still get the errors but they're easy enough to suppress. it also works from within subfolders!

git status >/dev/null 2>&1 && echo Hello World! 

You can put this in an if then statement if you need to conditionally do more.

3 Comments

Good enough for many cases perhaps, but it fails on a bare git repo.
git status can be very slow on a big/old repo. I wouldn't use it for this purpose.
@henrebotha I totally agree and I am still doing it, because I would need the output for processing anyways: git_status="$(git status --porcelain --branch 2> /dev/null)"; if [ $? -eq 0 ]; then echo something with $git_status; fi
2

This questions is really old, and there are some nice answers. Yet there is missing one thing: The solution how it is handled by git itself inside it's git-prompt.sh with __git_ps (). Here is the snippet taken from there:

 # [...] local repo_info rev_parse_exit_code repo_info="$(git rev-parse --git-dir --is-inside-git-dir \ --is-bare-repository --is-inside-work-tree \ --short HEAD 2>/dev/null)" rev_parse_exit_code="$?" if [ -z "$repo_info" ]; then return $exit fi local short_sha="" if [ "$rev_parse_exit_code" = "0" ]; then short_sha="${repo_info##*$'\n'}" repo_info="${repo_info%$'\n'*}" fi # [...] 

This is pretty nice, as it seems to handle all the mentioned issues to the other answers given here. Simply by combining the already known parameters in one call of git rev-parse. Maybe this script (git-prompt.sh with __git_ps ()) wasn't available 13 years ago, when this question was asked, but I thought it could be still interesting for people who want to create their own ps1.

1 Comment

Upvoting, this is the only solution using the --is-bare-repository flag (present at least since git 2.0.5 from 2014)
1

While William Pursell's 2010 answer is about two states (in a valid git repository or not), a git rev-parse --is-inside-work-tree is actually more detailed, as illustrated with Git 2.46 (Q3 2024), batch 8:

See commit d424488 (01 May 2024) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 3acecc0, 28 May 2024)

rev-parse: document how --is-* options work outside a repository

When "git rev-parse"(man) is run with the --is-inside-work-tree option and friends outside a Git repository, the command exits with a non-zero status and says "fatal: not a repository".

While it is not wrong per-se, in the sense that it is useless to learn if we are inside or outside a working tree in the first place when we are not even in a repository, it could be argued that they should emit "false" and exit with status 0, as they cannot possibly be "true".

As the current behaviour has been with us for a decade or more since it was introduced in Git 1.5.3 timeframe, it is too late to change it.

And arguably, the current behaviour is easier to use if you want to distinguish among three states, i.e.,

  1. the cwd is not controlled by Git at all
  2. the cwd is inside a working tree
  3. the cwd is not inside a working tree (e.g., .git/hooks/)

with a single invocation of the command by doing

if inout=$(git rev-parse --is-inside-work-tree) then case "$inout" in true) : in a working tree ;; false) : not in a working tree ;; esac else : not in a repository fi 

So, let's document clearly that the command will die() when run outside a repository in general, unless in some special cases like when the command is in the --parseopt mode.

While at it, update the introductory text that makes it sound as if the primary operating mode is the only operating mode of the command, which was written long before we added "--parseopt" and "--sq-quote" modes.

git rev-parse now includes in its man page:

Unless otherwise specified, most of the options and operation modes require you to run this command inside a git repository or a working tree that is under the control of a git repository, and will give you a fatal error otherwise. [...] The command in this mode can be used outside a repository or a working tree controlled by a repository.

Comments

0
##Current branch echo $(git branch --show-current 2> /dev/null && echo '') echo $(git branch --show-current 2> /dev/null) ##OR GIT_DIR=$(git rev-parse --git-dir 2> /dev/null) 

Comments

0

simple use any of the git commands like git branch or on linux machine if u want to search everywhere for .git file to know git folder use these command sudo find / -type d -name ".git"

Comments

0

Since there is no --quiet option, I prefer

git rev-parse --show-toplevel 2>/dev/null 

Since it works in sub-directories and outputs useful info: ~/src/lang/project-git-root

It does not output mostly useless stdout like alternatives:

  • Output .git/ like git rev-parse --is-inside-work-tree(very specific usecase)

  • true like git rev-parse --is-inside-work-tree (obsolete to exit code)

NOTE: If using submodules you should initially check:
git rev-parse --show-superproject-working-tree

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.