nix.sh: fails immediately when run from a git worktree ("fatal: not a git repository")
メンテナーはふだん 3 日以内に返信
評価
- 難易度
- 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 の本文から書いたものです。
説明
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(hostgit version 2.46.0,go version go1.26.7 darwin/arm64; container imagenixos/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
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
crossplane/cli のほかの issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
crossplane/cli#432 ·
メンテナーはふだん 3 日以内に返信
-
`credsStore` in docker config causes unit test failures対応中かも @sujeito-operator が 59 日前に担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
crossplane/cli#282 ·
メンテナーはふだん 3 日以内に返信
-
Generated schemas go stale because each source writes into the shared tree on its own対応中かも @stevendborrelli が 2 日前に担当しました。 オープンenhancement
難易度 4/5 3〜5日 初心者へのやさしさ 18/100
crossplane/cli#428 ·
メンテナーはふだん 3 日以内に返信
-
bug
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
crossplane/cli#424 ·
メンテナーはふだん 3 日以内に返信
-
enhancement
難易度 4/5 3〜5日 初心者へのやさしさ 42/100
crossplane/cli#410 ·
メンテナーはふだん 3 日以内に返信
似ている issue
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:session-state issue-rating: 🦞 diamond lobster no-stale P2
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
openclaw/wacli#503 · コメント 1 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 81/100
apache/rocketmq-dashboard#6895 ·
メンテナーはふだん 3 日以内に返信
-
agent-butler-finding chore
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
jordansmall/spindrift#5466 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
open-telemetry/opentelemetry-go-compile-instrumentation#1507 ·
メンテナーはふだん 3 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 87/100
777genius/agent-notifications#490 ·
メンテナーはふだん 1 日以内に返信