Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

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

未关闭
#425 0 条评论 0 个 reaction 已指派 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 小时
30 天内合并 PR
21

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

crossplane/cli 的其他 Issue

查看 crossplane/cli 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。