Architecture Decision Records - ADR260201d
2026/02/01Force push/pull senza merge resolution
Autore: Marco Orlandin, Architect
Data: 01 Febbraio 2026
Status: Implementato
Progetto: git-side (open-source, sviluppato per Solexma LLC)
Constraint principali: Semplicità d'uso, nessuno stato di conflitto possibile, mental model chiaro per l'utente
Contesto e problema
git-side supporta remote: puoi fare push e pull dei file "a lato" per condividerli tra macchine o con colleghi. La domanda è: cosa succede quando il locale e il remoto divergono?
Nel Git tradizionale, la divergenza si risolve con merge o rebase, operazioni che possono generare conflitti e richiedere intervento manuale. Per un tool che versiona appunti, scratch, config locali, questa complessità è sproporzionata.
Il rischio concreto: un utente fa git side pull, si ritrova in uno stato di conflitto su BACKLOG.md, e non sa come uscirne. Il tool che doveva semplificargli la vita gli ha appena complicato la giornata.
Requisiti non funzionali
- Nessuno stato di conflitto possibile, mai
- Operazione deterministica: il risultato è sempre prevedibile
- Mental model immediato: l'utente deve capire cosa succede senza leggere documentazione
- Nessuna perdita di dati silenziosa
Opzioni valutate
Opzione 1: Merge standard (come git pull)
- Pro: Comportamento familiare per chi usa Git.
- Contro: Genera conflitti. Richiede risoluzione manuale. Stato "conflitto in corso" su file come TODO.md è assurdo. Complessità sproporzionata per il tipo di contenuto.
Opzione 2: Rebase automatico
- Pro: Storia lineare, meno conflitti rispetto al merge.
- Contro: Può comunque generare conflitti. Comportamento meno prevedibile. Richiede comprensione di rebase da parte dell'utente.
Opzione 3: Strategia "ours/theirs" automatica
- Pro: Nessun conflitto, risoluzione automatica.
- Contro: Semantica ambigua: chi "vince" dipende dalla direzione. Rischio di perdita dati silenziosa se la strategia non è chiara.
Opzione 4: Force push (locale vince) e force pull (remoto vince)
- Pro: Deterministico. Zero conflitti. Mental model cristallino: push = il mio locale sovrascrive il remoto, pull = il remoto sovrascrive il mio locale. Nessuno stato intermedio possibile.
- Contro: Una delle due versioni viene sovrascritta. Non c'è "merge intelligente" dei contenuti.
Decisione
Scelta la strategia force: push con --force (locale vince sempre), pull con fetch + reset --hard (remoto vince sempre).
Motivazioni principali:
- Zero conflitti: nessuno stato di merge in corso, mai.
- Determinismo totale: l'utente sa esattamente cosa succede.
- Adeguato al contesto: file "a lato" (appunti, config, scratch) non hanno bisogno di merge a tre vie.
- La storia è preservata: le versioni precedenti restano nella storia git, non vengono perse.
Implementazione passo-passo
- Push:
git push --force origin main, il contenuto locale sovrascrive il remoto. - Pull:
git fetch origin mainseguito dagit reset --hard origin/main, il contenuto remoto sovrascrive il locale. - Nessun merge, fetch-only: Pull non usa
git pullma la sequenza fetch + reset, evitando qualsiasi tentativo di merge. - Branch unico: Operazioni su
mainper semplicità. Nessun supporto multi-branch nel side repo.
Conseguenze osservate
- Nessun utente si è mai trovato in stato di conflitto.
- Il mental model "push = locale vince, pull = remoto vince" è stato compreso immediatamente da tutti i tester.
- La storia git preserva le versioni precedenti, quindi nessun dato è realmente "perso", solo sovrascritto nella working copy.
- Lezioni apprese:
- La complessità del merge è giustificata per codice sorgente, non per ogni tipo di contenuto.
- "Niente conflitti, mai" è un requisito di UX, non solo tecnico.
- La semplicità radicale richiede coraggio nelle scelte di design: rinunciare al merge è stata la decisione più opinionata e più apprezzata.
Stack utilizzato
- Linguaggio: Rust (Edition 2024, MSRV 1.85)
- Git:
git push --force,git fetch+git reset --hard
Quando considerare questo approccio
Se il tuo tool sincronizza contenuti dove:
- Il merge semantico non ha senso (appunti, config, file binari)
- La semplicità d'uso è prioritaria rispetto alla granularità
- L'utente deve avere un mental model immediato
...force operations è quasi sempre la scelta giusta. Aggiungi merge solo quando il contenuto lo richiede davvero.
Hai un caso simile? Contattami. Valutiamo insieme se la semplicità radicale è la strada giusta.