push --force-with-lease per impostazione predefinita


130

Ho appena saputo git push --force-with-lease. È davvero fantastico. Ma, naturalmente, non uso la forza così spesso, quindi sono preoccupato che potrei dimenticare questa caratteristica elegante la prossima volta che ne ho bisogno.

C'è un modo per configurare git in modo da git push -futilizzarlo automaticamente a --force-with-leasemeno che non lo ignori intenzionalmente con --no-force-with-lease?

(Non riesco a immaginare di voler mai usare la forza senza contratto di locazione!)

Risposte:


141

AFAIK non c'è alcuna configurazione disponibile per dire a git di usare sempre force-with-leaseinvece di force. Questo sembra essere un buon esempio per una richiesta di funzionalità; se non hai problemi a immergerti nella base di codice git, puoi implementarlo tu stesso e inviarlo per la revisione.

EDIT Così com'è, questo è ancora vero ad aprile 2019.

Fino ad allora l'unica opzione che vedo è, come spesso, di creare un oggetto aliasche serva a questo scopo.

Crea un alias

Per creare un alias si dovrebbe usare git config --global alias.<alias-name> <command>, nel nostro caso suggerirei qualcosa di simile a questo.

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

Questo creerà una voce nel tuo .gitconfigfile globale (che di solito puoi trovare nella tua home directory ). Dopo questo puoi semplicemente usare git pushfper forzare con contratto di locazione .

Sporcarsi le mani

Se si desidera implementare la funzione da soli ma non si è sicuri da dove iniziare, si dovrebbe prima dare un'occhiata alla directory della documentazione nel repository git . Qui puoi trovare le linee guida per la codifica e le informazioni su come inviare le patch .

Puoi trovare tutti questi link e altro sulla pagina ufficiale della community .


25
Una nota sul fatto che questa non è una caratteristica: l'argomento comune contro la riscrittura dei comandi standard ("push --force") è che ci si abitua a loro, si dimentica la loro origine e un giorno li si usa accidentalmente in quel modo su un nuovo sistema. Molto simile aliasing rma rm -inel vostro .bashrc; un giorno dimenticherai ed eliminerai un file importante su un server. Andare con il tuo alias non ha questo problema :)
hraban

2
Aneddoto personale / parola di cautela: ho provato a farlo alias pushfma ho sempre ricontrollato che non stavo facendo un push -f, perché sembrava simile all'alias. Alcuni membri del team lo stavano usando push -fcomunque, pensando che l'alias fosse solo una scorciatoia cosmetica. Alla fine, abbiamo invece definito la forma più sicura pushfle abbiamo smesso di preoccuparci.
Kelvin,

31

Sono preoccupato che potrei dimenticare questa caratteristica elegante la prossima volta che ne avrò bisogno.

Git 2.13 (Q2 2017) spiega perché non vi è alcuna "protezione" da dimenticare questa opzione push, perché anche se non la dimentichi a git pushlivello, potrebbe comunque essere ignorata.

Vedi commit f17d642 (19 apr 2017) di Ævar Arnfjörð Bjarmason ( avar) .
(Unito da Junio ​​C Hamano - gitster- in commit 46bdfa3 , 26 apr 2017)

push: documenta e testa --force-with-leasecon più telecomandi

Documenta e verifica i casi in cui ci sono due telecomandi che puntano allo stesso URL e un recupero in background e successivi git push --force-with-leasenon dovrebbero ostruire i riferimenti non aggiornati che non abbiamo recuperato.

Alcuni editor come Microsoft VSC hanno una funzione per il recupero automatico in background, questo ignora le protezioni offerte da --force-with-lease&--force-with-lease=<refname> , come indicato nella documentazione che viene aggiunta qui.

Quindi la documentazione pergit push ora include:

nota generale sulla sicurezza: fornire questa opzione senza un valore atteso, ovvero come --force-with-leaseo--force-with-lease=<refname> interagisce molto male con tutto ciò che viene implicitamente eseguito git fetchsul telecomando per essere spinto in background, ad esempio git fetch origin sul proprio repository in un cronjob.

La protezione che offre --force che le successive modifiche su cui non è stato basato il tuo lavoro non siano bloccate, ma questo è banalmente sconfitto se alcuni processi in background aggiornano i riferimenti in background. Non abbiamo nulla a parte le informazioni di tracciamento remoto da passare come euristiche per i ref che dovresti aver visto e che sei disposto a bloccare.

Se il tuo editor o qualche altro sistema è in esecuzione git fetchin background per te, un modo per mitigarlo è semplicemente configurare un altro telecomando:

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

Ora, quando viene eseguito git fetch originil processo in background, i riferimenti origin-pushnon verranno aggiornati e quindi comandi come:

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

Fallirà se non si esegue manualmente git fetch origin-push.
Questo metodo è ovviamente completamente sconfitto da qualcosa che viene eseguito git fetch --all, in tal caso dovresti disabilitarlo o fare qualcosa di più noioso come:

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

Vale a dire creare un basetag per le versioni del codice upstream che hai visto e che sei disposto a sovrascrivere, quindi riscrivere la cronologia e infine forzare le modifiche push masterse la versione remota è ancora disponibile base, indipendentemente da quale remotes/origin/mastersia stato aggiornato il tuo locale nella sfondo.


30

La mia soluzione era quella di creare uno script wrapper e utilizzare un alias in modo che io lo usassi sempre al posto del reale git .

Ogni volta che provo git push -f, vedo quanto segue:

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

Alcuni vantaggi di questo script sono:

  • mi allena a usarlo abitualmente --force-with-lease, quindi non mi annoio quando sbaglio
  • se, per qualche motivo, avremo davvero bisogno di forzare la spinta, git push --forcefunzionerà.

Come implementarlo:

  1. creare uno script personalizzato che passerà attraverso tutti i parametri da git, ad eccezione di -f
  2. alias quello script così lo usiamo invece di git

Queste istruzioni presuppongono Linux o Mac, che eseguono bash. Non ho provato questo con zsh o Windows, ma suppongo che funzionerà anche lì.

~/.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 queste modifiche, riavvia il tuo terminale e gitora dovrebbe ottenere il massimo quando provi a forzare la spinta.


17
Sembra conveniente. +1. Forse sostituisci "hey idiota" con "hey, anima gentile ma semplice" o qualcosa del genere;)
VonC,

5

Per le persone che usano OMYZSH puoi semplicemente usare ggfl.


3

Voglio essere ricordato che non dovrei usare -f, ma non voglio essere ingannato nel credere che ciò -fsignifichi --force-with-lease. Quindi questa è la mia opinione:

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

Aggiungi alla tua .bash_profile, .bashrco .zshrc.


1

È possibile creare una funzione bash che sostituisce gite utilizza --force-with-leaseinvece di--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, in una riga:

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

Aggiungilo al tuo ~/.bashrco ~/.zshrc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.