Forza "git push" per sovrascrivere i file remoti


768

Voglio inviare i miei file locali e averli su un repository remoto, senza dover affrontare i conflitti di unione. Voglio solo che la mia versione locale abbia la priorità su quella remota.

Come posso farlo con Git?


106
Non git push origin --forceha funzionato per te?


Non è chiaro se si desidera sovrascrivere solo i file .git o la copia di lavoro associata. Se è il repository git, git push è la risposta. Se si desidera aggiornare la copia di lavoro remota, è necessario utilizzare un hook post-ricezione
Pierre-Olivier Vares,

@Mike che funziona per me per qualche motivo ... mi chiedo cosa fosse

Una causa probabile, la spinta forzata non funziona, è che potrebbe essere stato esplicitamente disabilitato sul repository remoto (per garantire che nulla ottenga oggetti dovuti a collaboratori idioti e / o maligni): usare config receive.denyNonFastforwardsper scoprirlo.
Frank Nocke,

Risposte:


1088

Dovresti essere in grado di forzare la revisione locale al repository remoto utilizzando

git push -f <remote> <branch>

(ad es git push -f origin master.). Uscire <remote>e <branch>forzare spingere tutti i rami locali che si sono stabiliti --set-upstream.

Basta essere avvisati, se altre persone condividono questo repository la loro cronologia delle revisioni sarà in conflitto con quella nuova. E se hanno qualche commit locale dopo il punto di cambiamento diventeranno non validi.

Aggiornamento : ho pensato di aggiungere una nota a margine. Se si stanno creando modifiche che verranno esaminate da altri, non è insolito creare una succursale con tali modifiche e riformularle periodicamente per mantenerle aggiornate con la succursale di sviluppo principale. Fai semplicemente sapere agli altri sviluppatori che ciò accadrà periodicamente, così sapranno cosa aspettarsi.

Aggiornamento 2 : a causa del numero crescente di spettatori, vorrei aggiungere alcune informazioni aggiuntive su cosa fare quando upstreamsi verifica una spinta forzata.

Supponiamo di aver clonato il tuo repository e di aver aggiunto alcuni commit in questo modo:

            D ---- E argomento
           /
A ---- B ---- C sviluppo

Ma più tardi il developmentramo viene colpito con un rebase, che mi farà ricevere un errore simile quando corro git pull:

Disimballaggio degli oggetti: 100% (3/3), fatto.
Da <repo-location>
 * sviluppo filiale -> FETCH_HEAD
Unione automatica <file>
CONFLICT (contenuto): unisci conflitto in <locations>
Unione automatica non riuscita; correggere i conflitti e quindi eseguire il commit del risultato.

Qui potrei risolvere i conflitti e commit, ma questo mi lascerebbe con una storia di commessa davvero brutta:

       C ---- D ---- E ---- F argomento
      / /
A ---- B -------------- C 'sviluppo

Potrebbe sembrare allettante da usare, git pull --forcema fai attenzione perché ti lascerà con commit incagliati:

            D ---- E argomento

A ---- B ---- C 'sviluppo

Quindi probabilmente l'opzione migliore è fare un git pull --rebase. Questo mi richiederà di risolvere eventuali conflitti come prima, ma per ogni passaggio invece di impegnarmi lo userò git rebase --continue. Alla fine la cronologia del commit avrà un aspetto molto migliore:

            Argomento D '--- E'
           /
A ---- B ---- C 'sviluppo

Aggiornamento 3: puoi anche usare l' --force-with-leaseopzione come spinta di forza "più sicura", come menzionato da Cupcake nella sua risposta :

La spinta forzata con un "lease" consente alla spinta forzata di fallire se ci sono nuovi commit sul telecomando che non ti aspettavi (tecnicamente, se non li hai ancora recuperati nel tuo ramo di monitoraggio remoto), che è utile se non vuoi sovrascrivere accidentalmente i commit di qualcun altro di cui non sapevi ancora nulla e vuoi solo sovrascrivere i tuoi:

git push <remote> <branch> --force-with-lease

Puoi scoprire maggiori dettagli su come usare --force-with-leaseleggendo uno dei seguenti:


5
Poiché questa è la risposta selezionata, commenterò qui. L'uso della forza non è un problema quando si lavora da soli. Ad esempio, il mio host cloud inizia con il suo git. Se lavoro localmente e costruisco un progetto e voglio metterlo sul mio host cloud (OpenShift), ho due progetti git separati. Il mio locale e il mio OpenShift. Ricevo il mio locale proprio come mi piace, ma ora voglio visualizzarlo in anteprima sul mio OpenShift. Quindi premi su OpenShift per la prima volta, usando -fflag. In sostanza, metti il ​​tuo git locale su OpenShift.
Wade,

128

Vuoi forzare la spinta

Quello che sostanzialmente vuoi fare è forzare il push del tuo ramo locale, al fine di sovrascrivere quello remoto.

Se desideri una spiegazione più dettagliata di ciascuno dei seguenti comandi, consulta la sezione dei miei dettagli di seguito. Fondamentalmente hai 4 diverse opzioni per forzare la spinta con Git:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Se desideri una spiegazione più dettagliata di ciascun comando, consulta la sezione delle mie lunghe risposte di seguito.

Avvertenza: la spinta forzata sovrascriverà il ramo remoto con lo stato del ramo che stai spingendo. Assicurati che questo sia ciò che vuoi veramente fare prima di usarlo, altrimenti potresti sovrascrivere i commit che vuoi effettivamente conservare.

Forza la spinta dei dettagli

Specifica del telecomando e del ramo

È possibile specificare completamente rami specifici e un telecomando. La -fbandiera è la versione breve di--force

git push <remote> <branch> --force
git push <remote> <branch> -f

Omettendo il ramo

Quando il ramo per inviare il ramo viene omesso, Git lo scoprirà in base alle impostazioni di configurazione. Nelle versioni Git successive alla 2.0, un nuovo repository avrà impostazioni predefinite per inviare il ramo attualmente estratto:

git push <remote> --force

mentre prima della 2.0, i nuovi repository avranno impostazioni predefinite per inviare più filiali locali. Le impostazioni in questione sono le impostazioni remote.<remote>.pushe push.default(vedi sotto).

Omettendo il telecomando e il ramo

Quando vengono omessi sia il telecomando sia il ramo, il comportamento di just git push --forceè determinato dalle push.defaultimpostazioni di configurazione di Git:

git push --force
  • A partire da Git 2.0, l'impostazione predefinita simple, basterà semplicemente spingere il ramo corrente nella sua controparte remota a monte. Il telecomando è determinato dall'impostazione della diramazione branch.<remote>.remotee, in caso contrario, viene impostato automaticamente il repository di origine.

  • Prima di Git versione 2.0, l'impostazione predefinita matching, in pratica, invia semplicemente tutti i rami locali ai rami con lo stesso nome sul telecomando (che per impostazione predefinita è di origine).

Puoi leggere altre push.defaultimpostazioni leggendo git help configo una versione online della Pagina del Manuale di git-config (1) .

Forza la spinta più sicura con --force-with-lease

La spinta forzata con un "lease" consente alla spinta forzata di fallire se ci sono nuovi commit sul telecomando che non ti aspettavi (tecnicamente, se non li hai ancora recuperati nel tuo ramo di monitoraggio remoto), che è utile se non vuoi sovrascrivere accidentalmente i commit di qualcun altro di cui non sapevi ancora nulla e vuoi solo sovrascrivere i tuoi:

git push <remote> <branch> --force-with-lease

Puoi scoprire maggiori dettagli su come usare --force-with-leaseleggendo uno dei seguenti:


Hai ragione, ma questo dovrebbe davvero essere usato solo in situazioni eccezionali .
Scott Berrevoets,

1
@ScottBerrevoets " Preferirei spingere quello che ho e lasciarlo sovrascrivere da remoto piuttosto che integrarlo. " Ho dato all'OP esattamente quello che mi chiedeva.

Lo so, ma l'OP potrebbe non essere consapevole delle conseguenze di ciò. Tecnicamente hai risposto alla domanda, ma penso che un avvertimento per non farlo non sia fuori posto.
Scott Berrevoets,

1
@ScottBerrevoets Sto cercando di fare in modo che un moderatore unisca la mia risposta al canonico, perché menziono la nuova --force-with-leaseopzione;)


32

Un'altra opzione (per evitare qualsiasi spinta forzata che può essere problematica per altri collaboratori) è:

  • metti i tuoi nuovi commit in una filiale dedicata
  • resetta il tuo masteronorigin/master
  • unisci il tuo ramo dedicato a master , mantenendo sempre i commit dal ramo dedicato (il che significa creare nuove revisioni in cima alle masterquali rispecchierà il tuo ramo dedicato).
    Vedi " comando git per creare un ramo come un altro " per le strategie per simulare a git merge --strategy=theirs.

In questo modo, puoi spingere il master sul telecomando senza forzare nulla.


In che modo il risultato differisce da "push -force"?
alexkovelsky,

6
@alexkovelsky Qualsiasi push forzato riscriverebbe la cronologia, costringendo gli altri utenti del repository a reimpostare il proprio repository locale in modo che corrispondesse ai commit appena spinti. Questo approccio crea solo nuovi commit e non richiede una spinta forzata.
VonC,

1
Ti suggerisco di aggiungere un'intestazione alla tua risposta: "Non vuoi forzare la spinta" :)
alexkovelsky,

@alexkovelsky Un buon punto. Ho modificato la risposta di conseguenza.
VonC,

4

git push -f è un po 'distruttivo perché reimposta qualsiasi modifica remota che era stata fatta da chiunque nel team. Un'opzione più sicura è {git push --force-with-lease}.

Ciò che {--force-with-lease} fa è rifiutare di aggiornare una filiale a meno che non sia lo stato che ci aspettiamo; cioè nessuno ha aggiornato il ramo a monte. In pratica, questo funziona verificando che il riferimento a monte sia quello che ci aspettiamo, perché i riferimenti sono hash e codificano implicitamente la catena di genitori nel loro valore. Puoi dire a {--force-with-lease} esattamente cosa controllare, ma per impostazione predefinita controllerà l'attuale riferimento remoto. Ciò significa in pratica che quando Alice aggiorna il suo ramo e lo spinge verso il repository remoto, la testa di riferimento ref del ramo verrà aggiornata. Ora, a meno che Bob non esegua un pull dal telecomando, il suo riferimento locale al telecomando non sarà aggiornato. Quando va a spingere usando {--force-with-lease}, git verificherà il riferimento locale contro il nuovo telecomando e rifiuterà di forzare la spinta. {--force-with-lease} ti consente effettivamente di forzare la spinta solo se nessun altro ha inviato modifiche al telecomando nel frattempo. È {--force} con la cintura di sicurezza inserita.



0

Semplici passi usando tartaruga

GIT dà il commit dei file locali e inserisce il repository git.

Passaggi:

1) stash cambia il nome dello stash

2) tirare

3) pop stash

4) eseguire il commit di 1 o più file e fornire la descrizione delle modifiche del commit impostare autore e data

5) spingere

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.