Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

nix.sh: fails immediately when run from a git worktree ("fatal: not a git repository")

オープン
#425 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 3 日以内に返信

@boxcee-interview がすでに取り組んでいます。

2026年10月14日 から。

  • #427 @boxcee-interview による — オープン

評価

難易度
3/5
見積もり時間
半日
初心者へのやさしさ
62/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
docker, git, shell

調査の方向性

Start in nix.sh: the git config --global --add safe.directory call and the docker run block that mounts only $(pwd). Reproduce with git worktree add --detach ../cli-wt origin/main, then run ./nix.sh flake metadata from the worktree. Check what git rev-parse --git-common-dir returns there. Done when the command exits 0 in the worktree and still works in a full clone.

索引モデルが issue の本文から書いたものです。

説明

bug

Usernames and home paths in captured output are redacted to me / /Users/me.

What happened?

./nix.sh fails before Nix starts when it runs from a checkout created with git worktree add:

$ ./nix.sh flake metadata; echo "\$? = $?"
fatal: not a git repository: /Users/me/workspace/crossplane-cli/.git/worktrees/probe-flakes
$? = 128

./nix.sh flake check and every other subcommand fail the same way.

nix.sh
bind-mounts only $(pwd) at /crossplane-cli. In a worktree, .git is a file containing
gitdir: /…/crossplane-cli/.git/worktrees/<name>, a path in the main clone that isn't mounted into the
container. The first git command inside the container is
git config --global --add safe.directory /crossplane-cli.
Even with --global, git runs repository discovery from the working directory. It finds the dangling
gitfile and exits 128, and set -e aborts the script.

Expected: nix.sh works from a worktree just as it does from a full clone. Worktrees are a common way to
work on several PRs at once.

Mounting the main clone's git directory alone isn't enough. Nix reads the repository through libgit2, and
libgit2 takes the worktree's path from the path recorded in .git/worktrees/<name>/gitdir, which is the
host path, and checks safe.directory against that path. Here's what I hit with progressively more
complete setups. Each is the final error line of nix flake metadata in a hand-run nixos/nix
container, abridged to that line:

  • Common git dir mounted at its host path, safe.directory /crossplane-cli:

    error: opening Git repository "/crossplane-cli": repository path '/crossplane-cli/.git' is not owned by current user (libgit2 error code = 7)
    
  • Same, but safe.directory '*':

    error: getting working directory status: failed to open directory '/Users/me/workspace/crossplane-cli-worktrees/probe-flakes/': No such file or directory (libgit2 error code = 2)
    
  • Common git dir and worktree both mounted at their host paths, safe.directory /crossplane-cli:

    error: opening Git repository "/crossplane-cli": repository path '/Users/me/workspace/crossplane-cli-worktrees/probe-flakes' is not owned by current user (libgit2 error code = 7)
    

Adding the worktree's host path to safe.directory as well makes it work.

How can we reproduce it?
git -C crossplane-cli worktree add --detach ../cli-wt origin/main
cd ../cli-wt
./nix.sh flake metadata

Possible fix: when git rev-parse --git-common-dir resolves outside $(pwd), also bind-mount the
common git dir and the worktree at their host paths, and add the worktree's host path to
safe.directory inside the container. The worktree's own gitdir (<common>/worktrees/<name>) is inside
the common dir, so it doesn't need a separate mount. Full clones are unaffected, because GIT_MOUNTS
stays empty. If the host's git is older than 2.31 and doesn't support --path-format=absolute, the
rev-parse fails, GIT_MOUNTS stays empty, and the current behavior is unchanged.

--- a/nix.sh
+++ b/nix.sh
@@ -43,6 +43,9 @@ if [ "${NIX_SH_CONTAINER:-}" = "1" ]; then
 	# by the host user. Git refuses to operate in directories owned by other
 	# users.
 	git config --global --add safe.directory /crossplane-cli
+	if [ -n "${NIX_SH_HOST_PWD:-}" ]; then
+		git config --global --add safe.directory "${NIX_SH_HOST_PWD}"
+	fi
 
 	# Record the current time. After nix runs, we'll find files newer than this
 	# marker and chown them to the host user.
@@ -108,9 +111,20 @@ if [ -t 1 ]; then
 	INTERACTIVE_FLAGS="-it"
 fi
 
+# In a git worktree, .git is a file pointing into the main clone's git
+# directory, outside $(pwd), and that directory records the worktree's host
+# path. Mount both at their host paths so git and Nix (libgit2) can resolve
+# them inside the container.
+GIT_MOUNTS=()
+common_dir=$(git rev-parse --path-format=absolute --git-common-dir 2>/dev/null || true)
+if [ -n "${common_dir}" ] && [ "${common_dir}" != "$(pwd -P)/.git" ]; then
+	GIT_MOUNTS+=(-v "${common_dir}:${common_dir}" -v "$(pwd -P):$(pwd -P)" -e "NIX_SH_HOST_PWD=$(pwd -P)")
+fi
+
 # Run with --privileged for Docker-in-Docker (required for kind clusters).
 docker run --rm --privileged --cgroupns=host ${INTERACTIVE_FLAGS} \
 	-v "$(pwd):/crossplane-cli" \
+	"${GIT_MOUNTS[@]}" \
 	-v "crossplane-cli-nix:/nix" \
 	-w /crossplane-cli \
 	-e "NIX_SH_CONTAINER=1" \

With this patch applied in the same worktree, flake metadata succeeds. The tree shows as dirty only
because the patch itself is uncommitted. Output abridged (… marks the elided Last modified/Inputs
lines) and ANSI colors removed:

$ ./nix.sh flake metadata; echo "\$? = $?"
warning: Git tree '/crossplane-cli' is dirty
Resolved URL:  git+file:///crossplane-cli
Description:   Crossplane CLI
Path:          /nix/store/4q08d2cyiydvz2faxwscj76qb1kax2lv-source
Revision:      29316fea54f2ede9d2c039d9c54f0c29cbad4b65-dirty
…
$? = 0

The same patched script also still works in a full clone (./nix.sh flake metadata exits 0). I only
tried flake metadata, not a full flake check. I also haven't tried worktrees created with
git worktree add --relative-paths (or worktree.useRelativePaths), whose gitfile holds a relative path.
That relative path would resolve against /crossplane-cli inside the container and probably needs the
worktree mounted at its host path and used as the working directory instead.

What environment did it happen in?
  • Crossplane CLI version: main @ 29316fea54f2ede9d2c039d9c54f0c29cbad4b65 (host git version 2.46.0, go version go1.26.7 darwin/arm64; container image nixos/nix, nix (Nix) 2.34.7)
  • Platform (e.g., linux/amd64): darwin/arm64, Docker Engine 29.5.3 (Rancher Desktop)
  • Crossplane version (if applicable): n/a
主要言語
Go
スター
20
フォーク
34
平均マージ
5日 4時間
マージ済み PR(30日)
21

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

crossplane/cli のほかの issue

crossplane/cli の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。