Rollback del repository git locale e remoto di 1 commit


188

Ho letto i post simili su questo argomento e non riesco a capire come farlo correttamente.

Ho archiviato circa 1000 file che non desidero e preferirei non dover passare 1by1 e rimuoverli tutti dal repository.

  • Ho un masterBranch remoto .
  • Ho la masterfiliale locale .

Sono entrambi alla stessa revisione.

Voglio ripristinare il mio telecomando di 1 commit.

Di 'che la mia storia masterè A--B--C--D--E.
Voglio ripristinare il mio locale a D.
Quindi spingilo sul telecomando in modo che il mio hash corrente sia D sia remoto che locale.

Sto avendo problemi a farlo.
Sto usando Git Tower ma mi sento a mio agio con la riga di comando. Qualsiasi aiuto?

AGGIORNAMENTO: grandi commenti di seguito. L'uso di un ripristino sembra essere parzialmente scoraggiato, specialmente se il repository è condiviso con altri utenti. Qual è il modo migliore per annullare le modifiche del commit precedente senza utilizzare un hard reset ? C'è un modo?


Ho aggiornato la mia risposta a "annullare le modifiche del commit precedente senza utilizzare un hard reset".
VonC,

3
Utilizzare git revertper fare senza hard reset e senza disturbare gli utenti.
user562374


Il rollback del telecomando è ciò che è scoraggiato, ma se è quello che vuoi fare, fallo. Ci sono centinaia di modi per farlo, ma il risultato sarebbe lo stesso sul lato server.
FelipeC

Risposte:


307

Se nessuno ha ancora estratto il tuo repository remoto, puoi cambiare il tuo HEAD di filiale e forzarlo a spingerlo in detto repository remoto:

git reset --hard HEAD^ 
git push -f 

(oppure, se si ha accesso diretto al repository remoto, è possibile modificare il riferimento HEAD anche se si tratta di un repository nudo )

Nota, come commentato dalla tecnologia aliena nei commenti qui sotto , su Windows (sessione CMD), avresti bisogno di ^^:

git reset --hard HEAD^^
git push -f 

Aggiornamento dal 2011: l'
utilizzo git push --force-with-lease( che presento qui , introdotto nel 2013 con Git 1.8.5) è più sicuro.

Vedi la risposta di Schwern per l'illustrazione.


E se qualcuno ha già ritirato il repository? Cosa farei allora?

Quindi suggerirei qualcosa che non riscriva la storia:

  • git revert localmente il tuo ultimo commit (creando un nuovo commit che inverte ciò che ha fatto il commit precedente)
  • spingere il "ripristino" generato da git revert.

1
E se qualcuno ha già ritirato il repository? Cosa farei allora?
Jamis Charles,

1
@gwho crea un ramo? No, sposta la TESTA di un ramo, ma sei ancora nello stesso ramo. Tuttavia, poiché la spinta non è più un avanzamento rapido, sì, è necessario forzare quella spinta.
VonC

1
c'è un modo per sapere se qualcuno ha ritirato il repository?
Pinkerton,

4
In Windows, il carattere ^ viene utilizzato per la continuazione della linea e per sfuggire a un carattere, eseguendo il comando: git reset --hard HEAD ^^
Alien Technology

1
@AlienTechnology Utilizzando Powershell, su Windows 10, ho dovuto solo digitare reset --hard HEAD^e non reset --hard HEAD^^ripristinare l'ultimo commit.
Gaspacchio,

58

Imposta il ramo locale una revisione indietro ( HEAD^significa una revisione indietro):

git reset --hard HEAD^

Invia le modifiche all'origine:

git push --force

Dovrai forzare la spinta perché altrimenti Git riconoscerebbe che sei dietro origindi un commit e nulla cambierà.

Farlo con --forcedice a git di sovrascrivere HEADnel repository remoto senza rispettare i progressi lì.


1
Suggerirei di non definire questo un ripristino, poiché si tratta di un termine specifico con un significato molto diverso in git.
Cascabel,

@Jefromi: grazie per il suggerimento. Modificato.
Verifica il

Bella risposta. Ho letto che l'utilizzo di un ripristino sembra essere parzialmente scoraggiato, specialmente se il repository è condiviso con altri utenti. C'è un modo più pulito per farlo, che annulla tutte le modifiche del commit precedente?
Jamis Charles,

Stai attento! Metti da parte le modifiche senza impegno o le hai perse
Nosov Pavel,

Questo è figo. Quindi, ciò significa che quando lo facciamo git push origin master, Git è in grado di creare un nuovo commit sul telecomando perché il ramo locale è in anticipo di almeno una volta il commit? Inoltre, quest'ultimo deve essere sostanzialmente diverso da quello a cui punta la testa nel repository remoto?
MadPhysicist,

18

Se vuoi ripristinare l'ultimo commit ascolta:

Passo 1:

Controlla i tuoi impegni locali con i messaggi

$ git log

Passo 2:

Rimuovi l'ultimo commit senza ripristinare le modifiche dalla filiale locale (o dal master)

$ git reset HEAD^

OPPURE se non si desidera ascoltare gli ultimi file di commit e gli aggiornamenti

$ git reset HEAD^ --hard

Passaggio 3:

Siamo in grado di aggiornare i file e i codici e di nuovo è necessario spingere con forza eliminerà il commit precedente. Manterrà il nuovo commit.

$ git push origin branch -f

Questo è tutto!


Non sta ripristinando un commit, sta sostituendo uno. Per favore, non confonderci con i principianti git usando in modo improprio termini convenzionali.
Suncat2000,

7

Immettendo il seguente comando è possibile visualizzare la cronologia del commit git:

$ git log

Supponiamo che la tua cronologia su quel particolare ramo sia simile a: commit_A, commit_B, commit_C, commit_D. Dove, commit_D è l'ultimo commit ed è qui che rimane HEAD. Ora, per rimuovere l'ultimo commit da locale e remoto, è necessario effettuare le seguenti operazioni:

Passaggio 1: rimuovere l'ultimo commit localmente da -

$ git reset --hard HEAD ~

Questo cambierà il tuo commit HEAD in commit_C

Passaggio 2: invia la modifica per il nuovo commit HEAD sul telecomando

$ git push origin + HEAD

Questo comando eliminerà l'ultimo commit dal remoto.

PS questo comando è testato su Mac OSX e dovrebbe funzionare anche su altri sistemi operativi (non pretendendo su altri sistemi operativi)



3

Ecco una versione aggiornata della procedura che è più sicura.

git reset --hard HEAD^ 
git push --force-with-lease

git push -fsostituirà indiscriminatamente il repository remoto con le tue modifiche. Se qualcun altro ha spinto i cambiamenti, questi andranno persi. git push --force-with-leasespingerà il tuo rebase solo se il repository è come previsto. Se qualcun altro ha già premuto la tua spinta fallirà.

Vedi - forza considerata dannosa; comprendere la forza di Git con contratto di locazione .

Raccomando questo alias come repush = push --force-with-lease.

E se qualcuno ha già ritirato il repository? Cosa farei allora?

Diglielo git pull --rebase=merges. Invece di a git fetch origine git merge origin/masterlo farà git fetch origine git rebase -r origin/master. Questo riscriverà qualsiasi delle loro modifiche locali masterin cima al nuovo rinnovato origin/master. -rconserverà eventuali fusioni che potrebbero aver effettuato.

Consiglio di rendere questo il comportamento predefinito per il pull. È sicuro, gestirà il rebasing degli altri e si tradurrà in fusioni meno inutili.

[pull]
        rebase = merges

1
Concordato e votato. Per mia difesa, la mia vecchia risposta del 2011 è stata scritta due anni prima dell'introduzione --force-with-leasedell'opzione.
VonC

Ho pensato che ho fatto che già (ieri): stackoverflow.com/posts/4647362/revisions
VonC

1

Ho risolto un problema come il tuo con questi comandi:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 


0

Volevo solo rimuovere l'ultimo commit dalla cronologia di commit remota e chiara. Il seguente ha funzionato come un fascino

git reset --hard HEAD^ 
git push -f 

Ma come "quanto segue" è diverso dalla mia risposta sopra ?
VonC,

0

Il modo per ripristinare la testa e ripristinare il precedente commit è attraverso

$ git reset HEAD^ --hard
$ git push <branchname> -f

Ma a volte potrebbe non essere accettato nel ramo remoto:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

quindi l'altro modo di fare è

git revert HEAD
git push <remote branch>

Funziona benissimo.

NOTA: ricorda se il git push -f <force>problema è fallito e quindi provi a ripristinare. Fai un git pullprima, in modo che remoto e locale siano sincronizzati e poi prova git revert.
Verificare con git logche il telecomando e il locale siano nello stesso punto di commit con lo stesso SHA1.

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

sul maestro locale

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

Non c'è bisogno di preoccuparsi se gli altri hanno tirato o no.

Fatto!


0

Se si desidera rimuovere solo l'ultimo commit dal repository remoto senza fare confusione con il repository locale, ecco una riga:

git push origin +origin/master~:master

Questo utilizza la sintassi seguente:

git push <remote> <refspec>

Ecco, <remote>è origine <refspec>ha la seguente struttura:

+origin/master~:master

I dettagli sono disponibili in git-push(1). Il precedente +significa "force push this ref", e l'altra parte significa "da origin/master~a master(di remoto origin)". Non è difficile sapere che origin/master~è l'ultimo commit prima origin/master, giusto?


0

per me funziona questi due comandi:

git checkout commit_id
git push origin +name_of_branch

0

Puoi anche fare questo:

git reset --hard <commit-hash>
git push -f origin master

e reimpostare tutti gli altri che hanno ricevuto l'ultimo commit errato:

git reset --hard origin/master
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.