Come spingo il commit modificato nel repository Git remoto?

Quando ho lavorato un po ‘con il mio codice sorgente, ho fatto il mio consueto commit e poi ho spinto su un repository remoto. Ma poi ho notato che mi sono dimenticato di organizzare le mie importazioni nel codice sorgente. Così faccio il comando emendamento per sostituire il commit precedente:

> git commit --amend 

Sfortunatamente il commit non può essere reimpostato nel repository. È rifiutato in questo modo:

 > git push origin To //my.remote.repo.com/stuff.git/ ! [rejected] master -> master (non-fast forward) error: failed to push some refs to '//my.remote.repo.com/stuff.git/' 

Cosa dovrei fare? (Posso accedere al repository remoto.)

In realtà una volta ho spinto con il repository --force e .git e sono stato sgridato da Linus BIG TIME . In generale questo creerà molti problemi per le altre persone. Una risposta semplice è “Non farlo”.

Vedo che gli altri hanno dato la ricetta per farlo comunque, quindi non li ripeterò qui. Ma ecco un consiglio per riprendersi dalla situazione dopo aver eliminato il commit modificato con –force (o + master).

  1. Trova il vecchio commit che hai modificato (chiamalo old , e chiameremo il nuovo commit che hai creato modificando new ).
  2. Crea una fusione tra old e new , registrando l’albero di new , come git checkout new && git merge -s ours old .
  3. Uniscilo al tuo maestro con git merge master
  4. Aggiorna il tuo master con il risultato con git push . HEAD:master git push . HEAD:master
  5. Spingere il risultato.

Quindi le persone che sono state sfortunate da aver basato il loro lavoro sull’impegno che hai cancellato modificando e forzando una spinta (che sei un pessimo ragazzo ) vedranno che la fusione risultante vedrà che tu preferisci il new rispetto al old . Le loro successive fusioni non vedranno i conflitti tra old e new causati dalla modifica, quindi non devono soffrire.

Stai vedendo una funzionalità di sicurezza Git. Git si rifiuta di aggiornare il ramo remoto con il tuo ramo, perché il comando head del ramo non è un diretto discendente dell’attuale head commit del ramo a cui stai spingendo.

Se così non fosse, allora due persone che spingono allo stesso repository più o meno nello stesso momento non saprebbero che c’è stato un nuovo commit in arrivo nello stesso momento e chi ha spinto per ultimo perderebbe il lavoro del precedente pusher senza uno dei due loro realizzando questo.

Se sai di essere l’unica persona che spinge e vuoi spingere un commit modificato o spingere un commit che riavvolge il ramo, puoi “forzare” Git per aggiornare il ramo remoto usando l’ -f .

 git push -f origin master 

Anche questo potrebbe non funzionare poiché Git consente ai repository remoti di rifiutare push non fastforward all’estremità usando la variabile di configurazione receive.denynonfastforwards . In tal caso, il motivo del rifiuto apparirà come segue (nota la parte “respinta da remoto”):

  ! [remote rejected] master -> master (non-fast forward) 

Per ovviare a questo, è necessario modificare la configurazione del repository remoto o come un trucco sporco è ansible eliminare e ricreare il ramo in questo modo:

 git push origin :master git push origin master 

In generale, l’ultimo parametro su git push utilizza il formato : , dove local_ref è il nome del ramo sul repository locale e remote_ref è il nome del ramo sul repository remoto. Questa coppia di comandi utilizza due stenografie. :master ha un local_ref null che significa spingere un ramo nullo sul master lato remoto, ovvero eliminare il ramo remoto. Un nome di ramo con no : significa spingere il ramo locale con il nome dato al ramo remoto con lo stesso nome. master in questa situazione è l’abbreviazione di master:master .

Quick rant: il fatto che nessuno abbia postato la risposta semplice dimostra la disperata user-ostilità mostrata dalla CLI di Git.

Ad ogni modo, il modo “ovvio” di fare questo, supponendo che tu non abbia provato a forzare la spinta, è quello di tirare prima. Questo tira la modifica che hai modificato (e quindi non ha più) in modo da averlo di nuovo.

Una volta risolti eventuali conflitti, puoi eseguire nuovamente il push.

Così:

 git pull 

Se ricevi errori in pull, forse qualcosa non va nella configurazione del tuo repository locale (ho avuto un ref sbagliato nella sezione .git / config).

E dopo

 git push 

Forse otterrai un impegno extra con l’argomento che narra di una “Trivial merge”.

Risposta breve: non spingere i commit modificati a un repo pubblico.

Risposta lunga: alcuni comandi Git, come git commit --amend e git rebase , in realtà riscrivono il grafico della cronologia. Questo va bene fintanto che non hai pubblicato le tue modifiche, ma una volta fatto, non dovresti davvero passare del tempo con la cronologia, perché se qualcuno ha già le tue modifiche, allora quando provano a tirare di nuovo, potrebbe fallire . Invece di modificare un commit, dovresti semplicemente creare un nuovo commit con le modifiche.

Tuttavia, se vuoi davvero spingere un commit modificato, puoi farlo in questo modo:

 $ git push origin +master:master 

Il segno + leader forzerà il push a verificarsi, anche se non risulta in un commit “avanti veloce”. (Un commit di avanzamento rapido si verifica quando le modifiche che si sta spingendo sono direttamente discendenti delle modifiche già nel repository pubblico.)

Ecco un modo molto semplice e pulito per commit --amend le modifiche dopo aver già effettuato un commit --amend :

 git reset --soft HEAD^ git stash git push -f origin master git stash pop git commit -a git push origin master 

Quale fa la seguente:

  • Reimposta il capo della diramazione sul commit principale.
  • Stash questo ultimo commit.
  • Spingere la spinta al telecomando. Il telecomando ora non ha l’ultimo commit.
  • Fai scoppiare la tua scorta.
  • Impegnati in modo pulito.
  • Premi sul telecomando.

Ricordati di cambiare “origine” e “maestro” se applicando questo a un ramo o remoto diverso.

L’ho risolto scartando il mio commit locale modificato e aggiungendo le nuove modifiche in cima:

 # Rewind to commit before conflicting git reset --soft HEAD~1 # Pull the remote version git pull # Add the new commit on top git add ... git commit git push 

Ho avuto lo stesso problema.

  • Modificato casualmente l’ultimo commit che era già stato spinto
  • Fatto molte modifiche a livello locale, commesso circa cinque volte
  • Ho cercato di spingere, ho avuto un errore, sono entrato nel panico, ho unito il telecomando, ho ricevuto un sacco di file non miei, spinto, fallito, ecc.

Come un principiante Git, ho pensato che fosse completo FUBAR .

Soluzione: un po ‘come suggerito da @bara + ha creato un ramo di backup locale

 # Rewind to commit just before the pushed-and-amended one. # Replace  with the needed hash. # --soft means: leave all the changes there, so nothing is lost. git reset --soft  # Create new branch, just for a backup, still having all changes in it. # The branch was feature/1234, new one - feature/1234-gone-bad git checkout -b feature/1234-gone-bad # Commit all the changes (all the mess) not to lose it & not to carry around git commit -a -m "feature/1234 backup" # Switch back to the original branch git checkout feature/1234 # Pull the from remote (named 'origin'), thus 'repairing' our main problem git pull origin/feature/1234 # Now you have a clean-and-non-diverged branch and a backup of the local changes. # Check the needed files from the backup branch git checkout feature/1234-gone-bad -- the/path/to/file.php 

Forse non è una soluzione veloce e pulita, e ho perso la mia storia (1 commit anziché 5), ma ha salvato un giorno di lavoro.

Se sai che nessuno ha tirato il tuo commit non modificato, usa l’opzione --force-with-lease di git push .

In TortoiseGit, puoi fare la stessa cosa in “Push …” opzioni “Forza: può scartare” e controllare “modifiche note”.

Force (può scartare le modifiche note) consente al repository remoto di accettare un push non fast-forward più sicuro. Ciò può causare la perdita di commit del repository remoto; usalo con cura Questo può impedire di perdere le modifiche sconosciute da altre persone sul telecomando. Controlla se il ramo del server punta allo stesso commit del ramo di localizzazione remota (modifiche note). Se sì, verrà eseguita una spinta forzata. Altrimenti sarà respinto. Poiché git non ha tag di localizzazione remota, i tag non possono essere sovrascritti utilizzando questa opzione.

Ecco un modo molto semplice e pulito per applicare le modifiche dopo aver già fatto un git add "your files" e git commit --amend :

 git push origin master -f 

o:

 git push origin master --force 

Se non hai inserito il codice nella tua diramazione remota (GitHub / Bitbucket) puoi cambiare il messaggio di commit sulla riga di comando come sotto.

  git commit --amend -m "Your new message" 

Se stai lavorando su un ramo specifico, fai questo:

 git commit --amend -m "BRANCH-NAME: new message" 

Se hai già inserito il codice con un messaggio sbagliato, devi fare attenzione quando cambi il messaggio. vale a dire dopo aver cambiato il messaggio di commit e provare a spingerlo di nuovo si finisce con avere problemi. Per renderlo fluido, segui i seguenti passaggi.

Si prega di leggere l’intera risposta prima di farlo

 git commit --amend -m "BRANCH-NAME : your new message" git push -f origin BRANCH-NAME # Not a best practice. Read below why? 

Nota importante: quando usi direttamente il force push potresti finire con problemi di codice che altri sviluppatori stanno lavorando sullo stesso ramo. Quindi per evitare questi conflitti è necessario estrarre il codice dal ramo prima di eseguire il push forzato :

  git commit --amend -m "BRANCH-NAME : your new message" git pull origin BRANCH-NAME git push -f origin BRANCH-NAME 

Questa è la procedura migliore quando si modifica il messaggio di commit, se già premuto.

Si sta verificando questo errore perché il telecomando Git ha già questi file di commit. Devi forzare a spingere il ramo affinché funzioni:

 git push -f origin branch_name 

Assicurati inoltre di estrarre il codice da remoto, poiché qualcun altro del tuo team potrebbe aver inviato allo stesso ramo.

 git pull origin branch_name 

Questo è uno dei casi in cui dobbiamo forzare l’invio del commit a remoto.

Ho dovuto risolvere questo problema tirando dal repository remoto e affrontando i conflitti di fusione che si sono presentati, commessi e poi spinti. Ma sento che c’è un modo migliore.

Ho continuato a fare quello che Git mi ha detto di fare. Così:

  • Imansible eseguire il push a causa del commit modificato.
  • Faccio un tiro come suggerito.
  • Unisci fallisce. quindi lo aggiusto manualmente.
  • Crea un nuovo commit (etichettato “unione”) e spingilo.
  • Sembra funzionare!

Nota: il commit modificato è l’ultimo.