Come ripristinare il commit iniziale di git?


358

Mi impegno per un repository git per la prima volta; Mi pento quindi del commit e voglio ripristinarlo. cerco

# git reset --hard HEAD~1

Ricevo questo messaggio:

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

Questo commit è il primo commit del repository. Qualche idea su come annullare il commit iniziale di git?

Risposte:


566

Devi solo eliminare il ramo in cui ti trovi. Non puoi usarlo git branch -Dperché questo ha un controllo di sicurezza per non farlo. Puoi usare update-refper fare questo.

git update-ref -d HEAD

Evitare Non usare rm -rf .gito qualcosa di simile in quanto ciò completamente cancellare l'intero archivio inclusi tutti gli altri rami, nonché il ramo che si sta tentando di ripristinare.


1
Ho provato questo mentre in un rebase - volevo dividere il primo commit - quindi ha fatto git statuse con mia sorpresa, ha detto Git fatal: Not a git repository (or any parent up to mount point ...)!
Matt Fenwick,

1
questo non ha funzionato per me. Crea file tra cui alcuni che dovrebbero essere ignorati ma no .gitignore. git add ., git commit -m "initial commit", git update-ref -D HEAD, Creare una .gitignore, si noti che git ancora è vedere i file che ha aggiunto in precedenza che dovrebbe ignorato. In altre parole git update-ref -d HEAD, non mi ha riportato allo stato prima del commit iniziale.
Gman,

1
Ma questo è il punto della domanda originale. Tornare allo stato appena prima del commit iniziale.
Gman,

2
git reset --hard HEAD~1rimuoverebbe i file aggiunti per tutti gli altri commit. Chiaramente la domanda è come arrivare allo stesso stato di quel comando funziona in tutti gli altri casi. Guarda questo riassunto per
provare che la

11
Nel caso qualcuno si confonde con i commenti di Gman: git update-ref -d HEAD non effettivamente invertire il primo commit, ma mantiene tutte le modifiche precedentemente commessi aggiunti all'indice. Se desideri rimuovere anche queste modifiche, esegui solo una delle seguenti operazioni git reset --hard. Anche se incompleta, questa risposta è davvero la migliore, quindi evita di usarla rm -fr .git(a meno che tu non sappia cosa stai facendo).
rsenna,

62

È possibile eliminare HEAD e ripristinare il repository in un nuovo stato, in cui è possibile creare un nuovo commit iniziale:

git update-ref -d HEAD

Dopo aver creato un nuovo commit, se si è già passati al remoto, sarà necessario forzarlo sul telecomando per sovrascrivere il precedente commit iniziale:

git push --force origin

1
Vale la pena notare ... questo è il comando corretto ma non cancella HEAD ... cancella il ref (che si trova sotto .git \ refs \ heads) che il file .git \ HEAD ha estratto. Dopo aver eseguito questo comando puoi ancora trovare il file HEAD che punta al file refs / heads / <name> che hai eliminato ma se segui quel percorso vedrai che il riferimento head non esiste più.
DanK,

15

Questa domanda è stata collegata da questo post sul blog ed è stata proposta una soluzione alternativa per le nuove versioni di Git:

git branch -m master old_master
git checkout --orphan master
git branch -D old_master

Questa soluzione presuppone che:

  1. Hai un solo commit sul tuo masterramo
  2. Non esiste un ramo chiamato, old_masterquindi sono libero di usare quel nome

Rinominerà il ramo esistente in old_mastere creerà un nuovo ramo orfano master (come è stato creato per i nuovi repository) dopo il quale è possibile eliminare liberamente old_master... oppure no. Sta a te.

Nota: lo spostamento o la copia di un ramo git ne preserva il reflog (vedere questo codice ) durante l'eliminazione e la creazione di un nuovo ramo lo distrugge. Poiché desideri tornare allo stato originale senza cronologia, probabilmente desideri eliminare il ramo, ma altri potrebbero voler prendere in considerazione questa piccola nota.


11

Alle condizioni stabilite nella domanda:

  • Il commit è il primo commit nel repository.
  • Ciò significa che sono stati eseguiti pochissimi comandi:
    • un git init,
    • presumibilmente alcune git addoperazioni,
    • e un git commit,
    • e questo è tutto!

Se tali requisiti sono soddisfatti, il modo più semplice per annullare il commit iniziale sarebbe:

rm -fr .git

dalla directory in cui lo hai fatto git init. È quindi possibile ripetere il git initper ricreare il repository Git e ripetere le aggiunte con qualsiasi modifica sensata che si è pentita di non aver effettuato la prima volta e ripetere il commit iniziale.

PERICOLO! Ciò rimuove la directory del repository Git.

Rimuove la directory del repository Git in modo permanente e irrecuperabile, a meno che tu non abbia backup da qualche parte. In base alle condizioni preliminari, non hai nulla che desideri conservare nel repository, quindi non perdi nulla. Tutti i file che hai aggiunto sono ancora disponibili nelle directory di lavoro, supponendo che non li hai ancora modificati e non li hai eliminati, ecc. Tuttavia, farlo è sicuro solo se non hai nient'altro nel tuo repository. Nelle circostanze descritte nella domanda "commetti il ​​repository per la prima volta, quindi se ne pentisce", è sicuro. Molto spesso, tuttavia, non è sicuro.

È anche sicuro farlo per rimuovere un repository clonato indesiderato; non danneggia il repository da cui è stato clonato. Butta via tutto ciò che hai fatto nella tua copia, ma non influisce altrimenti sul repository originale.

Fai attenzione, ma è sicuro ed efficace quando sono soddisfatte le condizioni preliminari.

Se hai fatto altre cose con il tuo repository che desideri conservare, allora questa non è la tecnica appropriata: il tuo repository non soddisfa più i presupposti affinché questo sia appropriato.


9
Questo è un cattivo consiglio. E se ci fossero altre cose nel repository che non vuoi perdere?
Matt Fenwick,

5
Quindi non sarebbe il commit iniziale, vero. C'è solo un commit iniziale.
Jonathan Leffler,

9
"Quindi non sarebbe il commit iniziale" - in realtà sì. Stai trascurando il caso molto comune di più rami. Vedi la risposta di Charles.
Matt Fenwick,

2
Utile, tuttavia dovrebbe venire con un avvertimento.
Simon Bengtsson,

5
Questo funziona davvero. La risposta accettata no. Vedi commento
gman,

3

Non puoi. Così:

rm -rf .git/
git init
git add -A
git commit -m 'Your new commit message'

1
Ha provato a dire git reset --hard, quindi perché dovrebbe git add -A?
Aristotele Pagaltzis,

3

Aggiungerò ciò che ha funzionato per me alla fine. Avevo bisogno di rimuovere il commit iniziale su un repository poiché i dati in quarantena erano stati collocati in modo errato, il commit era già stato inviato.

Assicurati di essere attualmente sul ramo giusto.

git checkout master

git update-ref -d HEAD

git commit -m "Initial commit

git push -u origin master

Questo è stato in grado di risolvere il problema.

Importante

Questo era su un repository interno che non era accessibile pubblicamente, se il tuo repository era accessibile pubblicamente, supponiamo che tutto ciò che è necessario ripristinare sia già stato rimosso da qualcun altro.


1

Mi chiedo perché "emendare" non sia suggerito e sia stato cancellato da @damkrat, poiché un emendamento mi sembra il modo giusto per risolvere in modo più efficiente il problema di fondo relativo alla correzione del commit errato poiché non vi è alcuno scopo di non avere iniziale commettere. Come alcuni hanno sottolineato, è necessario modificare il ramo "pubblico" come master solo se nessuno ha clonato il repository ...

git add <your different stuff>
git commit --amend --author="author name <author.name@email.com>"-m "new message"

--author è richiesto solo se qualcuno corregge la paternità del commit
Richard

0

git reset --hard apporta le modifiche, quindi fai

git add -A
git commit --amend --no-edit 

o

git add -A
git commit --amend -m "commit_message"

e poi

git push origin master --force

--force riscriverà il commit a cui hai reimpostato nel primo passaggio.

Non farlo, perché stai per andare contro l'idea dei sistemi VCS e git in particolare. L'unico buon metodo è quello di creare nuovi ed eliminare i rami non necessari. Vedi git help branchper info.


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.