#769 pre_push_check detaches HEAD when running from a git worktree
Closed: Fixed by onosek. Opened by vashirov.

When git push is run from a git worktree, the pre-push hook invokes rhpkg pre-push-check, which detaches HEAD in the worktree. After the push completes, the worktree is left in a "detached HEAD" state even though the push itself succeeded.

When git runs a command from a worktree, it sets GIT_DIR in the process environment to the worktree's git directory (e.g. .git/worktrees/<name>). For regular repos GIT_DIR is not set because the gitdir is the default .git, but for worktrees it's an absolute path, so git exports it via xsetenv("GIT_DIR", path, 1).

The pre-push hook inherits this environment. When pre_push_check() runs, it creates a temporary clone and runs git checkout <sha> in it:

https://pagure.io/rpkg/blob/master/f/pyrpkg/init.py#_4583-4589

Although cwd=clone_dir is passed, _run_command() inherits os.environ which contains GIT_DIR pointing to the source worktree's git directory. GIT_DIR takes precedence over cwd, so git checkout <sha> operates on the worktree instead of the temporary clone, detaching its HEAD.

Steps to reproduce:
1. Clone a dist-git repo and create a worktree:

rhpkg clone <package>
cd <package>
git worktree add ../my-worktree <branch>
cd ../my-worktree
  1. Make a commit and push:
# edit files, commit
git push
  1. Check HEAD state:
git symbolic-ref HEAD
# fatal: ref HEAD is not a symbolic ref

The issue can also be reproduced without pushing:

GIT_DIR=$(git rev-parse --git-dir) rhpkg pre-push-check $(git rev-parse HEAD)
git symbolic-ref HEAD
# fatal: ref HEAD is not a symbolic ref

Commit 2812d5ac fixes this issue

Metadata
Related Pull Requests