git push se queda colgado sin mensaje: credenciales

Ejecutas git fetch o git push contra GitHub por HTTPS desde WSL2, desde un script o desde una herramienta de automatización sin terminal interactiva. El comando no imprime nada y no termina: pasan más de dos minutos y, si lo repites con la opción de detalle, tampoco muestra salida. Para completar el cuadro, al intentar revisar la sesión de GitHub CLI en WSL ocurre esto:

$ git fetch
(sin salida; el comando no regresa)

$ git push -v origin main
(sin salida)

$ gh auth status
bash: gh: command not found

No hay un mensaje de error que buscar, y por eso el problema desconcierta. Este artículo explica qué está esperando Git, cómo hacer que falle de inmediato con un mensaje útil y cómo dejar la autenticación fija para que no vuelva a pasar.

Por qué pasa

Con una URL HTTPS, Git necesita un usuario y una contraseña o token. Según la documentación de credenciales de Git, primero consulta los credential helpers configurados; si ninguno entrega las credenciales, recurre a los programas de entrada (GIT_ASKPASS, core.askPass, SSH_ASKPASS) y, en último lugar, pregunta en la terminal.

En Windows, el helper habitual es Git Credential Manager (GCM). La documentación de GCM explica que puede interactuar con el usuario mediante ventanas o mensajes en terminal, y dedica una sección a un aviso de selección de cuenta ("Prompted to select an account?"), que corresponde al caso de tener varias cuentas disponibles para el mismo servidor. Si el proceso que lanza Git no tiene una terminal visible (WSL sin sesión interactiva, una herramienta de automatización, un script programado, CI), esa ventana o esa pregunta queda donde nadie la ve, y Git se queda esperando una respuesta que no llegará.

Tres detalles de WSL agravan la confusión:

  • Cuando WSL usa el GCM de Windows (la documentación de GCM explica cómo enlazarlo), se trata de un programa de Windows que, según esa misma documentación, lee la configuración de Git para Windows y no la de Git dentro de WSL.
  • Las variables de entorno de tu shell de Linux no llegan solas a los programas de Windows; deben estar listadas en WSLENV, según la documentación de WSL.
  • Las herramientas de Windows se invocan desde WSL con su extensión (gh.exe), por lo que un gh instalado en Windows no responde al comando gh dentro de la distribución. De ahí el command not found.

Solución

  1. Haz que falle rápido para ver el error real. GIT_TERMINAL_PROMPT=0 impide que Git pregunte en la terminal, y GCM_INTERACTIVE=never impide que GCM muestre ventanas o preguntas (la documentación de GCM acepta también false). Añade un tiempo máximo con timeout para no depender de la paciencia:

    export GIT_TERMINAL_PROMPT=0
    export GCM_INTERACTIVE=never
    timeout 60 git fetch

    En PowerShell, usa $env:GIT_TERMINAL_PROMPT = '0' y $env:GCM_INTERACTIVE = 'never'. Si Git necesita credenciales y no puede preguntar, termina con un mensaje como este:

    fatal: could not read Username for 'https://github.com': terminal prompts disabled

    Esto no autentica nada: convierte una espera silenciosa en un error accionable. Si timeout corta el comando, su estado de salida es 124; cuando Git termina con un fatal como el anterior, el estado es 128. Desde WSL, para que GCM_INTERACTIVE llegue al GCM de Windows, añádela a WSLENV antes de lanzar Git:

    export WSLENV="${WSLENV:+$WSLENV:}GCM_INTERACTIVE"

    Otra vía, según la documentación de GCM, es la opción de configuración equivalente credential.interactive con el valor never, que debes fijar en la configuración de Git para Windows (la que lee GCM).

  2. Fija la cuenta de GitHub. Si hay dos cuentas guardadas y GCM no sabe cuál usar, indícalo en la configuración. La documentación de credenciales de Git describe las opciones específicas por URL, y la de GCM muestra este mismo comando para GitHub:

    git config --global credential.https://github.com.username <usuario>

    Después, ejecuta una vez un git fetch normal desde una terminal visible para que GCM pueda guardar la autorización de esa cuenta si todavía no la tiene.

  3. Usa GitHub CLI como credential helper. Es la opción más simple en WSL, porque no depende del GCM de Windows. Instala gh dentro de la distribución con el método que indica su documentación de instalación para Linux, inicia sesión y regístralo en Git:

    gh auth login
    gh auth setup-git

    Según la documentación de gh, gh auth setup-git configura Git para usar GitHub CLI como credential helper. Por defecto aplica a todos los servidores en los que ya iniciaste sesión; con --hostname github.com se limita a uno. Si prefieres seguir con el GCM de Windows desde WSL, la documentación de GCM indica apuntar credential.helper al ejecutable git-credential-manager.exe de Git para Windows (la ruta exacta depende de tu instalación y versión).

  4. Considera SSH. Con una clave SSH registrada en tu cuenta, no intervienen contraseñas ni helpers. Cambia el remoto a la URL SSH que GitHub muestra en el botón de clonado del repositorio:

    git remote set-url origin <url-ssh-del-repositorio>

    La documentación de GitHub explica que SSH requiere generar un par de claves y agregar la clave pública a tu cuenta.

Un antipatrón que debes evitar: incrustar un token dentro de la URL del remoto para que "ya no pregunte". La URL del remoto se guarda en texto plano en .git/config y el comando con el token queda en el historial de la shell. Un helper de credenciales existe precisamente para no tener que hacerlo.

Cómo verificar que quedó resuelto

time timeout 60 git ls-remote origin
time timeout 60 git fetch
git config --global --get credential.https://github.com.username

Los dos primeros comandos deben terminar en segundos y sin pedir nada; antes de la corrección, el mismo git fetch podía tardar más de dos minutos sin responder. El tercero debe mostrar el usuario que fijaste. Para ver qué helper se ejecuta realmente, lanza GIT_TRACE=1 git fetch: la documentación de Git indica que ese valor imprime trazas generales de la ejecución en la salida de error. Por último, en un repositorio donde puedas crear ramas, un git push a una rama de prueba debe completarse sin intervención:

git push origin HEAD:refs/heads/prueba-credenciales
git push origin --delete prueba-credenciales

Variantes y errores relacionados

Con la solución 1 aplicada falla de inmediato con "terminal prompts disabled"

Es lo esperado: ahora ves el problema real, que es que no hay credenciales utilizables. Aplica la solución 2 o la 3 y vuelve a probar. Quita las variables del entorno cuando termines de diagnosticar si quieres recuperar la interactividad en tus sesiones normales.

Varias cuentas de GitHub en la misma máquina

La documentación de GCM ofrece los subcomandos github list, github login y github logout para revisar y gestionar las cuentas guardadas; consulta la ayuda de tu versión con git-credential-manager github --help. Para una cuenta distinta en un solo repositorio, la misma documentación sugiere incluir el nombre de usuario (nunca el token) en la URL del remoto.

El comando sigue colgado aunque ya no pregunta

Si timeout corta el comando con estado 124 y ya no hay ningún aviso pendiente, el problema deja de ser de credenciales: revisa la conexión, un proxy o un cortafuegos. Para ver dónde se detiene, GIT_TRACE=1 git fetch es un buen primer paso.

Un token con permisos insuficientes o caducado

Si el error cambia a un rechazo de autenticación, la causa ya no es el aviso invisible. Genera un token nuevo o vuelve a iniciar sesión con gh auth login. Si tu organización usa inicio de sesión único (SSO) con SAML, la documentación de GitHub indica que debes autorizar el token (o la clave SSH) para esa organización.

Resumen

  • Un git fetch o git push HTTPS que se cuelga sin salida suele estar esperando una pregunta de credenciales que nadie ve (selector de cuenta de GCM o aviso de terminal).
  • Para diagnosticar, usa GIT_TERMINAL_PROMPT=0, GCM_INTERACTIVE=never y timeout 60: el comando falla en segundos con un mensaje claro.
  • Para corregir, fija la cuenta con credential.https://github.com.username o usa gh auth setup-git como credential helper (instalando gh dentro de WSL).
  • SSH es una alternativa que evita los helpers; nunca pongas un token en la URL del remoto.
  • Verifica con git ls-remote origin y git fetch: deben responder en segundos.

Referencias

Comentarios