GitGit

fatal: not a git repository (or any of the parent directories): .git

Git searched up the directory tree and found no .git. Usually the wrong directory, a clone that failed, or a submodule or container path that lost it.

easy fix6 min read

the git error
fatal: not a git repository (or any of the parent directories): .git

fatal: not a git repository: '.git'

fatal: detected dubious ownership in repository at '/workspace'

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

  1. 1

    Confirm where you are and whether anything above you is a repository

    pwd && git rev-parse --show-toplevel 2>&1

    rev-parse prints the repository root if one exists anywhere up the tree. The same fatal error here confirms there genuinely is no repository above your current directory.

  2. 2

    Look for a .git that exists but is unreadable

    ls -ld .git 2>/dev/null || echo "no .git here"

    A .git that exists while Git says otherwise usually means an ownership or permissions problem rather than a missing repository, which produces the dubious ownership variant of this error.

  3. 3

    If this is genuinely a new project, create the repository

    git init && git add . && git commit -m "Initial commit"

    Only do this when you intend a new repository. Running git init inside what should have been a clone creates a second, empty history and leads to the unrelated histories error later.

All 8 sections

Git looks for a .git directory in the current directory, then each parent, up to the filesystem root. Finding none, it stops. The message is accurate: there is no repository here or above here.

pwd
git rev-parse --show-toplevel

rev-parse --show-toplevel prints the repository root if one exists anywhere up the tree. The same fatal error confirms there is none.

The ordinary causes

Wrong directory. You cloned into ~/projects/myapp and are sitting in ~/projects. The most common cause by a wide margin.

The clone failed. git clone printed an error you scrolled past, so the directory is missing or empty:

ls -la

You never initialised it. A new project needs git init.

.git was deleted. Sometimes by an over-enthusiastic rm -rf or a cleanup script. If you have a remote, re-clone rather than trying to repair.

Be careful with git init

Running git init inside what should have been a clone creates a brand new empty history. Everything looks fine until you add the remote and pull, at which point you get refusing to merge unrelated histories, because you now have two unrelated roots.

If the project exists on a remote, clone it:

git clone git@github.com:acme/myapp.git
cd myapp

The dubious ownership variant

fatal: detected dubious ownership in repository at '/workspace'

This is a different failure with a similar feel. The .git directory exists and is owned by a different user than the one running Git. It was added in Git 2.35.2 to close a real vulnerability: a repository in a shared location could contain configuration that executes commands, so Git now refuses repositories it does not trust.

It shows up constantly in CI containers and on shared build hosts, where the checkout is owned by one uid and the build step runs as another.

ls -ld /workspace/.git
id

Mark it trusted:

git config --global --add safe.directory /workspace

Or fix the ownership, which is the better answer when you can:

sudo chown -R "$(id -u):$(id -g)" /workspace

In a container image you can trust everything, which is acceptable in a disposable build environment and should not be done on a shared machine:

RUN git config --system --add safe.directory '*'

Understand what that disables before using it: it is a security check, and * turns it off entirely.

Submodules

A submodule directory that is empty gives this error inside it:

git submodule status
-a1b2c3d4 vendor/lib

The leading - means not initialised. The files are simply not there:

git submodule update --init --recursive

Clone with submodules in the first place:

git clone --recurse-submodules git@github.com:acme/myapp.git

Note that a submodule's .git is a file, not a directory, containing a gitdir: pointer into the parent's .git/modules. Copying a working tree without the parent's .git breaks every submodule in it, which is a confusing way to meet this error.

GIT_DIR pointing somewhere wrong

env | grep -i '^GIT'

GIT_DIR overrides the search entirely. A stale export in a shell profile, or one left behind by a hook, sends Git to a path that no longer exists.

unset GIT_DIR GIT_WORK_TREE

Git hooks run with GIT_DIR set, so a script invoked from a hook that then operates on a different repository hits this. Unset both at the top of such a script.

In Docker

COPY . /app

.dockerignore containing .git means the image has no repository, so any build step running git describe or git rev-parse HEAD fails.

Excluding .git is usually right, since it can be large and it invalidates the build cache on every commit. Pass the value in instead of shipping the repository:

ARG GIT_SHA=unknown
LABEL org.opencontainers.image.revision=$GIT_SHA
docker build --build-arg GIT_SHA="$(git rev-parse HEAD)" .

Also note that many CI systems perform a shallow clone by default, --depth 1, so git describe --tags finds no tags and git log shows one commit. That is not this error, but it comes from the same place and is worth knowing.

A checklist

  1. pwd, then git rev-parse --show-toplevel.
  2. Wrong directory is the most likely answer. cd into the project.
  3. Empty directory → the clone failed. Re-run it and read the output.
  4. Only run git init for a genuinely new project.
  5. dubious ownershipgit config --global --add safe.directory <path>, or fix ownership.
  6. Empty submodule → git submodule update --init --recursive.
  7. env | grep GIT for a stale GIT_DIR.
  8. In Docker, .dockerignore excluding .git breaks build-time git commands. Pass a build arg.

Frequently Asked Questions

What does "or any of the parent directories" mean?

Git does not only look in your current directory. It walks up through each parent to the filesystem root looking for a .git, so the message is telling you that nothing anywhere above you is a repository either. That rules out the common assumption of being one level too deep inside a project. git rev-parse --show-toplevel performs the same search and prints the root when it finds one, which makes it a quick way to confirm.

Should I run git init to fix this?

Only if you intend to create a new repository. If the project already exists on a remote, git init creates a second empty history that has nothing in common with it, and you will hit refusing to merge unrelated histories as soon as you add the remote and pull. Clone instead. git init is the right answer for a genuinely new project, and the wrong answer for a clone that failed or a directory you are simply standing in by mistake.

What is "detected dubious ownership" and why did it start appearing?

Git 2.35.2 added a check that refuses to operate on a repository owned by a different user, because a repository in a shared location can carry configuration that runs commands, making it a real escalation path. It appears most often in CI containers and on shared build machines where the checkout and the build step run as different users. Add the path with git config --global --add safe.directory <path>, or fix the ownership with chown, which is preferable when you control the environment.

Why do I get this inside a submodule directory?

Because the submodule has not been initialised, so the directory exists and is empty. git submodule status shows a leading - against any submodule in that state. Run git submodule update --init --recursive, or clone with --recurse-submodules to avoid it. Worth knowing: a submodule's .git is a file containing a gitdir: pointer into the parent repository's .git/modules, so copying a working tree without the parent's .git breaks every submodule inside it.

Why do git commands fail inside my Docker build?

Almost certainly because .git is listed in .dockerignore, so the repository is not in the build context and any git describe or git rev-parse in a RUN step has nothing to work with. Excluding it is usually correct, since the directory can be large and changes on every commit, which invalidates the build cache. Pass the values you need in as build arguments instead, for example --build-arg GIT_SHA="$(git rev-parse HEAD)", which keeps the context small and the cache useful.

Reference and practice

Learn the underlying concept

Other Git errors