push --force-with-lease por defecto

130

Acabo de enterarme git push --force-with-lease. Es bastante asombroso. Pero, por supuesto, no uso la fuerza con tanta frecuencia, por lo que me preocupa olvidarme de esta característica ingeniosa la próxima vez que la necesite.

¿Hay alguna forma de configurar git para git push -fque se use automáticamente a --force-with-leasemenos que lo anule intencionalmente --no-force-with-lease?

(¡No puedo imaginar querer usar la fuerza sin arrendamiento!)

Dan Fabulich
fuente

Respuestas:

141

AFAIK no hay configuración disponible para decirle a git que use siempre en force-with-leaselugar de force. Este parece ser un buen ejemplo para una solicitud de función; Si no tiene problemas para sumergirse en la base del código git, puede implementarlo usted mismo y enviarlo para su revisión.

EDITAR Tal como está, esto sigue siendo cierto en abril de 2019.

Hasta entonces, la única opción que veo es, como a menudo, crear una aliasque sirva para este propósito.

Crea un alias

Para crear un alias se usaría git config --global alias.<alias-name> <command>, en nuestro caso sugeriría algo similar a esto.

git config --global alias.pushf "push --force-with-lease"

Esto creará una entrada en su .gitconfigarchivo global (que generalmente puede encontrar en su directorio de inicio ). Después de esto, simplemente puede usar git pushfpara forzar con arrendamiento .

Ensuciarse las manos

Si desea implementar la función usted mismo, pero no está seguro de dónde comenzar, primero debe consultar el directorio de documentación en el repositorio de git . Aquí puede encontrar las pautas de codificación e información sobre cómo enviar parches .

Puede encontrar todos estos enlaces y más en la página oficial de la comunidad .

Sascha Wolf
fuente
25
Una nota sobre esto no es una característica: el argumento común contra la reescritura de comandos estándar ("push --force") es que te acostumbras a ellos, olvidas su origen y un día los usas accidentalmente de esa manera en un nuevo sistema. Al igual que el aliasing rma rm -ien su .bashrc; algún día olvidará y eliminará un archivo importante en un servidor. Ir con tu propio alias no tiene ese problema :)
hraban
2
Anécdota personal / palabra de advertencia: traté de alias pushfpero siempre comprobé que no estaba haciendo un push -f, debido a que se parecía al alias. Algunos miembros del equipo usaban de push -ftodos modos, pensando que el alias era solo una abreviatura cosmética para ello. Finalmente, aliasamos la forma más segura en su pushfllugar y dejamos de preocuparnos por eso.
Kelvin
31

Me preocupa olvidarme de esta ingeniosa característica la próxima vez que la necesite.

Git 2.13 (Q2 2017) explica por qué no existe una "protección" contra el olvido de esta opción de inserción, porque incluso si no la olvida en el git pushnivel, aún podría ignorarse.

Ver commit f17d642 (19 abr 2017) por Ævar Arnfjörð Bjarmason ( avar) .
(Fusionada por Junio ​​C Hamano - gitster- en commit 46bdfa3 , 26 abr 2017)

push: documento y prueba --force-with-leasecon múltiples controles remotos

Documente y pruebe los casos en los que hay dos controles remotos que apuntan a la misma URL, y una búsqueda en segundo plano y posterior git push --force-with-leaseno deberían detectar referencias no actualizadas que no hemos obtenido.

Algunos editores, como el VSC de Microsoft, tienen una función para buscar automáticamente en segundo plano, lo que evita las protecciones ofrecidas por --force-with-lease&--force-with-lease=<refname> , como se indica en la documentación que se agrega aquí.

Entonces la documentación porgit push ahora incluye:

nota general sobre seguridad: proporcionar esta opción sin un valor esperado, es decir, como --force-with-leaseo --force-with-lease=<refname> interactúa muy mal con cualquier cosa que implícitamente se ejecute git fetchen el control remoto para ser empujado en segundo plano, por ejemplogit fetch origin en su repositorio en un cronjob.

La protección que ofrece sobre --force es garantizar que los cambios posteriores en los que su trabajo no se basó no se vean afectados, pero esto se vence trivialmente si algún proceso en segundo plano actualiza las referencias en segundo plano. No tenemos nada más que la información de seguimiento remoto para seguir como una heurística para los árbitros que se espera que hayas visto y estés dispuesto a chasquear.

Si su editor o algún otro sistema se está ejecutando git fetchen segundo plano, una forma de mitigar esto es simplemente configurar otro control remoto:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

Ahora, cuando se ejecuta git fetch originel proceso en segundo plano, las referencias origin-pushno se actualizarán y, por lo tanto, comandos como:

git push --force-with-lease origin-push

Fallará a menos que lo ejecute manualmente git fetch origin-push.
Por supuesto, este método es completamente derrotado por algo que se ejecuta git fetch --all, en ese caso, deberá deshabilitarlo o hacer algo más tedioso como:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

Es decir, cree una baseetiqueta para las versiones del código ascendente que haya visto y esté dispuesto a sobrescribir, luego reescriba el historial y, finalmente, fuerce los cambios automáticos mastersi la versión remota todavía está en base, independientemente de a qué remotes/origin/masterse haya actualizado su local en el antecedentes.

VonC
fuente
30

Mi solución fue crear un script de envoltura y usar un alias para que siempre lo use en lugar del real git .

Cada vez que lo intento git push -f, veo lo siguiente:

⚡ git push -f
use this instead so you don't cause race conditions in the 
repo: git push --force-with-lease

Algunas ventajas de este script son:

  • me entrena para usar habitualmente --force-with-lease, así que no me molestan cuando me equivoco
  • si, por alguna razón, realmente necesitamos forzar el empuje, git push --forcefuncionará.

Cómo implementarlo:

  1. crear un script personalizado que pasará por cualquier parámetro a git, excepto -f
  2. alias ese script así que lo usamos en lugar de git

Estas instrucciones asumen Linux o Mac, ejecutando bash. No he intentado esto con zsh o Windows, pero supongo que funcionará allí también.

~/.bash_profile:

alias git=~/.git_wrapper.sh

~./git_wrapper.sh:

#!/bin/bash
for arg in "$@"; do
    if [ "$arg" = "push" ]; then
        ispush=1
    elif [ "$ispush" = 1 -a "$arg" = '-f' ]; then
        echo "use this instead so you don't cause race conflicts in the repo: git push --force-with-lease"
        exit 1
    fi
done

git "$@"

Con esos cambios, reinicie su terminal y gitahora debería ser optimista cuando intente forzar el empuje.

Jessica Knight
fuente
17
Eso parece conveniente. +1. Tal vez reemplace "oye idiota" por "oye, alma gentil pero simple" o algo así;)
VonC
5

Para las personas que usan OMYZSH, simplemente puede usar ggfl.

Nicolas
fuente
3

Quiero que me recuerden que no debo usar -f, pero no quiero que me engañen creyendo que eso -fsignifica --force-with-lease. Entonces esta es mi opinión:

git() {
  if [[ $@ == 'push -f'* ]]; then
    echo Hey stupid, use --force-with-lease instead
  else
    command git "$@"
  fi
}

Añadir a su .bash_profile, .bashrco .zshrc.

neu242
fuente
1

Puede crear una función bash que reemplace gity use en --force-with-leaselugar de--force

# replaces `git push --force` with `git push --force-with-lease`
git() {
  if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then
    command git push --force-with-lease
  else
    command git "$@"
  fi
}

o, en una línea:

git() { if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then command git push --force-with-lease; else command git "$@"; fi; }

Solo agrégalo a tu ~/.bashrco ~/.zshrc.

paulodiovani
fuente