El correo de un cliente en mi repo personal: por qué existe git-wrong-email
Un día mis proyectos personales empezaron a firmar los commits con el correo del cliente para el que trabajo, en lugar del mío. Un cliente gráfico de git había reescrito mi configuración global, y nada me avisó.
El 13 de octubre, mirando un historial de commits público, vi que mis commits más recientes en un proyecto personal no llevaban mi correo. Llevaban el del cliente para el que trabajo.
No es un detalle estético. Un commit queda público para siempre con el correo que lleva, y ese no era un correo para usar en mis proyectos.
Lo que tenía
Creía tenerlo resuelto. El trabajo del cliente vive en su propia carpeta dentro de ~/Code, y en ~/.gitconfig un includeIf le asigna su correo:
[user]
name = Sergio Infante
email = [email protected]
[includeIf "gitdir:~/Code/cliente/"]
path = ~/.config/git/identity-cliente
El archivo identity-cliente define el user.email del cliente. Si el repo está bajo ~/Code/cliente/, git usa ese correo. Si no, usa el correo global, que es el personal. Es la solución que recomienda casi cualquier guía, y funciona.
Cómo pasó
No había tocado nada. El que lo tocó fue un cliente gráfico de git que uso, con una opción llamada más o menos “mantener mi .gitconfig actualizado con la información de mi perfil”. Esa opción reescribió el user.email global con el correo de la cuenta en la que tenía la sesión abierta, que era la del cliente.
Los repos del cliente no se enteraron, porque su includeIf seguía ganando. Pero mis repos personales no tenían un includeIf propio: dependían del correo global, que era justo el valor que acababa de cambiar. Todos empezaron a firmar con el correo del cliente, y git no tenía ningún motivo para quejarse.
Por qué lo que tenía no me avisó
includeIf asigna, no verifica. Le dice a git qué correo usar en una carpeta. No tiene forma de decirte que el correo que git va a usar no es el que esperabas, porque no sabe qué esperabas. Si el includeIf no aplica, por la razón que sea, git usa lo que haya y sigue de largo.
user.useConfigOnly no cubre este caso. Lo tenía activado. Hace que git se niegue a inventar una identidad del tipo usuario@nombre-de-la-mac cuando no hay ninguna configurada. Está bien activarlo, pero aquí el correo sí estaba configurado. Estaba configurado mal.
Un pre-commit en cada repo tampoco alcanza. Existen hooks que revisan el correo, pero hay que agregarlos repo por repo, con un archivo de configuración dentro del repo. No puedo hacer eso en el repo del cliente, me olvidaría en el próximo repo que clone, y además solo revisan al hacer el commit.
Y el cliente gráfico de git no era el único riesgo. También hago commits desde la terminal, desde el editor y, cada vez más, desde agentes de código. Cualquiera de ellos puede traer su propia idea de quién soy.
Lo que necesitaba de verdad
No me hacía falta otra forma de asignar el correo, eso ya lo tenía. Me hacía falta algo que revisara el resultado:
- Mirar el correo que git va a poner en el commit, no la configuración. Así no importa cómo llegó ahí el correo equivocado: un
.gitconfigreescrito, unincludeIfmal escrito, una variable de entorno o un repo clonado en la carpeta equivocada. - Una regla por carpeta, escrita una vez. “En esta carpeta solo se aceptan estos correos.” Y si un repo no cae en ninguna regla, que lo rechace: un repo sin regla es un repo en el que todavía no pensé.
- Que cubra toda la máquina sin tocar ningún repo. Los que ya tengo, los que clone mañana y los del cliente, donde no puedo agregar nada.
- Que funcione con cualquier herramienta: la terminal, el editor, el cliente gráfico o un agente.
- Que revise también antes del push. Un commit puede saltarse el chequeo con
--no-verifyo llegar por un rebase, pero lo que importa es que no salga de la máquina.
git-wrong-email
Ese mismo día escribí la primera versión, como parte de los archivos de configuración que mantengo con macsetup. Al día siguiente ya tuve que arreglarla: bloqueaba un push porque había un merge de commits que ya estaban públicos con otro correo, y frenar un push por historia que nadie puede corregir solo te enseña a usar --no-verify. Unos días después la separé en su propio proyecto, git-wrong-email.
Es un solo script de shell, sin dependencias. Se instala como hook global de git, y las reglas viven en un archivo:
~/Code/cliente/ [email protected]
~/Code/personal/ [email protected]
* [email protected]
Si intento hacer un commit con el correo equivocado, git se niega:
$ git commit -m 'arreglo un typo'
git-wrong-email: committer email is '[email protected]', which this repository does not accept.
Repository: /Users/yo/Code/personal/mi-blog
Allowed: [email protected]
Check: git config --show-origin user.email
Con esto, lo del 13 de octubre habría sido un commit rechazado en mi terminal, no un commit público.
En otro post voy a contar cómo funciona por dentro: por qué el hook que más importa es el de pre-push, qué cuesta instalar un hook global sin romper los hooks de cada repo y qué casos todavía se le escapan. Este era para explicar por qué hacía falta. Si trabajas con más de una identidad en la misma computadora, está en GitHub con licencia MIT, y se instala con Homebrew:
brew install neosergio/tap/git-wrong-email
git wrong-email install
Comentarios