Git: recuperar rama eliminada (remota)

94

Necesito recuperar dos ramas de Git que de alguna manera eliminé durante un envío.

Estas dos ramas se crearon en un sistema diferente y luego se enviaron a mi repositorio "compartido" (github).

En mi sistema, (aparentemente) recuperé las ramas durante una búsqueda:

~/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

Inmediatamente después de eso, hice un empujón para enviar mis cambios locales al repositorio central. Por alguna razón, estas ramas se eliminaron tanto de mi sistema local como del repositorio 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 [email protected]: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

No es muy fácil sacar las ramas de la máquina de su lugar de nacimiento, así que me gustaría intentar recuperarlas de mi local si es posible.

Toda la información de "deshacer" de git que he buscado en Google tiene que ver con la recuperación de confirmaciones perdidas. No creo que eso se aplique aquí, ya que no tengo UID de confirmación para estas ramas.

Me gustaría saber cómo puedo recuperarlos. También me gustaría saber cómo se eliminaron en primer lugar y cómo puedo evitarlo en el futuro.

EDITAR: por solicitud, aquí está mi configuración de repositorio

user.name=Craig Walker
[email protected]
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/*
[email protected]: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
Craig Walker
fuente
Parece que tiene una configuración de extracción y envío "inusual" o no coincidente. ¿Qué git config -lmuestra el repositorio local?
CB Bailey
Muy posiblemente; Lo he publicado.
Craig Walker
2
Su remote.origin.fetchrefspec no es apropiada para su uso con remote.origin.mirror = true. ¿Quieres duplicar o quieres usar el repositorio de GitHub como un control remoto normal? Mi respuesta debería tener los comandos que necesita de cualquier manera.
Chris Johnsen
Supongo que con el segundo repositorio, la duplicación ya no es una opción (esto probablemente causó la eliminación en primer lugar).
Craig Walker

Respuestas:

103

No soy un experto Pero puedes intentar

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

para encontrar la confirmación HEAD de la rama eliminada y recuperarla.

iamamac
fuente
Intenté fsck antes; ¿Sabes cómo averiguar cuál es la confirmación correcta? Tengo 20 para probar.
Craig Walker
1
Esto lo hizo; una vez que tuve los mensajes de confirmación, git branch <uid>los recuperé. ¡Gracias!
Craig Walker
Es bueno escuchar. Asegúrese de resolver también el conflicto entre su configuración remotes.origin.mirrory remotes.origin.fetch, de lo contrario, es probable que vuelva a encontrarse con el problema (o involuntariamente chobber confirmaciones empujadas desde otros repositorios).
Chris Johnsen
@Craig: Me alegro de ser útil :)
iamamac
3
Hoy perdí una rama candidata a la liberación. No conocía el ID de confirmación. Lo recuperé usando:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
spezifanta
23

solo dos comandos salvan mi vida

1. Esto mostrará una lista de todos los HEAD anteriores.

git reflog

2. Esto revertirá el HEAD para confirmar que eliminó.

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02
chinnawatp
fuente
1
Nunca me registré en la sucursal localmente, por lo que mi HEAD nunca ha estado allí, por lo tanto, no puedo encontrar el ID de confirmación con git reflog. ¿Hay algo más que pueda probar?
zyy
1
Igual que @zyy La confirmación ha sido eliminada por otro miembro del equipo en forma remota, así que tengo que recuperarla en mi máquina local (nunca tuve esa confirmación localmente) y retroceder ...
OmGanesh
11

Sus ramas eliminadas no se pierden, se copiaron en origin / contact_page y origin / new_pictures "ramas de seguimiento remoto" por la búsqueda que mostró (también fueron expulsadas por el empuje que mostró, pero fueron enviadas a refs / remotes / origin / en lugar de refs / heads /). Verifique git log origin/contact_pagey git log origin/new_picturesvea si sus copias locales están “actualizadas” con lo que crea que debería estar allí. Si se enviaron nuevas confirmaciones a esas ramas (desde algún otro repositorio) entre la búsqueda y la inserción que mostró, es posible que las haya "perdido" (pero probablemente podría encontrarlas en el otro repositorio que más recientemente empujó esas ramas) .

Conflicto de búsqueda / empuje

Parece que está obteniendo en un 'modo remoto' normal (las referencias / cabezas remotas / se almacenan localmente en refs / remotes / origin /), pero presionando en 'modo espejo' (las referencias locales / se envían a las referencias remotas /) . Verifique su .git / config y concilie la configuración de remote.origin.fetchy remote.origin.push.

Hacer una copia de seguridad

Antes de intentar cualquier cambio, cree un archivo tar o zip simple o todo su repositorio local. De esa manera, si no le gusta lo que sucede, puede volver a intentarlo desde un repositorio restaurado.

Opción A: reconfigurar como espejo

Si tiene la intención de usar su repositorio remoto como un espejo del local, haga esto:

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

Es posible que también desee eliminar todas sus referencias / remotos / origen / referencias, ya que no son útiles si está operando en modo espejo (sus ramas normales toman el lugar de las ramas de seguimiento remoto habituales).

Opción B: reconfigurar como un control remoto normal

Pero como parece que está utilizando este repositorio remoto con varios repositorios de "trabajo", probablemente no desee utilizar el modo espejo. Puede intentar esto:

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

Entonces, es muy probable que desee eliminar los falsos refs / mandos a distancia / árbitros de origen en tu repositorio remoto: git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures ….

Prueba de empuje

Intente git push --dry-runver qué git pushharía sin tener que realizar ningún cambio en el repositorio remoto. Si no le gusta lo que dice que va a hacer, recupérese de su copia de seguridad (tar / zip) y pruebe la otra opción.

Chris Johnsen
fuente
1
No creo que se mantuvieran las ramas de seguimiento remoto, si es que se copiaron. 'git branch -a' no los muestra, y tampoco puedo encontrar ningún archivo con esos nombres en el directorio .git. Por último, los comandos "git log" que recomendó devuelven "fatal: argumento ambiguo 'origin / contact_page': revisión desconocida o ruta que no está en el árbol de trabajo": - \ Gracias.
Craig Walker
1
Bueno, esas ramas estaban allí, su registro de empuje lo muestra. Cuando busque referencias en el .gitdirectorio, asegúrese de verificar .git/packed_refsademás de .git/refs/. git show-refarrojará todas sus referencias locales (empaquetadas o 'sueltas'). Aún debería poder encontrar las referencias en el repositorio que originalmente las envió a su repositorio de GitHub (¿en una máquina diferente? ¿En el repositorio de otra persona?). De no ser así, siempre y cuando no lo ha hecho un GC o ciruela, usted debe poder a la git fscksalida de examinar las confirmaciones colgando y vuelva a ellos: git branch contact_page-recovered <SHA-1-of-dangling-commit>.
Chris Johnsen
pack_refs tampoco lo tenía. Las confirmaciones definitivamente estaban colgando; no tengo idea de cómo sucedió eso. ¡Gracias por tu ayuda!
Craig Walker
8

Si la eliminación es lo suficientemente reciente (como un momento ¡Oh-NO!), Aún debería tener un mensaje:

Deleted branch <branch name> (was abcdefghi).

todavía puedes ejecutar:

git checkout abcdefghi

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

Timmy
fuente
8
  1. averiguar el id de coimmit

    git reflog

  2. recuperar la rama local que eliminó por error

    git branch need-recover-branch-name commitId

  3. presione need-recovery-branch-name nuevamente si eliminó la rama remota también antes

    git push origin need-recover-branch-name

JackChouMine
fuente
2
Esto funcionó para mí. Prefiero la respuesta aceptada porque fueron muchos menos pasos. Pude ver mi mensaje de confirmación git reflog, en lugar de tener que adivinar y git show.
theUtherSide
3

Los datos aún existen en github, puede crear una nueva rama a partir de los datos antiguos:

git checkout origin/BranchName #get a readonly pointer to the old branch
git checkout –b BranchName #create a new branch from the old
git push origin BranchName #publish the new branch
jhilden
fuente
1

Creo que tiene una configuración no coincidente para 'buscar' y 'empujar', por lo que esto ha provocado que la búsqueda / empuje predeterminado no se realice correctamente. Afortunadamente, ha obtenido las ramas que posteriormente eliminó, por lo que debería poder volver a crearlas con un empujón explícito.

git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures
CB Bailey
fuente
Al igual que con mi comentario a @Chris Johnson, parece que las sucursales ya no existen (¿nunca?) Localmente. Cuando git push origin origin/contact_page:contact_pagerecibo esto: error: src refspec origin/contact_page does not match any
Craig Walker
Bien, creo que veo lo que sucedió (aunque el error completo sería útil). push ha actualizado la rama eliminada y eliminado la referencia localmente, así como también es una referencia de seguimiento. ¿Qué git rev-parse refs/remotes/origin/origin/contact_pagedice? Debido a la configuración falsa de 'espejo', la rama ahora puede ser referenciada aquí en el repositorio local.
CB Bailey
Hola Charles; Desde que escribí esto, modifiqué (y arreglé) mi configuración, por lo que ya no puedo obtener la salida (significativa) de análisis de revoluciones. Sin embargo, no creo que hubiera un directorio de "origen" doble anidado en los controles remotos.
Craig Walker
0

Si su organización usa JIRA u otro sistema similar que esté vinculado a git, puede encontrar las confirmaciones enumeradas en el ticket y hacer clic en los enlaces a los cambios de código. Github elimina la rama, pero aún tiene las confirmaciones disponibles para seleccionar.

Roralee
fuente
-1

Puede parecer demasiado cauteloso, pero con frecuencia comprimo una copia de lo que he estado trabajando antes de realizar cambios en el control de código fuente. En un proyecto de Gitlab en el que estoy trabajando, recientemente eliminé por error una rama remota que quería conservar después de fusionar una solicitud de combinación. Resulta que todo lo que tuve que hacer para recuperarlo con el historial de confirmaciones fue presionar nuevamente. Gitlab siguió rastreando la solicitud de combinación, por lo que todavía muestra la etiqueta azul 'combinada' a la derecha de la rama. Todavía comprimí mi carpeta local en caso de que sucediera algo malo.

Artorias2718
fuente