Qu'arrive-t-il aux commits git créés dans un état HEAD détaché?

137

C'est ce qui s'est passé:

J'ai une branche A. Sur la branche AI ​​a commis un tas de changements. Je n'étais pas satisfait du code, j'ai donc vérifié le commit précédent dans la branche A. J'ai ensuite apporté un tas de modifications supplémentaires et les ai validées sur la branche A. Maintenant, je ne trouve ce commit nulle part. Ai-je perdu ce code?

Mausimo
la source
Quand vous dites "J'ai vérifié le commit précédent dans la branche A", voulez-vous dire "Je réinitialise la branche A au commit précédent"? c'est à dire avez-vous en fait git resetplutôt que git checkout?
CB Bailey
Non, j'ai utilisé la caisse. reflog a fonctionné.
Mausimo le
Si vous avez utilisé checkout, vous aurez été sur un détaché HEADet la branche A serait restée sur le commit précédent. Quelles commandes avez-vous exécutées exactement?
CB Bailey
1
J'utilisais l'interface graphique SourceTree GIT sur OSX Lion. J'étais sur la branche A et j'ai effectué une vérification du commit précédent sur la branche A. J'ai ensuite fait un tas de changements de code et commis (branche A). Je crois que j'avais une TÊTE détachée.
Mausimo
OK, je pense que je ne comprenais pas quand vous avez dit que vous avez commis un tas d' autres changements sur la branche A .
CB Bailey

Réponses:

186

L'ancien commit est toujours dans le reflog.

git reflog

Cela affichera une liste de commits, et le commit «perdu» devrait être là. Vous pouvez en faire une nouvelle succursale. Par exemple, si le SHA-1 est ba5a739, vous pouvez créer une nouvelle branche nommée "new-branch" à l'ancien commit avec:

git branch new-branch ba5a739

Notez que les commits «perdus» seront supprimés lorsque la base de données sera élaguée.

Dietrich Epp
la source
3
J'ai fait la même chose et j'ai eu une crise cardiaque en pensant qu'elle était perdue. Merci pour l'info!
Poursuite du
15
Utilisez git cherry-pick [SHA]pour déplacer le commit sur une branche existante au cas où vous vous seriez accidentellement commis alors que vous étiez dans l'état principal détaché
Jan Aagaard Meier
3
Vous pouvez également basculer vers une branche existante et faire "git merge HEAD @ {n}" n correspondant au commit "lost" listé dans reflog.
eaykin
Savez-vous si le prunesupprimerait également les commits détachés qui sont référencés dans les messages de validation? Ou cela les rend joignables ?
Kamafeather
@Kamafeather: Je ne pense pas que cela les rend joignables.
Dietrich Epp
64

Vos commits sont toujours disponibles dans le reflog, comme indiqué précédemment. En plus des autres réponses, voici un moyen de reprendre directement les commits HEAD détachés dans votre branche actuelle , sans créer ni fusionner une nouvelle branche:

  1. Recherchez les hachages SHA-1 des commits que vous avez effectués dans l'état HEAD détaché avec

    git reflog
    
  2. Ensuite, exécutez, avec tous les hachages de validation classés du plus ancien au plus récent:

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

    Par exemple si j'en avais un seul, donné dans le format de hachage court "7 premiers caractères":

    git cherry-pick a21d053
    

Cela créera de nouveaux commits dans votre branche actuelle, un commit par hachage détaché-HEAD-commit que vous mentionnez dans la commande. Il reprend également les messages de validation d'origine.

Tanius
la source
11

Vous pouvez trouver des commits perdus (pendants) avec la commande suivante:

git fsck --lost-found

Notez que si votre tête actuelle est en cours de validation, elle n'est pas répertoriée comme perdue.

Vous pouvez trouver plus d'informations sur la page de manuel git-fsck (1)

Ensuite, vous pouvez créer une branche sur ce commit perdu:

git branch new-branch ba5a739
sergtk
la source
J'ai d'abord utilisé la commande "git reflog" puis "git branch new-branch ba5a739" pour un sous-module, cela a fonctionné.
ondermerol
7

Le langage Git pour l'état de votre répertoire de travail est un « HEAD détaché ». Voici un autre endroit qui git reflogfait la sauvegarde.

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

Si j'essaye de récupérer une autre branche, git-1.7.5.1 donne une suggestion utile.

$ git checkout master
Attention: vous laissez 1 commit derrière vous, non connecté à
l'une de vos succursales:

  0b40dd6 mon commit sur HEAD détaché

Si vous souhaitez les conserver en créant une nouvelle branche, cela peut être le bon moment
pour le faire avec:

 git branch new_branch_name 0b40dd65c06bb215327863c2ca10fdb4f904215b

Passé à la branche «maître»
Greg Bacon
la source
Merci pour l'information et le lien. Le lien m'a aidé à comprendre ce qui se passait.
Mausimo le
6

Vous ne l'avez pas perdu, Git en garde toujours une copie (mais il est actuellement inaccessible par n'importe quel chef de branche). Vous pouvez trouver votre commit manquant en utilisant la git reflogcommande. Le reflog garde la trace des positions historiques d'une tête de branche et vous pouvez l'utiliser pour rechercher les éléments sur lesquels la tête de branche pointait précédemment.

Greg Hewgill
la source
4

Suivez ces étapes pour relier votre tête détachée à git repo

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

Par exemple, si le nom distant est l'origine et le nom de la branche est bugfix/somebranchalors utilisezgit checkout bugfix/somebranch

  1. git reflog récupérez les SHA de commit répertoriés dans votre liste de commit de la branche détachée.

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

  3. git push

TOUT ENSEMBLE !!

user1520615
la source
2

Dans Sourcetree, j'ai trouvé que git reflog ne fonctionnait pas, alors j'ai compris comment faire cela en utilisant l'interface graphique.

Tout d'abord, essayez de trouver le commit "perdu" en recherchant un message dans l'historique des commandes (vue: Afficher la sortie de la commande). J'espère que ce sera dans la commande "Switching Branch" après le commit que vous avez perdu et vous verrez le commentaire de commit avec un ID de commit 1234567.

Passez cet ID de validation à l'étape suivante.

Appuyez sur le bouton "Branche" dans la barre d'outils supérieure et vous devriez obtenir une boîte de dialogue "Nouvelle Branche" où vous pouvez spécifier un certain commit. Mettez cet ID de validation, spécifiez un nouveau nom de branche, appuyez sur Créer une branche et vous devriez obtenir une nouvelle branche avec votre validation perdue!

Cela m'a rapporté du travail perdu!

blond
la source