# How `safe.bareRepository` Mode Affects Git Operations in no-mistakes

> Learn how safe.bareRepository mode in Git impacts operations. Understand when explicit --git-dir flags are required to avoid discovery issues.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: deep-dive
- Published: 2026-07-17

---

**When `safe.bareRepository` is set to `explicit`, Git refuses to automatically discover bare repositories via the current working directory, requiring the `--git-dir` flag to be explicitly provided for all operations.**

The `no-mistakes` pipeline executes automation steps inside a *gate* repository—a bare Git repository that receives pushes from the user's working tree. In hardened CI environments and agent harnesses (including the Claude Code harness), this Git configuration blocks cwd-based repository discovery, forcing the tool to adapt how it invokes Git commands. Understanding this interaction is essential when working with the `kunchenguid/no-mistakes` codebase, particularly the wrapper logic implemented in [`internal/git/git.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/git/git.go).

## What is `safe.bareRepository=explicit`

**`safe.bareRepository=explicit`** is a Git configuration variable designed to prevent security issues in multi-user or automated environments. When active, it tells Git to **disallow automatic discovery of a bare repository through the current working directory**. 

Normally, Git traverses upward from the cwd to locate a `.git` directory. However, with `explicit` mode enabled, any Git command that would rely on this implicit discovery—whether triggered by the cwd or the `-C` flag—will abort unless the repository path is specified explicitly via `--git-dir`.

## Impact on Git Command Execution

The restriction fundamentally changes how Git commands behave when targeting bare repositories:

- **`git rev-parse --show-toplevel`**: Without explicit configuration, this uses cwd to locate the repo root. With `safe.bareRepository=explicit`, the command is refused if Git cannot verify the repository path explicitly.
- **`git remote add`**, **`git push`**, and **`git fetch`**: These operations fail with the error *"fatal: cannot use bare repository without specifying --git-dir"* if executed from within or relative to a bare repository directory without the `--git-dir` flag.
- **Daemon operations**: Background processes that initialize, fetch, or checkout from gate repositories cannot rely on directory context and must declare the repository location explicitly.

## How no-mistakes Adapts to Explicit Bare Repository Mode

The `no-mistakes` tool handles this constraint globally through a centralized Git wrapper that automatically injects the required flags when operating on gate repositories.

### The `git.Run` Wrapper in [`internal/git/git.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/git/git.go)

All Git operations that touch the gate repository flow through [`internal/git/git.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/git/git.go), specifically the **`Run`** function. This function acts as the sole entry point for executing Git binaries, ensuring consistent handling of bare repositories across the codebase.

Before invoking the `git` binary, `Run` checks whether the supplied directory is a bare Git repository using the helper **`isBareGitDir`**. If the target is bare, the function automatically prefixes the Git arguments with `--git-dir=<dir>`, effectively bypassing the cwd-based discovery restriction.

### Bare Repository Detection and Flag Injection

The detection logic ensures that any command targeting a gate repository receives the proper context:

```go
// Example: Running a Git command on a gate (bare) repository.
ctx := context.Background()
gatePath := "/path/to/gate-repo" // a bare repository

// `Run` will detect the bare repo and prepend `--git-dir`.
out, err := git.Run(ctx, gatePath, "rev-parse", "--git-dir")
if err != nil {
    log.Fatalf("git failed: %v", err)
}
fmt.Println("Git dir:", out) // prints the absolute path of the bare repo

```

This pattern guarantees that tools like **`FindGitRoot`**, **`AddRemote`**, and **`Push`** function correctly regardless of the `safe.bareRepository` setting. For example, `AddRemote` internally uses `Run`, which adds the `--git-dir` flag automatically when `isBareGitDir` returns true:

```go
// Adding a remote to the gate repo – no need to manually add `--git-dir`.
func addRemote(ctx context.Context, repoPath, name, url string) error {
    return git.AddRemote(ctx, repoPath, name, url) // internally uses Run
}

```

### Explicit Directory Resolution

Higher-level functions like `FindGitRoot` still operate correctly because they invoke Git directly through the `Run` wrapper with an explicit directory argument, rather than relying on the process's working directory. This maintains deterministic repository layout even in hardened environments affected by issue #362.

## Implementation Examples

When building custom extensions or debugging the `no-mistakes` daemon, you can detect bare repositories explicitly before issuing commands:

```go
// Detecting a bare repository before issuing a command.
if git.IsBareGitDir(gatePath) {
    // Custom logic if needed; otherwise just call Run().
    fmt.Println("Running against a bare repo")
}

```

The wrapper ensures that even complex operations like initializing new gate repositories or fetching updates respect the security constraint. By centralizing this logic in [`internal/git/git.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/git/git.go), the codebase avoids scattered `--git-dir` flags and maintains a single source of truth for repository discovery.

## Summary

- **`safe.bareRepository=explicit`** blocks Git from automatically discovering bare repositories through the current working directory, preventing cwd-based attacks.
- **`internal/git/Run`** in `no-mistakes` automatically detects bare repositories via `isBareGitDir` and injects `--git-dir=<path>` to satisfy explicit mode requirements.
- **All Git operations** targeting gate repositories—including `Push`, `AddRemote`, and `FindGitRoot`—flow through this wrapper, ensuring compatibility with hardened CI environments.
- **Failure to provide `--git-dir`** results in the fatal error *"cannot use bare repository without specifying --git-dir"* when explicit mode is active.

## Frequently Asked Questions

### What does `safe.bareRepository=explicit` do?

This Git configuration variable tells Git to disallow automatic discovery of bare repositories by traversing the directory tree from the current working directory. When set, Git will only operate on a bare repository if you explicitly provide the path using the `--git-dir` flag, preventing potential security issues in shared or automated environments.

### How does no-mistakes detect and handle bare repositories?

The `no-mistakes` tool uses the `isBareGitDir` helper function in [`internal/git/git.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/git/git.go) to check if a target directory is a bare repository. When `Run` detects a bare repo, it automatically prepends `--git-dir=<directory>` to the Git command arguments, ensuring all operations specify the repository explicitly as required by `safe.bareRepository=explicit`.

### What error occurs if `--git-dir` is omitted in explicit mode?

If you attempt to run a Git command against a bare repository without specifying `--git-dir` while `safe.bareRepository=explicit` is active, Git aborts with the error: *"fatal: cannot use bare repository without specifying --git-dir"*. The `no-mistakes` wrapper prevents this by always adding the flag for bare gate repositories.

### Why is this pattern important for CI and agent environments?

Hardened CI systems, agent harnesses, and tools like the Claude Code harness often set `safe.bareRepository=explicit` to prevent malicious repositories from being accidentally loaded. By enforcing explicit `--git-dir` usage, `no-mistakes` ensures pipeline steps work reliably across different security postures without requiring users to manually configure Git security settings.