anon
anon

Reputation: 42697

Check if current directory is a Git repository

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).

Upvotes: 353

Views: 215143

Answers (15)

VonC
VonC

Reputation: 1329092

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.

Upvotes: 1

Yash Shah
Yash Shah

Reputation: 21

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"

Upvotes: 0

MAChitgarha
MAChitgarha

Reputation: 4298

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

Upvotes: 9

ChaosOptimum
ChaosOptimum

Reputation: 31

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.

Upvotes: 2

TM.
TM.

Reputation: 111127

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

Upvotes: 288

DEV Tiago França
DEV Tiago França

Reputation: 1716

##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)

Upvotes: 0

ivan_pozdeev
ivan_pozdeev

Reputation: 36106

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.

Upvotes: 22

William Pursell
William Pursell

Reputation: 212634

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.

Upvotes: 76

CharlesTWall3
CharlesTWall3

Reputation: 546

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.

Upvotes: 3

jabbie
jabbie

Reputation: 2714

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

Upvotes: 217

Pascal Andy
Pascal Andy

Reputation: 61

# 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

Upvotes: 3

go2null
go2null

Reputation: 2308

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

Upvotes: 9

Alex Cory
Alex Cory

Reputation: 11875

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

Upvotes: 37

user2095363
user2095363

Reputation:

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.

Upvotes: 7

James
James

Reputation: 255

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

Upvotes: 10

Related Questions