130 votes

Git : Récupérer une branche supprimée (à distance)

J'ai besoin de récupérer deux branches Git que j'ai en quelque sorte supprimées lors d'un push.

Ces deux branches ont été créées sur un système différent, puis poussées vers mon dépôt "partagé" (github).

Sur mon système, j'ai (apparemment) récupéré les branches lors d'un fetch :

~/myfolder> git fetch
remote: Counting objects: 105, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 62 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (62/62), done.
From github.com:mygiturl
 * [new branch]      contact_page -> origin/contact_page
   731d1bb..e8b68cc  homepage   -> origin/homepage
 * [new branch]      new_pictures -> origin/new_pictures

Juste après, j'ai fait un push pour envoyer mes changements locaux vers le dépôt central. Pour une raison quelconque, ces branches ont été supprimées à la fois de mon système local et du dépôt central :

~/myfolder> git push
Counting objects: 71, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (49/49), 4.99 KiB, done.
Total 49 (delta 33), reused 0 (delta 0)
To git@github.com:mygiturl.git
 - [deleted]         contact_page
 + e8b68cc...731d1bb homepage -> homepage (forced update)
   bb7e9f2..e0d061c  master -> master
 - [deleted]         new_pictures
   e38ac2e..bb7e9f2  origin/HEAD -> origin/HEAD
   731d1bb..e8b68cc  origin/homepage -> origin/homepage
   e38ac2e..bb7e9f2  origin/master -> origin/master
 * [new branch]      origin/contact_page -> origin/contact_page
 * [new branch]      origin/new_pictures -> origin/new_pictures

Il n'est pas très facile d'extraire les branches de leur machine d'origine. J'aimerais donc essayer de les récupérer sur ma machine locale si possible.

Toutes les informations sur l'annulation de git que j'ai trouvées sur Google concernent la récupération de commits perdus. Je ne pense pas que cela s'applique ici, puisque je n'ai pas d'UID de commit pour ces branches.

J'aimerais savoir comment je peux les récupérer. J'aimerais également savoir comment ils ont été supprimés et comment je peux éviter cela à l'avenir.

EDIT : à la demande, voici la configuration de mon repo

user.name=Craig Walker
user.email=github@softcraft.ca
alias.unadd=reset HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=git@github.com:MyGitURL.git
remote.origin.mirror=true
branch.master.remote=origin
branch.master.merge=refs/heads/master
alias.undo=reset --hard
alias.test=push -f ci HEAD:master
alias.st=status
alias.ci=commit
alias.br=branch
alias.co=checkout
alias.ch=checkout
alias.df=diff
alias.lg=log -p
alias.who=shortlog -s --
remote.ci.url=ContinuousIntegrationGitURL
remote.ci.fetch=+refs/heads/*:refs/remotes/ci/*
branch.photo.remote=origin
branch.photo.merge=refs/heads/photos
remote.foo.url=FooGitURL
remote.foo.fetch=+refs/heads/*:refs/remotes/cynthia/*
branch.homepage.remote=origin
branch.homepage.merge=refs/heads/homepage

0 votes

Il semble que vous ayez une configuration "inhabituelle" ou mal adaptée pour la récupération et la poussée. Que fait git config -l pour le référentiel local ?

0 votes

C'est tout à fait possible ; je l'ai affiché.

2 votes

Votre remote.origin.fetch refspec n'est pas approprié pour être utilisé avec remote.origin.mirror = true . Voulez-vous faire un miroir ou voulez-vous utiliser le repo GitHub comme une télécommande normale ? Ma réponse devrait contenir les commandes dont vous avez besoin dans les deux cas.

123voto

iamamac Points 3333

Je ne suis pas un expert. Mais vous pouvez essayer

git fsck --full --no-reflogs | grep commit

pour trouver le commit HEAD de la branche supprimée et les récupérer.

0 votes

J'ai essayé fsck plus tôt ; savez-vous comment trouver quel commit est le bon ? J'en ai 20 à essayer.

1 votes

Cela a fonctionné, une fois que j'ai eu les messages de validation, git branch <uid> Je les ai récupérés. Merci !

0 votes

C'est bon à entendre. Assurez-vous également de résoudre le conflit entre votre remotes.origin.mirror et remotes.origin.fetch sinon vous risquez de rencontrer à nouveau ce problème (ou de bloquer involontairement des commits poussés depuis d'autres dépôts).

44voto

chinnawatp Points 615

deux commandes seulement ont sauvé ma vie

1. La liste de tous les HEADs précédents sera affichée

git reflog

2. Cela va rétablir le HEAD en commit que vous avez supprimé.

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02

4 votes

Je n'ai jamais vérifié la branche localement, donc mon HEAD n'a jamais été là, donc je ne peux pas trouver l'ID de commit avec git reflog . Y a-t-il autre chose que je puisse essayer ?

3 votes

Même chose que @zyy Le commit a été supprimé par un autre membre de l'équipe à distance, je dois donc le récupérer sur ma machine locale (je n'ai jamais eu ce commit localement) et le repousser...

28voto

JackChouMine Points 462
  1. trouver l'identifiant de l'engagement

    git reflog

  2. récupérer la branche locale que vous avez supprimée par erreur

    git branch <NEED-RECOVER-BRANCH-NAME> commitId

  3. pousser need-recover-branch-name à nouveau si vous avez supprimé la branche distante avant

    git push origin <NEED-RECOVER-BRANCH-NAME>

2 votes

Cela a fonctionné pour moi. Je préfère la réponse acceptée car il y avait beaucoup moins d'étapes. J'ai pu voir mon message de validation à partir de git reflog plutôt que de devoir deviner et git show .

0 votes

Cela m'a permis d'économiser 5 jours de travail non-stop pendant 13 heures. Merci beaucoup. J'ai juste par erreur supprimé ma branche locale et distante mais j'ai pu la récupérer avec ceci

15voto

Chris Johnsen Points 50064

Vos branches supprimées ne sont pas perdues, elles ont été copiées dans le fichier origine/contact_page et origine/new_pictures "branches de suivi distantes" par le fetch que vous avez montré (elles ont également été repoussées par le push que vous avez montré, mais elles ont été poussées dans refs/remotes/origin/ au lieu de refs/heads/). Vérifiez git log origin/contact_page et git log origin/new_pictures pour voir si vos copies locales sont "à jour" avec ce que vous pensez devoir y être. Si de nouveaux commits ont été poussés sur ces branches (depuis un autre repo) entre le fetch et le push que vous avez montrés, vous pouvez les avoir "perdus" (mais vous pourriez probablement les retrouver dans l'autre repo qui a poussé ces branches le plus récemment).

Conflit entre la recherche et la poussée

Il semble que vous récupérez les données en "mode distant" normal (les refs/heads/ distants sont stockés localement dans refs/remotes/origin/), mais que vous poussez en "mode miroir" (les refs/ locaux sont poussés sur les refs/ distants). Vérifiez votre .git/config et réconciliez les paramètres suivants remote.origin.fetch et remote.origin.push paramètres.

Faire une sauvegarde

Avant d'essayer tout changement, faites une simple archive tar ou zip de votre repo local entier. De cette façon, si vous n'aimez pas ce qui se passe, vous pouvez réessayer à partir d'un repo restauré.

Option A : Reconfigurer comme un miroir

Si vous avez l'intention d'utiliser votre repo distant comme un miroir de votre repo local, faites ceci :

git branch contact_page origin/contact_page &&
git branch new_pictures origin/new_pictures &&
git config remote.origin.fetch '+refs/*:refs/*' &&
git config --unset remote.origin.push &&
git config remote.origin.mirror true

Vous pourriez aussi éventuellement vouloir supprimer toutes vos refs/remotes/origin/ refs, puisqu'elles ne sont pas utiles si vous opérez en mode miroir (vos branches normales prennent la place des branches habituelles de suivi à distance).

Option B : Reconfigurer comme une télécommande normale

Mais comme il semble que vous utilisez ce dépôt distant avec plusieurs dépôts "de travail", vous ne voulez probablement pas utiliser le mode miroir. Vous pouvez essayer ceci :

git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror

Ensuite, vous voudrez éventuellement supprimer les faux refs/remotes/origin refs dans votre repo distant : git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures … .

Test Push

Essayez git push --dry-run pour voir ce qu'il git push sans qu'il ait à effectuer des modifications sur le dépôt distant. Si vous n'aimez pas ce qu'il dit qu'il va faire, récupérez à partir de votre sauvegarde (tar/zip) et essayez l'autre option.

1 votes

Je ne pense pas que les branches de suivi à distance aient été conservées, si tant est qu'elles aient été copiées. 'git branch -a' ne les montre pas, et je ne trouve pas non plus de fichiers avec ces noms dans le répertoire .git. Enfin, les commandes "git log" que vous avez recommandées renvoient "fatal : ambiguous argument 'origin/contact_page' : unknown revision or path not in the working tree" :-\ Merci quand même.

1 votes

Eh bien, ces branches étaient là, votre journal de poussée le montre. En cherchant les refs dans le .git dir, assurez-vous de vérifier .git/packed_refs en plus de .git/refs/ . git show-ref va vider tous vos refs locaux (emballés ou 'loose'). Vous devriez toujours être en mesure de trouver les références dans le repo qui les a poussées à l'origine vers votre repo GitHub (sur une machine différente ? le repo de quelqu'un d'autre ?). Si ce n'est pas le cas, tant que vous n'avez pas effectué de gc ou de prune, vous devriez être en mesure de trouver les références dans le repo GitHub. git fsck pour examiner les commits pendants et les rattacher : git branch contact_page-recovered <SHA-1-of-dangling-commit> .

0 votes

Packed_refs ne l'avait pas non plus. Les commits étaient définitivement en suspens ; je ne sais pas comment c'est arrivé. Merci pour votre aide !

14voto

Timmy Points 188

Si l'effacement est assez récent (comme un moment Oh-NO !), vous devriez avoir un message :

Deleted branch <branch name> (was abcdefghi).

tu peux toujours courir :

git checkout abcdefghi

git checkout -b <some new branch name or the old one>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X