Puis-je récupérer une branche après sa suppression dans Git?


1068

Si je cours git branch -d XYZ, existe-t-il un moyen de récupérer la branche? Existe-t-il un moyen de revenir en arrière comme si je n'avais pas exécuté la commande delete branch?


4
Une note vraiment impressionnante à faire sur la réponse acceptée est qu'elle fonctionne même si la branche a été supprimée à l'origine! Je viens de récupérer plusieurs branches que je n'avais plus localement après leur suppression accidentelle d'origine.
theblang

Réponses:


1955

Oui, vous devriez pouvoir faire git refloget trouver le SHA1 pour le commit à la pointe de votre branche supprimée, alors juste git checkout [sha]. Et une fois que vous êtes à ce commit, vous pouvez simplement git checkout -b [branchname]recréer la branche à partir de là.


Nous remercions @Cascabel pour cette version condensée / monocouche.

Vous pouvez le faire en une seule étape:

git checkout -b <branch> <sha>

477
Vous pouvez le faire en une seule étape: git checkout -b <branch> <sha>.
Cascabel

200
Astuce rapide - si vous venez de supprimer la branche, vous verrez quelque chose comme ça dans votre terminal - "Branche supprimée <votre-branche> (était <sha>)". Et puis c'est super facile - utilisez-le <sha>. Par exemple, comme mentionné ci-dessus -git checkout -b <branch> <sha>
Snowcrash

6
oui, faites défiler vers le haut dans votre terminal (sauf si vous l'avez fait CMD+K)
neaumusic

42
Utilisez git reflog --no-abbrevpour voir le texte complet <sha>abrégé par défaut.
jkulak

5
Pour quelqu'un d'autre comme moi, qui a eu du mal à trouver le sha de la branche supprimée: j'ai pu git checkout remotes/origin/deleted_branch.
Jeff Irwin

161

La plupart du temps, les validations inaccessibles sont dans le reflog. Donc, la première chose à essayer est de regarder le reflog en utilisant la commande git reflog(qui affiche le reflog pour HEAD).

Peut-être quelque chose de plus facile si la validation faisait partie d'une branche spécifique encore existante est d'utiliser la commande git reflog name-of-my-branch. Cela fonctionne également avec une télécommande, par exemple si vous avez forcé la poussée (conseil supplémentaire: préférez toujoursgit push --force-with-lease plutôt que mieux éviter les erreurs et est plus récupérable).


Si vos commits ne sont pas dans votre reflog (peut-être parce qu'ils ont été supprimés par un outil tiers qui n'écrit pas dans le reflog), j'ai réussi à récupérer une branche en réinitialisant ma branche au sha du commit trouvé en utilisant une commande comme celle-ci (elle crée un fichier avec toutes les validations pendantes):

git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

Si vous devez l'utiliser plus d'une fois (ou si vous voulez l'enregistrer quelque part), vous pouvez également créer un alias avec cette commande ...

git config --global alias.rescue '!git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt'

et l'utiliser avec git rescue

Pour rechercher les validations trouvées, vous pouvez afficher chaque validation à l'aide de certaines commandes pour les examiner.

Pour afficher les métadonnées de validation (auteur, date de création et message de validation):

git cat-file -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Pour voir aussi les diffs:

git log -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Une fois que vous avez trouvé votre commit, créez une branche sur ce commit avec:

git branch commit_rescued 48540dfa438ad8e442b18e57a5a255c0ecad0560

Pour ceux qui sont sous Windows et qui aiment les interfaces graphiques, vous pouvez facilement récupérer les validations (et également les fichiers intermédiaires non validés) avec GitExtensions en utilisant la fonctionnalité Repository=> Git maintenance=>Recover lost objects...


Une commande similaire pour récupérer facilement les fichiers intermédiaires supprimés: https://stackoverflow.com/a/58853981/717372


2
Une aide énorme. J'avais un commit perdu qui n'était jamais dans mon dépôt local. La première commande que vous avez là-haut m'a aidé à le trouver sur le serveur. +1
Sean Adkinson

1
cet alias de sauvetage git est une aubaine !!! Merci beaucoup pour votre contribution!
72A12F4E

2
Tu m'as sauvé la vie.
Jed Lynch

La réponse de Patrick Koorevaar m'a aidé, car je ne connais pas mes derniers branchements branchés supprimés <sha>.
Monir Khan

@ Monir-Khan Et? Que dois-je conclure? La réponse de Patrick n'est qu'un copier / coller de ma commande (avec une erreur: il a oublié de filtrer sur les commits) ...
Philippe

45

Si vous aimez utiliser une interface graphique, vous pouvez effectuer toute l'opération avec gitk.

gitk --reflog

Cela vous permettra de voir l'historique des validations de la branche comme si la branche n'avait pas été supprimée. Maintenant, faites simplement un clic droit sur le commit le plus récent de la branche et sélectionnez l'option de menu Create new branch.


28

La solution la mieux votée fait en fait plus que ce qui était demandé:

git checkout <sha>
git checkout -b <branch>

ou

git checkout -b <branch> <sha>

vous déplacer vers la nouvelle branche avec toutes les modifications récentes que vous avez peut-être oublié de valider. Ce n'est peut-être pas votre intention, surtout lorsque vous êtes en "mode panique" après avoir perdu la branche.

Une solution plus propre (et plus simple) semble être le one-liner (après avoir trouvé le <sha>avec git reflog):

git branch <branch> <sha>

Désormais, ni votre branche actuelle ni les modifications non validées ne sont affectées. Au lieu de cela, seule une nouvelle branche sera créée jusqu'à la <sha>.

Si ce n'est pas l'astuce, cela fonctionnera toujours et vous obtiendrez une branche plus courte, alors vous pouvez réessayer avec un nouveau <sha>et un nouveau nom de branche jusqu'à ce que vous obteniez le bon résultat.

Enfin, vous pouvez renommer la branche restaurée avec succès en son nom ou toute autre chose:

git branch -m <restored branch> <final branch>

Inutile de dire que la clé du succès était de trouver le bon commit <sha>, alors nommez vos commits à bon escient :)


14

Ajout à la réponse tfe : il y a aussi le script git-resurrect.sh dans la contrib/zone des sources Git (dans le dépôt git.git), qui pourrait vous aider.

git-resurrect <name>tente de trouver des traces d'un bout de branche appelé <name>et essaie de le ressusciter. Actuellement, le reflog est recherché pour les messages d'extraction, ainsi que pour les -rmessages de fusion. Avec -met -t, l'historique de toutes les références est analysé pour Merge <name> into other/ Merge <other> into <name>(respectivement) valider les sujets, ce qui est plutôt lent mais vous permet de ressusciter les branches de sujets d'autres personnes.


1
Cela a fonctionné pour moi maintenant même si je devais ajouter / usr / lib / git-core / à mon PATH. Mais il n'a pas réalisé le miracle que j'espérais :(
AmanicA

10

J'ai utilisé les commandes suivantes pour rechercher et récupérer ma branche supprimée. Les premières étapes proviennent de la description de gcb.

$ git fsck --full --no-reflogs --unreachable --lost-found > lost
$ cat lost | cut -d\  -f3 > commits
$ cat commits | xargs -n 1 git log -n 1 --pretty=oneline

Recherchez maintenant l'ID de validation git (GIT-SHA) basé sur les commentaires de validation et utilisez-le dans la commande ci-dessous. Découvrez une nouvelle branche appelée NEW-BRANCH avec le GIT-SHA précédemment trouvé:

$ git checkout -b NEW-BRANCH GIT-SHA

Merci beaucoup. Il a fallu un peu de temps pour rechercher le nom, mais le temps en valait la peine. S'il existe un moyen de rechercher également sur la chaîne de message de validation, ce serait bien mieux.
Monir Khan

9

Si vous n'avez pas de reflog, par exemple. comme vous travaillez dans un référentiel nu où le reflog n'est pas activé et la validation que vous souhaitez récupérer a été créée récemment, une autre option consiste à rechercher les objets de validation récemment créés et à les parcourir.

Depuis l'intérieur du .git/objectsrépertoire, exécutez:

find . -ctime -12h -type f | sed 's/[./]//g' | git cat-file --batch-check | grep commit

Cela recherche tous les objets (validations, fichiers, balises, etc.) créés au cours des 12 dernières heures et les filtre pour afficher uniquement les validations. Leur vérification est alors un processus rapide.

J'essaierais d'abord le script git-ressurect.sh mentionné dans la réponse de Jakub .


1
Belle idée alternative! Votre commande génère cependant une erreur. Le problème est avec la partie "12h" (en fait le "h"). Une fois que j'ai supprimé le "h", cela a bien fonctionné. De man find: "-ctime n - Le statut du fichier a été modifié pour la dernière fois il y a n * 24 heures." Nous devons donc également changer 12 à 0,5 pour avoir le comportement attendu des 12 dernières heures.
pagliuca

1
J'utilise OS X 10.8 ici, donc les drapeaux 'find' ci-dessus sont basés sur la version qu'il expédie.
Robert Knight

1
Oui, bien sûr, le problème est avec les versions! C'est pourquoi j'ai voté votre réponse en premier lieu! Je viens de commenter pour que les gens réalisent que les paramètres peuvent être différents.
pagliuca

9

Pour les utilisateurs de GitHub sans Git installé:

Si vous souhaitez le restaurer à partir du site Web de GitHub , vous pouvez utiliser leur API pour obtenir une liste des événements liés au dépôt:

Première

  • trouver ces SHA (validation des hachages):

    curl -i https://api.github.com/repos/PublicUser/PublicRepo/events

    ... ou pour des repos privés:

    curl -su YourUserName https://api.github.com/repos/YourUserName/YourProject/events

    (sera invité à entrer le mot de passe GitHub)

    • (Si le dépôt requiert une authentification à deux facteurs, voir les commentaires sur cette réponse ci-dessous.)

Prochain

  • allez sur GitHub et créez une nouvelle branche temporaire qui sera supprimée pour toujours ( Chrome est préférable).

   • Accédez aux succursales et supprimez celle-ci.

   •   Sur la même page, sans rechargement , ouvrez DevTools, panneau Réseau. Maintenant, préparez ...

   • Cliquez sur restaurer. Vous remarquerez une nouvelle "ligne". Faites un clic droit dessus et sélectionnez "Copier en tant que cURL" et enregistrez ce texte dans un éditeur.

   • Append à la fin de la ligne copiée de code, celui - ci: -H "Cookie=".

Vous devriez maintenant obtenir quelque chose comme:

    curl 'https://github.com/UserName/ProjectName/branches?branch=BranchSHA&name=BranchName' -H 'Cookie:' -H 'Origin: https://github.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US' -H 'User-Agent: User-Agent' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: https://github.com/UserName/ProjectName/branches' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=token' --compressed

Dernière étape

  • remplacez "BranchSHA" par votre SHA-hash et BranchName par le nom souhaité (BTW, c'est un bon hack pour renommer une branche à partir du Web). Si vous n'êtes pas trop lent, vous devez quand même faire cette demande. Par exemple, copiez-collez simplement sur un terminal.

PS

Je me rends compte que ce n'est peut-être pas la "solution la plus simple" ou la "bonne" solution, mais elle est offerte au cas où quelqu'un la trouverait utile.


1
Ce qui précède est l'un des rares qui ne dépend pas git refloget a donc été utile, par exemple, pour avoir supprimé une branche distante et perdu l'accès à l'ordinateur, ce qui a été fait de sorte que rien de utile ne peut être obtenu reflog. Notez que lorsque vous utilisez OAuth ou l'authentification à deux facteurs sur Github, la curlcommande prend la forme: curl -u username:token https://api.github.com/useroucurl -H "Authorization: token TOKEN" https://api.github.com/repos/USER_OR_ORG_NAME/REPO_NAME/events
TT--

@ TT-- wow, je suis content que ça ait aidé! et merci pour votre contribution concernant le jeton d'authentification :)
Maxim Mazurok

8

D'après ce que je comprends si la branche à supprimer peut être atteinte par une autre branche, vous pouvez la supprimer en toute sécurité à l'aide

git branch -d [branch]

et votre travail n'est pas perdu. N'oubliez pas qu'une branche n'est pas un instantané, mais un pointeur vers une branche. Ainsi, lorsque vous supprimez une branche, vous supprimez un pointeur.

Vous ne perdrez même pas de travail si vous supprimez une branche qui ne peut pas être atteinte par une autre. Bien sûr, ce ne sera pas aussi simple que de vérifier le hachage de validation, mais vous pouvez toujours le faire. C'est pourquoi Git ne peut pas supprimer une branche qui ne peut pas être atteinte en utilisant -d. Au lieu de cela, vous devez utiliser

git branch -D [branch]

Cela fait partie d'une vidéo incontournable de Scott Chacon sur Git. Vérifiez la minute 58:00 quand il parle des branches et comment les supprimer.

Introduction à Git avec Scott Chacon de GitHub


7
Comment cela aide-t-il à répondre à la question?
Dmitri Zaitsev

6
Dire au demandeur que les branches ne contiennent pas de contenu mais sont en fait des pointeurs. Vous n'avez pas besoin d'avoir peur de supprimer des branches .. vous pouvez en créer de nouvelles pointant vers le même commit que celui supprimé .... Wow! Je me souviens encore quand j'ai posé cette question. Bon retour en 2012!
fabiopagoti

1
J'ai dû faire défiler trois écrans pour enfin trouver une réponse qui résout le problème: supprimer une branche, c'est supprimer un simple pointeur. Aucune situation de perte de données ici, la seule chose à récupérer est où cela pointait-il. Les réponses qui vont directement à reflogsont simplement exagérées.
RomainValeri

5

Assurez-vous d'effectuer tout cela localement et confirmez que votre dépôt est dans l'état souhaité avant de passer à Bitbucket Cloud. Il peut également être judicieux de cloner votre référentiel actuel et de tester ces solutions en premier.

  1. Si vous venez de supprimer la branche, vous verrez quelque chose comme ça dans votre terminal:
    Deleted branch <your-branch> (was <sha>)

Pour restaurer la branche, utilisez:

    git checkout -b <branch> <sha>

Si vous ne connaissez pas le «sha» du haut de votre tête, vous pouvez:

  1. Trouvez le «sha» pour le commit à l'extrémité de votre branche supprimée en utilisant:
    git reflog
  1. Pour restaurer la branche, utilisez:
    git checkout -b <branch> <sha>

Si vos commits ne sont pas dans votre reflog:

  1. Vous pouvez essayer de récupérer une branche en réinitialisant votre branche au sha du commit trouvé en utilisant une commande comme:
    git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

2.Vous pouvez ensuite afficher chaque commit à l'aide de l'un d'eux:

    git log -p <commit>
    git cat-file -p <commit>

4

Pour récupérer une branche supprimée, parcourez d'abord l'historique de reflog,

git reflog -n 60

Où n fait référence aux n derniers validations. Trouvez ensuite la tête appropriée et créez une branche avec cette tête.

git branch testbranch HEAD@{30}

4

J'ai rebasé une branche à distance pour essayer d'effacer quelques commits que je ne voulais pas et j'allais choisir les bons que je voulais. Bien sûr, j'ai mal écrit les SHA ...

Voici comment je les ai trouvés (principalement une interface / interaction plus facile à partir des choses sur les réponses ici):

Commencez par générer une liste des validations lâches dans votre journal. Faites-le dès que possible et arrêtez de travailler, car ceux-ci peuvent être jetés par le garbage collector.

git fsck --full --no-reflogs --unreachable --lost-found > lost

Cela crée un lostfichier avec toutes les validations que vous devrez consulter. Pour simplifier notre vie, coupons-en seulement le SHA:

cat lost | cut -d\  -f3 > commits

Vous avez maintenant un commitsfichier avec tous les commits que vous devez consulter.

En supposant que vous utilisez Bash, la dernière étape:

for c in `cat commits`; do  git show $c; read; done

Cela vous montrera les informations de diff et de validation pour chacun d'eux. Et attendez que vous appuyiez Enter. Maintenant, notez tous ceux que vous voulez, puis sélectionnez-les. Une fois que vous avez terminé, appuyez simplement sur Ctrl-C.



1

Allez d'abord dans git batch pour passer à votre projet comme:

cd android studio project
cd Myproject
then type :
git reflog

Vous avez tous une liste des changements et le numéro de référence prend le numéro de référence puis passez
à la caisse depuis Android studio ou depuis le git betcha. une autre solution, prenez le numéro de référence et allez dans le studio Android, cliquez sur git branches vers le bas, puis cliquez sur la case à cocher ou la révision après le numéro de référence, puis lol, vous avez les branches.


1

Ajout à la réponse de tfe, vous pouvez récupérer avec ce processus mentionné, à moins que ses validations ne soient pas récupérées. La branche Git est simplement un pointeur vers une validation particulière dans l'arbre de validation. Mais si vous supprimez le pointeur et que les validations sur cette branche ne sont pas fusionnées dans une autre branche existante, git le traite comme des validations pendantes et les supprime lors du garbage collection, qu'il peut exécuter automatiquement périodiquement.

Si votre branche n'a pas été fusionnée avec une branche existante et si elle a été récupérée, vous perdrez toutes les validations jusqu'au point d'où la branche a été bifurquée à partir d'une branche existante.


1

Un problème connexe: je suis arrivé sur cette page après avoir cherché "comment savoir quelles sont les branches supprimées".

Lors de la suppression de nombreuses anciennes branches, j'ai senti que j'avais supprimé par erreur l'une des nouvelles branches, mais je ne connaissais pas le nom pour la récupérer.

Pour savoir quelles branches ont été supprimées récemment, procédez comme suit:

Si vous accédez à votre URL Git, qui ressemblera à ceci:

https://your-website-name/orgs/your-org-name/dashboard

Ensuite, vous pouvez voir le flux, de ce qui est supprimé, par qui, dans un passé récent.


Sûr. La réponse ci-dessus est pour GitHub. Nous avons installé GitHub localement. Merci d'avoir posé une question.
Manohar Reddy Poreddy

1

Je l'ai fait sur l'ordinateur dont je supprime la branche:

git reflog

réponse:

74b2383 (develope) HEAD@{1}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: checkout: moving from develope to master
74b2383 (develope) HEAD@{3}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{4}: reset: moving to HEAD
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{5}: clone: from http://LOCALGITSERVER/myBigProject/Android.git

et je récupère la branche avec cette commande:

git checkout -b newBranchName 74b2383


0

Le simple git reflogfait de ne pas retourner le shapour moi. Seul le commit id(qui est long de 8 caractères et un sha est beaucoup plus long)

J'ai donc utilisé git reflog --no-abbrev

Et puis faites la même chose que mentionné ci-dessus: git checkout -b <branch> <sha>


vous pouvez toujours utiliser le sha abrégé à 8 caractères, vous n'avez pas à utiliser le sha complet
Michael Dreher

0

SI vous utilisez VSCode ... et que vous avez synchronisé votre branche avec le serveur à un moment donné avant de la supprimer ...

Notez que git branch delete supprime uniquement la copie locale, pas la copie sur le serveur. Tout d'abord, dans le panneau Git (icône git sur la barre d'outils de gauche), regardez à travers les branches et voyez si votre branche est toujours là sous "origine / votre_nom_branche". Si c'est le cas, sélectionnez-le et vous devriez récupérer votre code (suggérer de le copier / coller / enregistrer immédiatement localement ailleurs).

Si vous ne voyez pas "origin / your_branch_name", installez l'extension GitLens. Cela vous permet de fouiller visuellement dans les référentiels du serveur et de localiser la copie que vous avez synchronisée avec le serveur. Si vous avez plusieurs référentiels, notez qu'il peut être nécessaire d'ouvrir au moins un fichier à partir du référentiel souhaité afin de faire apparaître le référentiel dans GitLens. Alors:

  1. Ouvrez le panneau GitLens

  2. Développez le référentiel

  3. Vous devriez voir une liste de catégories: Succursales / Contributeurs / Télécommandes / Cachettes / etc

Vous devriez trouver YourLostTreasure sous "Branches" ou éventuellement sous "Télécommandes -> Origines". J'espère que vous verrez une branche avec le nom souhaité - si vous la développez, vous devriez voir les fichiers que vous avez modifiés dans cette branche. Double-cliquez sur les noms de fichiers pour les ouvrir et sauvegardez immédiatement ce code.

Si vous ne voyez pas immédiatement votre branche perdue, fouillez et si vous trouvez quelque chose de prometteur, ouvrez-le immédiatement et saisissez le code. J'ai dû fouiller un peu jusqu'à ce que je trouve TheGoldenBranch, et même alors, le code manquait les un ou deux derniers enregistrements (peut-être parce que je n'ai pas réussi à me synchroniser avec le serveur avant d'essayer de fusionner une branche, mais en cliquant accidentellement sur) Supprimer la branche). Ma recherche a été inutilement allongée car lorsque j'ai trouvé la branche pour la première fois, je n'étais pas complètement sûr que le nom était correct, alors j'ai continué à chercher, et il a fallu un certain temps pour retrouver cette première branche. (Ainsi, Carpe Carpum et puis continuer à chercher.)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.