Come posso forzare git pull per sovrascrivere tutto su ogni pull?


203

Ho un repository nudo CENTRALE che ha tre repository di sviluppatori che eseguono il pull e il push normalmente.

Ho anche altri due repository che estraggono dal repository nudo CENTRALE: uno è il server live e l'altro è un server test / stage, ognuno dei quali estrae dal rispettivo ramo.

Lo scenario è questo: ho uno post-updatescript hook sul repository CENTRAL che accede automaticamente al test e repository live ed esegue un comando pull su ciascuno. Questo aggiorna sia i server di prova che quelli attivi, tutto a seconda di quale ramo ha nuovi commit. Tutto funziona alla grande.

Il problema è questo: ci possono essere momenti in un'emergenza in cui i file possono essere aggiornati direttamente sul server (tramite ftp o altro) e lo script post-aggiornamento CENTRALE fallirà poiché si verificheranno conflitti di unione / sovrascrittura. Non c'è modo di evitare questo scenario ed è inevitabile.

Quello che vorrei che accadesse è questo: voglio che il pull dai siti live e di test sovrascriva / si unisca sempre al pull. Sempre. Questi repository saranno disponibili solo in quanto non sono destinati allo sviluppo.

In tutte le mie ricerche, non riesco a trovare una buona soluzione per avere un pull forzare sempre una sovrascrittura dei file locali. Questo è possibile? In tal caso sarebbe un grande scenario di sviluppo.


1
Mentre ho votato per la risposta "ripristina ciò che hai appena recuperato" di seguito, penso che la soluzione al tuo vero problema sia di non apportare modifiche fuori banda. Le modifiche, per quanto urgenti, dovrebbero sempre passare attraverso il controllo della versione. Nessuno, tranne gli operatori, dovrebbe avere accesso diretto ai siti in esecuzione (ad esempio, non sviluppatori). L'uso costante del controllo delle versioni significa che hai una registrazione di quando sono state apportate le modifiche e chi li ha fatti e strumenti migliori per lavorare con loro. Perché sovvertirlo, senza alcun beneficio reale?
Phil Miller,

1
@Novelocrat, ho capito cosa stai dicendo. Sfortunatamente, ci sono una serie di scenari in cui qualcuno potrebbe caricare un file direttamente sul server. In tal caso avrei bisogno di eseguire una serie di comandi per risincronizzare i repository. In precedenza abbiamo utilizzato uno script FTP per spostare i file dal repository al server. Il metodo proposto sopra eliminerebbe semplicemente il passaggio FTP, che ha funzionato molto bene in passato.
bmilesp

3
Quindi, non permettere alle persone di accedere direttamente al server. Blocca l'accesso FTP e SSH o dì loro che verranno licenziati per aver apportato modifiche non responsabili. Lasciare che quel tipo di pratica continui fa male solo a te e alla tua squadra nel lungo periodo.
Phil Miller,

Risposte:


510

Davvero il modo ideale per farlo è non usare pullaffatto, ma invece fetche reset:

git fetch origin master
git reset --hard FETCH_HEAD
git clean -df

(Modificando masterqualsiasi ramo tu voglia seguire.)

pullè progettato per unire le modifiche in qualche modo, mentre resetè progettato semplicemente per far corrispondere la tua copia locale a un commit specifico.

Potresti prendere in considerazione opzioni leggermente diverse a cleanseconda delle esigenze del tuo sistema.


3
@ user730569 reset --hardè un comando utilizzato per forzare lo stato della directory di lavoro (e il ramo corrente) su uno stato corrispondente a quello di un particolare commit.
Ambra

25
FETCH_HEADè un riferimento che viene creato automaticamente da fetchper rappresentare il riferimento recuperato. Non è unito, semplicemente sovrascritto ogni volta che esegui un recupero. cleanè un comando che rimuove i file che non sono tracciati da git, i -dfflag gli dicono di rimuovere le directory ( -d) e di fare effettivamente la rimozione ( -f).
Ambra

4
perché non esiste una parola chiave per questo? Ne ho bisogno molto più spesso di tirare.
Wolfgang Fahl,

14
Potresti voler usare git clean -dnprima dell'uso in git clean -dfmodo da vedere quali file / cartelle verranno eliminati. git clean -dfpuò essere annullato solo se si dispone di un backup
Ibrahim Lawal,

1
@NickMiddleweek Ero preoccupato di git clean -dfrimuovere anche i file gitignored, ma si scopre che non lo farà. git clean --helpdice "Normalmente, vengono rimossi solo i file sconosciuti a Git, ma se viene specificata l'opzione -x, vengono rimossi anche i file ignorati. Questo, ad esempio, può essere utile per rimuovere tutti i prodotti di compilazione."
Nick


6

Non sono sicuro di come farlo in un solo comando ma potresti fare qualcosa del tipo:

git reset --hard
git pull

o anche

git stash
git pull

Per eseguire in un unico comando: git reset --hard && git pull. In alternativa, ma non migliore, git reset --hard; git pull. L'uso &&eseguirà il secondo comando solo se il primo comando ha avuto esito positivo. ;lo eseguirà indipendentemente dal codice di uscita del primo comando.
Mazunki,

5

Per estrarre una copia del ramo e forzare la sovrascrittura dei file locali dall'origine utilizzare:

git reset --hard origin/current_branch

Tutto il lavoro corrente andrà perso e sarà quindi lo stesso del ramo di origine


5
git reset --hard HEAD
git fetch --all
git reset --hard origin/your_branch

2

Puoi cambiare il gancio per pulire tutto.

# Danger! Wipes local data!

# Remove all local changes to tracked files
git reset --hard HEAD

# Remove all untracked files and directories
git clean -dfx

git pull ...

2
cosa fa x? per favore, spiega gli interruttori
Steve K

2
Penso che la x rimuova tutti i file non tracciati. Difficile dirlo in manpage-speak, motivo per cui abbiamo SO.
JosephK,

2
@JosephK: non è corretto. Lo scopo di base git cleanè già "Rimuovi i file non tracciati dall'albero di lavoro" (parte superiore della pagina). Normalmente, questo non include i file ignorati, ma -xdice git cleandi includere anche i file ignorati (tranne per il fatto che ciò non influisce sui file ignorati -edall'opzione).
Dietrich Epp,

2

Se non hai ancora eseguito il commit delle modifiche locali dall'ultimo pull / clone, puoi utilizzare:

git checkout *
git pull

checkoutcancellerà le modifiche locali con l'ultimo commit locale e pullle sincronizzerà nel repository remoto

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.