git-for-windows / git

A fork of Git containing Windows-specific patches.
http://gitforwindows.org/
Other
8.35k stars 2.53k forks source link

headless-git maintenance locks repository forever when askPass is triggered #4706

Open JustusGreiberORGADATA opened 11 months ago

JustusGreiberORGADATA commented 11 months ago

Setup

$ git --version --build-options

git version 2.42.0.windows.2
cpu: x86_64
built from commit: 2f819d1670fff9a1818f63b6722e9959405378e3
sizeof-long: 4
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.22621.2715]
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
> type "$env:USERPROFILE\AppData\Local\Programs\Git\etc\install-options.txt"
$ cat /etc/install-options.txt

Editor Option: VIM
Custom Editor Path:
Default Branch Option:
Path Option: Cmd
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: OpenSSL
CRLF Option: CRLFAlways
Bash Terminal Option: MinTTY
Git Pull Behavior Option: FFOnly
Use Credential Manager: Enabled
Performance Tweaks FSCache: Enabled
Enable Symlinks: Disabled
Enable Pseudo Console Support: Disabled
Enable FSMonitor: Disabled

When our git server restarts the git client will fail to authenticate and use askPass to ask for a username and password. The restarts coincide with the times set in the task scheduler by git maintenance start. IMHO the issue is a general one though and not really special to this environment.

Details

Git Bash in Windows Terminal. But in the real world this issue likely happens outside the terminal in the Windows Task Scheduler.

The actual problem occurs when git maintenance tasks are running in the Windows Task Scheduler. The minimal example below just reproduces the issue in a terminal.

# you need a git server which will trigger askPass. I reproduced this, by deleting the credentials I had
# (The blank line below protocol signals the input is complete.)
$ git credential-manager erase
host=github.com
protocol=https

# If credential manager is installed the next command might open a window or two.
# After the user closes those windows git will fallback to askPass. The user can't type in the password though,
# because headless-git is used.
# SIGINT also does not work so you need to kill the task some other way.
$ "C:/Program Files/Git/mingw64/libexec/git-core/headless-git.exe" maintenance run --task=prefetch

# When the previous command started, it locked the repo with .git/objects/maintenance.lock
# All maintenance commands after that will fail:
$ git maintenance run --task=prefetch
warning: lock file '.git/objects/maintenance' exists, skipping maintenance

I expected headless-git to not start any terminal interaction, because there is no way for the user to interact with the terminal. If headless-git is just a helper to facilitate git maintenance start I could live with the fact that it is not truly "headless" as long as the task that are registered in the Windows Task Scheduler set git config values to prevent the terminal interactions, e. g.

git -c "core.askPass=true" -c "credential.interactive=false" for-each-repo --config=maintenance.repo maintenance run --schedule=daily

(This is not a good solution if the graphical user interfaces triggered by askPass and Credential Manager are desired though and only the terminal interaction should be suppressed. I sadly haven't found a config value to only deactivate terminal interaction.)

It did start a terminal interaction and locked all maintenance commands.

dscho commented 11 months ago

I guess we need to upstream https://github.com/microsoft/git/pull/598 (patches 2-4, that is).

dscho commented 11 months ago

git -c "core.askPass=true" -c "credential.interactive=false" for-each-repo --config=maintenance.repo maintenance run --schedule=daily

FWIW the reason why this does not work as intended is that credential.interactive is only supported in the Microsoft fork of Git so far.