Come posso eliminare i commit git non compressi?


948

Mi sono impegnato accidentalmente nel ramo sbagliato. Come posso eliminare quel commit?

Risposte:


1811

Elimina il commit più recente, mantenendo il lavoro svolto:

git reset --soft HEAD~1

Elimina il commit più recente, distruggendo il lavoro svolto:

git reset --hard HEAD~1

13
assicurati che HEAD indichi il ramo .. (controlla prima)
Frank Schwieterman,

128
E assicurati che HEAD ~ 1 sia il commit ... Potresti anche faregit reset --hard origin
Daenyth

13
Dice le git remoteorigini delle liste di pensieri . Perché? git reset --hard originfatal: ambiguous argument 'origin': unknown revision or path not in the working tree.
trss,

7
Questo è bellissimo. Mi ha appena salvato la vita.
NinjaBoy,

2
git reset HEAD~1manterrà anche tutte le modifiche ma ti lascerà con un indice vuoto anziché mantenere tutto (come --softfarebbe l' opzione).
Holloway,

139

Mi chiedo perché la migliore risposta che ho trovato sia solo nei commenti! ( di Daenyth con 86 voti positivi )

git reset --hard origin

Questo comando sincronizzerà il repository locale con il repository remoto eliminando tutte le modifiche apportate sul locale. Puoi anche fare quanto segue per recuperare il ramo esatto che hai nell'origine.

git reset --hard origin/<branch>

16
Grazie per questo, espandendo leggermente la spiegazione: per un ramo specifico:git reset --hard origin/<branch>
chiaramente il

4
Oppure git reset --soft origin/<branch>, se si desidera eliminare il commit ma mantenere il lavoro locale.
cavallo di fiume

1
Capisco fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., è necessario specificare il ramo come:git reset --hard origin/feature/my-cool-stuff
Kip

Brillante! Questo in realtà funziona, a differenza della risposta "accettata" che stacca la testa e ti lascia sospeso.
Mae

55

Non eliminarlo: per un solo commit git cherry-pickè sufficiente.

Ma se hai avuto diversi commit sul ramo sbagliato, è qui che git rebase --ontobrilla:

Supponi di avere questo:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, quindi puoi contrassegnarlo mastere spostarlo dove vorresti essere:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, reimposta il ramo y dove avrebbe dovuto essere:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

e infine sposta i tuoi commit (riapplicali, effettuando effettivamente nuovi commit)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch

sfortunatamente, non era questa la domanda.
Kataria,

1
@KatariaA Questa è una valida alternativa all'eliminazione del commit fatto sul ramo sbagliato e aiuterà gli altri nella stessa situazione (buon commit fatto sul ramo sbagliato).
VonC del

14

Esegui git rebase -i FAR_ENOUGH_BACKe rilascia la riga per il commit che non desideri.


6

Se si desidera spostare quel commit in un altro ramo, ottenere lo SHA del commit in questione

git rev-parse HEAD

Quindi cambiare il ramo corrente

git checkout other-branch

E cherry-pickl'impegno aother-branch

git cherry-pick <sha-of-the-commit>

Dalla mia esperienza, ciò non annulla il commit dal ramo originale, rendendo quindi necessario il git reset --hard HEAD~1successivo. Penso che l'utilizzo di un reset --softcambio di succursale e un nuovo impegno avrebbero risparmiato lavoro extra. Poi di nuovo stavo usando SourceTree per fare la maggior parte delle mie cose di base, solo con la riga di comando dopo questo errore.
jusopi,

3

Per tuo riferimento, credo che tu possa "tagliare" il commit dal tuo ramo attuale non solo con git reset --hard, ma anche con il seguente comando:

git checkout -B <branch-name> <SHA>

Infatti, se non ti interessa fare il check-out, puoi impostare il ramo su quello che vuoi con:

git branch -f <branch-name> <SHA>

Questo sarebbe un modo programmatico per rimuovere i commit da un ramo, per esempio, al fine di copiare nuovi commit su di esso (usando rebase).

Supponiamo di avere un ramo disconnesso dal master perché hai preso le fonti da un'altra posizione e l'hai scaricato nel ramo.

Ora hai un ramo in cui hai applicato le modifiche, chiamiamolo "argomento".

Ora creerai un duplicato del tuo ramo argomento e poi lo riposizionerai sul dump del codice sorgente che si trova nel ramo "dump":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Ora le tue modifiche vengono riapplicate nel ramo topic_duplicate in base al punto iniziale di "dump", ma solo i commit che sono avvenuti dopo "master". Quindi le tue modifiche dal master ora vengono riapplicate in cima a "dump" ma il risultato finisce in "topic_duplicate".

È quindi possibile sostituire "dump" con "topic_duplicate" eseguendo:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

O con

git branch -M topic_duplicate dump

O semplicemente scartando la discarica

git branch -D dump

Forse potresti anche scegliere solo dopo aver cancellato l'attuale "topic_duplicate".

Quello che sto cercando di dire è che se si desidera aggiornare l'attuale ramo "duplicato" basato su un antenato diverso, è necessario prima eliminare i commit precedentemente "cherrypicked" eseguendo un git reset --hard <last-commit-to-retain>o git branch -f topic_duplicate <last-commit-to-retain>e quindi copiando gli altri commit (dal principale argomento) mediante rebasing o cherry-picking.

Il rifacimento funziona solo su un ramo che ha già i commit, quindi è necessario duplicare il ramo dell'argomento ogni volta che lo si desidera.

La crittografia è molto più semplice:

git cherry-pick master..topic

Quindi l'intera sequenza scenderà a:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Quando il tuo ramo duplicato di argomento è stato estratto. Ciò eliminerebbe i commit precedentemente selezionati dalla ciliegia dal duplicato corrente e riapplicerebbe tutte le modifiche che si verificano in "topic" in aggiunta al "dump" corrente (antenato diverso). Sembra un modo ragionevolmente conveniente per basare lo sviluppo sul "vero" master upstream mentre si utilizza un master "downstream" diverso per verificare se anche le modifiche locali si applicano ancora a quello. In alternativa puoi semplicemente generare un diff e quindi applicarlo al di fuori di qualsiasi albero dei sorgenti di Git. Ma in questo modo puoi mantenere una versione aggiornata (patchata) aggiornata che si basa sulla versione della tua distribuzione mentre il tuo sviluppo reale è contro il vero master upstream.

Quindi, solo per dimostrare:

  • il reset farà sì che la tua filiale punti a un commit diverso (--hard controlla anche il commit precedente, --soft mantiene i file aggiunti nell'indice (che verrebbero commessi se commetti di nuovo) e il valore predefinito (--mixed) non lo farà controlla il commit precedente (cancellando le modifiche locali) ma cancellerà l'indice (non è stato ancora aggiunto nulla per il commit)
  • puoi semplicemente forzare un ramo a puntare a un commit diverso
  • puoi farlo anche controllando immediatamente quel commit
  • il rebasing funziona su commit presenti nel tuo ramo attuale
  • cherry-picking significa copiare da un ramo diverso

Spero che questo aiuti qualcuno. Volevo riscriverlo, ma non ci riesco ora. Saluti.


0

Dopo che il comando ha funzionato per me, tutte le modifiche locali impegnate vengono eliminate e locale viene reimpostato sullo stesso ramo origine / ramo remoto.

git reset --hard origin

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.