Cosa succede ai commit git creati in uno stato HEAD distaccato?


137

Questo è quello che è successo:

Ho un ramo A. Sul ramo AI ha commesso un sacco di cambiamenti. Non ero soddisfatto del codice, quindi ho verificato il precedente commit nel ramo A. Ho quindi apportato molte altre modifiche e li ho impegnati nel ramo A. Ora non riesco a trovare questo commit ovunque. Ho perso questo codice?


Quando dici "Ho verificato il precedente commit nel ramo A", vuoi dire "Ho ripristinato il ramo A al commit precedente"? cioè hai effettivamente git resetpiuttosto che git checkout?
CB Bailey

No, ho usato il checkout. reflog ha funzionato.
Mausimo,

Se hai utilizzato il checkout, sarai stato su un distaccato HEADe il ramo A sarebbe rimasto sul commit precedente. Esattamente quali comandi hai eseguito?
CB Bailey

1
Stavo usando la GUI di SourceTree GIT su OSX Lion. Ero sul ramo A e ho eseguito un checkout del commit precedente sul ramo A. Poi ho fatto un sacco di modifiche al codice e il commit (ramo A). Credo di avere una testa staccata.
Mausimo,

OK, penso che ero confuso quando hai detto che hai commesso un mucchio ulteriori modifiche sul ramo A .
CB Bailey

Risposte:


186

Il vecchio commit è ancora nel reflog.

git reflog

Questo mostrerà un elenco di commit, e il commit "perso" dovrebbe essere lì. Puoi trasformarlo in un nuovo ramo. Ad esempio, se SHA-1 è ba5a739, è possibile creare un nuovo ramo denominato "nuovo ramo" al vecchio commit con:

git branch new-branch ba5a739

Si noti che i commit "persi" verranno eliminati quando si elimina il database.


3
Ho fatto la stessa cosa e ho avuto un attacco di cuore pensando che fosse perso. Grazie per le informazioni!
Chase

15
Utilizzare git cherry-pick [SHA]per spostare il commit su una succursale esistente nel caso in cui tu abbia commesso accidentalmente in stato di testa distaccato
Jan Aagaard Meier,

3
In alternativa puoi passare a un ramo esistente ed eseguire "git merge HEAD @ {n}" n corrispondente al commit "perso" elencato nel reflog.
eaykin,

Sai se pruneeliminerebbe anche i commit staccati a cui si fa riferimento nei messaggi di commit? O questo li rende raggiungibili ?
Kamafeather,

@Kamafeather: non credo che li rende raggiungibili.
Dietrich Epp,

64

I tuoi commit sono ancora disponibili nel reflog, come già sottolineato. In aggiunta alle altre risposte, ecco un modo per prendere in consegna i commit testa staccata nel tuo ramo corrente direttamente , senza creare e la fusione di una nuova filiale:

  1. Cerca gli hash SHA-1 dei commit effettuati nello stato HEAD distaccato

    git reflog
    
  2. Quindi esegui, con tutti gli hash di commit ordinati dal più vecchio al più recente:

    git cherry-pick <hash1> <hash2> <hash3> ...
    

    Ad esempio se ne avessi solo uno, dato nel formato hash corto "primi 7 caratteri":

    git cherry-pick a21d053
    

Questo creerà nuovi commit per il tuo ramo corrente, un commit per ogni hash di HEAD-commit che hai citato nel comando. Assume anche i messaggi di commit originali.


11

È possibile trovare commit persi (penzoloni) con il seguente comando:

git fsck --lost-found

Nota, se la tua testa attuale è penzolante, non viene elencata come persa.

Puoi trovare maggiori informazioni nella pagina del manuale di git-fsck (1)

Quindi è possibile creare il ramo su quel commit perso:

git branch new-branch ba5a739

Prima ho usato il comando "git reflog" e poi "git branch new-branch ba5a739" per un sottomodulo, ha funzionato.
ondermerol,

7

Git parlance per lo stato della directory di lavoro è un " HEAD distaccato ". Ecco un altro posto che git reflogeffettua il salvataggio.

$ git reflog
0b40dd6 HEAD@{0}: commit: my commit on detached HEAD
...

Se provo a controllare un altro ramo, git-1.7.5.1 fornisce un suggerimento utile.

$ git checkout master
Avviso: stai lasciando 1 commit dietro, non connesso
uno dei tuoi rami:

  0b40dd6 il mio commit su HEAD distaccato

Se vuoi mantenerli creando una nuova filiale, potrebbe essere un buon momento
per farlo con:

 git branch nome_branch nuovo 0b40dd65c06bb215327863c2ca10fdb4f904215b

Passato al ramo "master"

Grazie per le informazioni e il link. Il link mi ha aiutato a capire cosa stava succedendo.
Mausimo,

6

Non l'hai persa, Git ne conserva ancora una copia (ma al momento non è raggiungibile da nessuna testa del ramo). Puoi trovare il commit mancante usando il git reflogcomando. Il reflog tiene traccia delle posizioni storiche di una testa di ramo e puoi usarlo per trovare cose a cui la testa di ramo puntava in precedenza.


4

Seguire questi passaggi per collegare la testa staccata indietro al repository git

  1. git checkout "your branch with path but without remote name"

ad es. se il nome remoto è di origine e viene bugfix/somebranchutilizzato il nome del ramogit checkout bugfix/somebranch

  1. git reflog ottenere gli SHA di commit elencati dall'elenco di commit del ramo distaccato.

  2. git cherry-pick "commit hash1" "commit hash2" "commit hash3"

  3. git push

TUTTO STABILITO!!


2

In Sourcetree, ho scoperto che git reflog non funzionava, quindi ho capito come farlo usando la GUI.

Innanzitutto, prova a trovare il commit "perso" cercando un messaggio nella cronologia dei comandi (visualizza: Mostra output dei comandi). Si spera che sarà nel comando "Cambio ramo" dopo il commit che hai perso e vedrai il commento di commit con un ID commit 1234567.

Porta l'ID commit al passaggio successivo.

Premi il pulsante "Branch" nella barra degli strumenti in alto e dovresti ottenere una finestra di dialogo "New Branch" in cui puoi specificare un certo commit. Inserisci l'ID Commit lì dentro, specifica un nuovo nome di filiale, premi Crea ramo e dovresti ottenere una nuova filiale con il tuo commit perso!

Questo mi ha riportato un po 'di lavoro perduto!

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.