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 小时
- 30 天内合并 PR
- 21
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 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 于 58 天前认领。 未关闭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 于 1 天前认领。 未关闭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
-
oss/0 pending team/container-integrations
难度 2/5 1-3 小时 新手友好度 68/100
DataDog/datadog-agent#58323 ·
维护者通常 1 天内回复
-
bug
难度 2/5 半天 新手友好度 72/100
维护者通常 1 天内回复
-
kind/bug
难度 2/5 1-3 小时 新手友好度 62/100
kubernetes-sigs/external-dns#6816 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
ANSI translator ignores SGR 22/24 (and other attribute-off codes): bold and underline never turn off未关闭
难度 2/5 1-3 小时 新手友好度 78/100