modulo 05 / lezione 24

Collaborazione con remoti

Force push in sicurezza: --force-with-lease

Quando serve riscrivere storia condivisa, farlo senza distruggere il lavoro di colleghi.

60 minGit e controllo versione

Force push in sicurezza: –force-with-lease

Force push significa chiedere al remoto di accettare la tua storia anche se non è un avanzamento lineare di quella già presente. È necessario dopo rebase o amend di commit già pushati, ma può sovrascrivere lavoro altrui.

--force-with-lease è la variante che controlla che il remoto sia ancora nello stato che tu conosci.

Perché questa lezione conta

Un git push --force lanciato sul branch sbagliato può cancellare commit remoti dal punto di vista dei branch. I commit possono essere recuperabili, ma il danno al team è reale: PR confuse, build rotte, colleghi costretti a riparare cloni.

Non serve demonizzare force push. Serve usarlo solo quando il workflow lo prevede.

Obiettivo operativo

Alla fine della lezione devi saper spiegare la differenza tra --force e --force-with-lease, sapere quando è legittimo usarlo e quali controlli fare prima.

Perché serve

Scenario:

git switch feat/login
git rebase origin/main
git push

Il push fallisce perché hai riscritto i commit locali. Il remoto ha ancora i vecchi hash.

Se il branch è tuo e nessun altro ha pushato sopra:

git push --force-with-lease

--force vs --force-with-lease

--force dice: sovrascrivi comunque.

--force-with-lease dice: sovrascrivi solo se il branch remoto punta ancora al commit che io credo sia l’ultimo visto.

Se un collega ha pushato nel frattempo, --force-with-lease rifiuta. È una cintura di sicurezza.

Controlli prima

git status -sb
git fetch origin
git log --oneline --decorate --graph --all -20
git log @{u}..HEAD --oneline
git log HEAD..@{u} --oneline

Se HEAD..@{u} mostra commit remoti che non hai, fermati. Potresti sovrascrivere lavoro altrui.

Quando è legittimo

Accettabile:

  1. branch personale;
  2. PR dove il team accetta rebase/squash durante review;
  3. fix di storia prima del merge;
  4. branch temporaneo non usato da altri.

Non accettabile:

  1. main;
  2. branch di release condivisi;
  3. branch su cui lavorano più persone senza accordo;
  4. quando non hai fatto fetch;
  5. per “risolvere” un push rifiutato senza capire.

Protezioni remote

Imposta sulla piattaforma:

  1. disabilita force push su main;
  2. richiedi PR;
  3. richiedi status check;
  4. limita chi può pushare su release branch;
  5. usa branch protection rules.

La sicurezza non deve dipendere solo dalla disciplina individuale.

Comunicazione dopo la riscrittura

Se fai force push su una PR già aperta, lascia un commento breve:

Ho rebased il branch su main e fatto push con --force-with-lease.
Diff da riguardare: commit finali abc123..def456.

Il problema non è solo tecnico. Una riscrittura cambia gli hash e può rendere vecchi alcuni commenti di review. Avvisare riduce il lavoro mentale di chi deve continuare a controllare la PR.

Laboratorio guidato

In un repo sandbox:

  1. crea branch e push con upstream;
  2. fai rebase locale;
  3. osserva push rifiutato;
  4. usa --force-with-lease;
  5. simula un secondo clone che pusha un commit;
  6. prova --force-with-lease dal primo clone e osserva il rifiuto.

Non farlo su repo reali condivisi.

Output atteso

Una policy:

Mai force push su main/release.
Sui branch personali: solo --force-with-lease.
Prima: fetch e controllo log.
Dopo: avvisare se la PR era in review.

Errori comuni

Usare alias per force push. Rende troppo facile un’azione rischiosa.

Saltare fetch. Lease si basa sulla tua conoscenza del remoto.

Force push su branch condiviso. Anche se recuperabile, rompe il flusso degli altri.

Confondere push rifiutato con problema da forzare. A volte devi pullare o integrare.

Checklist di verifica

  • so perché il push viene rifiutato dopo rebase;
  • uso --force-with-lease, non --force;
  • faccio fetch prima;
  • controllo commit remoti non presenti localmente;
  • branch protetti bloccano force push dove serve.

Esercizi

Base · facile

Dopo aver riscritto la storia di un tuo branch (es. rebase), pubblica i cambiamenti in sicurezza.

Soluzione
git push --force-with-lease

Quando riscrivi commit già pushati (rebase, amend), un push normale viene rifiutato. --force-with-lease forza l’aggiornamento solo se nessun altro ha pushato nel frattempo.

Intermedio · medio

Spiega la differenza tra --force e --force-with-lease e perché il secondo è quasi sempre preferibile.

Soluzione
--force            sovrascrive il branch remoto SEMPRE, anche se contiene
                   commit altrui che non hai → rischio di cancellare lavoro
--force-with-lease sovrascrive SOLO se il remoto è ancora dov'eri rimasto;
                   se qualcuno ha pushato, fallisce e ti avvisa

--force è cieco: butta giù tutto ciò che c’è sul remoto. --force-with-lease controlla prima che la tua “fotografia” del remoto sia ancora valida: se nel frattempo è arrivato altro, si ferma invece di distruggerlo. È la rete di sicurezza che evita di sovrascrivere il lavoro dei colleghi.

Sfida · difficile

Descrivi uno scenario in cui anche --force-with-lease può sorprenderti, e le regole d’oro per il force push in team.

Soluzione
Trappola: un 'git fetch' automatico (IDE, hook) aggiorna origin/feature
          → il 'lease' ora corrisponde di nuovo e --force-with-lease passa,
            pur essendo arrivato lavoro altrui che non hai integrato.

Regole d'oro:
- mai force push su branch condivisi stabili (main, develop)
- force push solo su branch tuoi / di feature personali
- concorda col team prima di riscrivere un branch condiviso
- preferisci --force-with-lease a --force, sempre

--force-with-lease confronta con la tua copia locale di origin/feature: se qualcosa la aggiorna a tua insaputa (un fetch automatico), il controllo perde efficacia. Per questo la sicurezza vera è procedurale: riscrivere storia solo su branch propri e coordinarsi sui branch condivisi.

Collegamenti

  • Modulo: Collaborazione con remoti — lezione 24 del corso.
  • Si collega a rebase e rebase interattivo del modulo 4.