Come annullare un "git cherry-pick" di successo?


99

Su un repository locale, ho appena eseguito git cherry-pick SHAsenza conflitti o problemi. Poi ho capito che non volevo fare quello che avevo appena fatto. Non l'ho spinto da nessuna parte.

Come posso rimuovere solo questo cherry pick?

Mi piacerebbe sapere se c'è un modo per farlo:

  • quando ho altre modifiche locali
  • quando non ho altre modifiche locali

Preferibilmente con un comando per entrambi i casi, se possibile.

Risposte:


134

Un cherry-pick è fondamentalmente un commit, quindi se vuoi annullarlo, annulla semplicemente il commit.

quando ho altre modifiche locali

Conserva le modifiche correnti in modo da poterle riapplicare dopo aver ripristinato il commit.

$ git stash
$ git reset --hard HEAD^
$ git stash pop  # or `git stash apply`, if you want to keep the changeset in the stash

quando non ho altre modifiche locali

$ git reset --hard HEAD^

6
Oltre alla domanda e alla risposta, se non sei sicuro di cosa stai scegliendo, puoi sempre `` scegliere SHA - no-commit '' e non ci saranno modifiche solo commit che possono essere facilmente verificate , questo è utile per la selezione parziale delle ciliegie
kuskmen

2
windows: git reset --hard "HEAD ^"
slim

22

Per annullare il tuo ultimo commit, fallo semplicemente git reset --hard HEAD~.

Modifica : questa risposta si applicava a una versione precedente della domanda che non menzionava la conservazione delle modifiche locali; la risposta accettata da Tim è davvero quella corretta. Grazie a qwertzguy per l'avvertenza.


2
Dovrebbe essere TESTA ^ o TESTA ~ 1
Andreas Wederbrand

Sono entrambi equivalenti a HEAD ~ (e HEAD ^ 1, del resto)
David Deutsch

1
@DavidDeutsch È vero (anche se solo nelle versioni più recenti di Git), ma le maiuscole ( HEAD) sono più robuste: si consideri lo sfortunato caso in cui si headtrova il nome di un riferimento esistente.
jub0bs

1
@Jubobs - buon punto; Ho cambiato l'involucro nella mia risposta.
David Deutsch

1
@qwertzguy, buona cattura; guardando i timestamp, il bit sui cambiamenti locali è stato aggiunto alla domanda un minuto dopo aver pubblicato questa risposta :)
David Deutsch

8

Se possibile, evitare hard reset. Gli hard reset sono una delle pochissime operazioni distruttive in git. Fortunatamente, puoi annullare una scelta rapida senza reimpostazioni ed evitare qualsiasi cosa distruttiva.

Nota l'hash della selezione che vuoi annullare, diciamo che lo è ${bad_cherrypick}. Fai un git revert ${bad_cherrypick}. Ora il contenuto del tuo albero di lavoro è come prima della tua scelta sbagliata.

Ripeti il ​​tuo git cherry-pick ${wanted_commit}e quando sei soddisfatto del nuovo cherry-pick, fai un git rebase -i ${bad_cherrypick}~1. Durante il rebase, elimina entrambi ${bad_cherrypick}e il corrispondente ripristino.

Il ramo su cui stai lavorando avrà solo la scelta migliore. Nessun ripristino necessario!


6

git reflog può venire in tuo soccorso.

Inseriscilo nella tua console e otterrai un elenco della tua cronologia git insieme a SHA-1 che li rappresenta.

Esegui semplicemente il checkout di qualsiasi SHA-1 che desideri ripristinare


Prima di rispondere aggiungiamo alcune informazioni di base, spiegando di cosa si tratta HEAD.

First of all what is HEAD?

HEADè semplicemente un riferimento al commit corrente (il più recente) sul ramo corrente.
Ci può essere solo un singolo HEADin un dato momento. (escluso git worktree)

Il contenuto di HEADè memorizzato all'interno .git/HEADe contiene i 40 byte SHA-1 del commit corrente.


detached HEAD

Se non sei sul commit più recente, il che significa che HEADpunta a un commit precedente nella cronologia, viene chiamato detached HEAD.

inserisci qui la descrizione dell'immagine

Sulla riga di comando, sarà simile a questo: SHA-1 invece del nome del ramo poiché HEADnon punta alla punta del ramo corrente

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Alcune opzioni su come recuperare da una HEAD staccata:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Questo controllerà il nuovo ramo che punta al commit desiderato.
Questo comando eseguirà il checkout di un determinato commit.
A questo punto, puoi creare un ramo e iniziare a lavorare da questo punto in poi.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Puoi sempre usare refloganche il file.
git reflogmostrerà tutte le modifiche che hanno aggiornato il HEADe il check out della voce reflog desiderata riporterà HEADindietro a questo commit.

Ogni volta che la TESTA viene modificata ci sarà una nuova voce nel file reflog

git reflog
git checkout HEAD@{...}

Questo ti riporterà al commit desiderato

inserisci qui la descrizione dell'immagine


git reset --hard <commit_id>

"Sposta" di nuovo la TESTA sul commit desiderato.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.

git revert <sha-1>

"Annulla" il commit specificato o l'intervallo di commit.
Il comando reset "annullerà" tutte le modifiche apportate al commit dato.
Verrà eseguito il commit di un nuovo commit con la patch di annullamento mentre anche il commit originale rimarrà nella cronologia.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Questo schema illustra quale comando fa cosa.
Come puoi vedere, reset && checkoutmodifica il file HEAD.

inserisci qui la descrizione dell'immagine


forse aggiungeregit reset --hard
wyx

3

Di fronte allo stesso problema, ho scoperto che se hai eseguito il commit e / o il push in remoto dopo il tuo cherry-pick di successo e vuoi rimuoverlo, puoi trovare SHA del cherry-pick eseguendo:

git log --graph --decorate --oneline

Quindi, (dopo aver usato :wqper uscire dal registro) puoi rimuovere il cherry-pick usando

git rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE

dove è YOUR_SHA_HEREuguale a SHA di 40 o 7 caratteri abbreviato del commit selezionato.

All'inizio, non sarai in grado di inviare le modifiche perché il tuo repository remoto e il tuo repository locale avranno cronologie di commit diverse. Puoi forzare i tuoi commit locali a sostituire ciò che è sul tuo telecomando usando

git push --force origin YOUR_REPO_NAME

(Ho adattato questa soluzione di Seth Robertson : vedi "Rimozione di un intero commit".)


1

Un comando e non utilizza il git resetcomando distruttivo :

GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash

Elimina semplicemente il commit, riportandoti esattamente nello stato precedente alla selezione, anche se hai avuto modifiche locali.


Elimina semplicemente il commit. cosa pensi git reset HEAD^faccia?
Tim

@TimCastelijns git resetannulla l'azione di commit senza annullare nessuna delle modifiche. Ti consiglio di leggere git-scm.com/docs/git-reset . La domanda di OP è annullare una scelta di ciliegie. Prova entrambi i comandi, il mio ti riporterà nello stato esatto in cui eri prima della scelta. git resetrovinerà il tuo albero di lavoro quando lascerà le modifiche selezionate e diventeranno indistinguibili dai tuoi cambiamenti locali preesistenti.
qwertzguy

si, scusa, volevo dire reset --hard. Non lascia modifiche
Tim

1
@TimCastelijns git reset --hardè un comando distruttivo che rimuoverà anche le modifiche locali non correlate e lo farà in modo irrecuperabile! Quindi non è quello che chiedeva l'OP.
qwertzguy

2
Questa risposta sarebbe molto più utile se spiegassi cosa sedsta facendo quel comando, in cosa differisce dal farlo manualmente e cosa --autostashfa.
Chris Page
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.