Estoy intentando recuperar mi trabajo. Estúpidamente lo hice git reset --hard
, pero antes de eso solo get add .
hice y no hice git commit
. ¡Por favor ayuda! Aquí está mi registro:
MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: .gitignore
...
MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api
¿Es posible deshacer git reset --hard
en esta situación?
Respuestas:
Debería poder recuperar cualquier archivo que haya agregado al índice (por ejemplo, como en su situación, con
git add .
), aunque puede ser un poco complicado. Para agregar un archivo al índice, git lo agrega a la base de datos del objeto, lo que significa que se puede recuperar siempre que no se haya realizado la recolección de basura. Hay un ejemplo de cómo hacer esto en la respuesta de Jakub Narębski aquí:Sin embargo, probé eso en un repositorio de prueba y hubo un par de problemas,
--cached
debería ser--cache
, y descubrí que en realidad no creaba el.git/lost-found
directorio. Sin embargo, los siguientes pasos funcionaron para mí:Eso debería generar todos los objetos en la base de datos de objetos que no son accesibles por ninguna referencia, en el índice o mediante el reflog. La salida se verá así:
... y para cada una de esas manchas, puede hacer:
Para generar el contenido del archivo.
¿Demasiada producción?
Actualización en respuesta al comentario de sehe a continuación:
Si encuentra que tiene muchas confirmaciones y árboles enumerados en la salida de ese comando, es posible que desee eliminar de la salida todos los objetos a los que se hace referencia de las confirmaciones no referenciadas. (Por lo general, puede volver a estas confirmaciones a través del reflog de todos modos; solo nos interesan los objetos que se han agregado al índice pero que nunca se pueden encontrar a través de una confirmación).
Primero, guarde la salida del comando, con:
Ahora los nombres de objeto de esas confirmaciones inalcanzables se pueden encontrar con:
De modo que puede encontrar solo los árboles y objetos que se han agregado al índice, pero que no se han confirmado en ningún momento, con:
Eso reduce enormemente la cantidad de objetos que tendrá que considerar.
Actualización: Philip Oakley a continuación sugiere otra forma de reducir la cantidad de objetos a considerar, que es simplemente considerar los archivos modificados más recientemente
.git/objects
. Puede encontrar estos con:(Encontré esa
find
invocación aquí ). El final de esa lista podría verse así:En cuyo caso puede ver esos objetos con:
(Tenga en cuenta que debe eliminar el
/
al final de la ruta para obtener el nombre del objeto).fuente
Acabo de hacer un
git reset --hard
compromiso y perdí uno. Pero conocía el hash de confirmación, así que pudegit cherry-pick COMMIT_HASH
restaurarlo.Hice esto a los pocos minutos de perder el compromiso, por lo que puede funcionar para algunos de ustedes.
fuente
git reflog
, por ejemplo,git reset --hard
->git reflog
(mirando el hash HEAD @ {1}) y finalmentegit cherry-pick COMMIT_HASH
git reset --hard
(suponiendo que no haya hecho nada más después de ese comando) esgit reset --hard @{1}
¡Gracias a Mark Longair recuperé mis cosas!
Primero guardé todos los hashes en un archivo:
a continuación, los puse todos (eliminando el 'blob inalcanzable') en una lista y puse todos los datos en archivos nuevos ... tienes que elegir tus archivos y cambiarles el nombre de nuevo, lo que necesitas ... pero solo necesitaba unos pocos archivos ... espero que esto ayude a alguien ...
fuente
mkdir lost; git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") | grep -Po '\s\S{40}$' | xargs -i echo "git show {} > lost/{}.blob" | sh
. Los archivos terminarán enlost/*.blob
La solución de @ Ajedi32 en los comentarios funcionó para mí exactamente en esta situación.
Tenga en cuenta que todas estas soluciones se basan en que no hay git gc, y algunas de ellas pueden causar una, por lo que comprimiría el contenido de su directorio .git antes de intentar algo para que tenga una instantánea a la que volver si no hay una. no funciona para ti.
fuente
git reset --hard
, que estropeó mi repositorio de una manera desconocida. @Duncan, ¿qué hace @ {1}? y a que comentario te refieres? ¿Está reseteando ungit reset
?Me encontré con el mismo problema, pero no había agregado los cambios al índice. Entonces, todos los comandos anteriores no me devolvieron los cambios deseados.
Después de todas las respuestas elaboradas anteriores, esta es una pista ingenua, pero puede ser que salve a alguien que no lo pensó primero, como lo hice yo.
Desesperado, intenté presionar CTRL-Z en mi editor (LightTable), una vez en cada pestaña abierta; afortunadamente, esto recuperó el archivo en esa pestaña, a su último estado antes del
git reset --hard
. HTH.fuente
Esto probablemente sea obvio para los profesionales de git, pero quería publicarlo ya que en mi búsqueda frenética no vi que esto surgiera.
Puse en escena algunos archivos, e hice una
git reset --hard
, me asusté un poco, y luego noté que mi estado mostraba que todos mis archivos aún estaban organizados, así como todas sus eliminaciones sin configurar.En este punto, puede confirmar esos cambios por etapas, siempre que no organice sus eliminaciones. Después de esto, solo tienes que reunir el coraje para hacerlo
git reset --hard
una vez más, lo que te devolverá a esos cambios que habías realizado y que ahora acabas de cometer.Nuevamente, esto probablemente no sea nada nuevo para la mayoría, pero espero que, dado que me ayudó y no encontré nada que sugiriera esto, pueda ayudar a otra persona.
fuente
Dios mío, me tiré del pelo hasta que me encontré con esta pregunta y sus respuestas. Creo que la respuesta correcta y concisa a la pregunta formulada solo está disponible si reúne dos de los comentarios anteriores, así que aquí está todo en un solo lugar:
Como lo menciona chilicuil, ejecute
git reflog
para identificar allí el hash de confirmación al que desea volverComo lo mencionó akimsko, es probable que NO desee seleccionar con precisión a menos que solo haya perdido una confirmación, por lo que debe ejecutar
git reset --hard <hash-commit-you-want>
Nota para los usuarios de egit Eclipse: no pude encontrar una manera de realizar estos pasos dentro de Eclipse con egit. Cerrar Eclipse, ejecutar los comandos anteriores desde una ventana de terminal y luego volver a abrir Eclipse funcionó bien para mí.
fuente
Las soluciones anteriores pueden funcionar, sin embargo, hay formas más simples de recuperarse de esto en lugar de pasar por el
git
complejo deshacer. Supongo que la mayoría de los restablecimientos de git ocurren en una pequeña cantidad de archivos, y si ya usa VIM, esta podría ser la solución más eficiente en el tiempo. La advertencia es que ya debe estar usandoViM's
persistent-undo, que debería usar de cualquier manera, porque le brinda la capacidad de deshacer un número ilimitado de cambios.Estos son los pasos:
En vim presione
:
y escriba el comandoset undodir
. Si hapersistent undo
activado en su.vimrc
, mostrará un resultado similar aundodir=~/.vim_runtime/temp_dirs/undodir
.En su repositorio, use
git log
para averiguar la última fecha / hora en que realizó la última confirmaciónEn su caparazón, navegue hasta su
undodir
usocd ~/.vim_runtime/temp_dirs/undodir
.En este directorio, use este comando para encontrar todos los archivos que ha cambiado desde la última confirmación
find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"
Aquí "2018-03-20 11:24:44" es la fecha y hora de la última confirmación. Si la fecha en la que lo hizo
git reset --hard
es "2018-03-22", use "2018-03-22", luego use "2018-03-23". Esto se debe a una peculiaridad de la búsqueda, donde el límite inferior es inclusivo y el límite superior es exclusivo. https://unix.stackexchange.com/a/70404/242983A continuación, vaya a cada uno de los archivos, ábralos en vim y haga un "20m anterior". Puede encontrar más detalles sobre "anterior" utilizando "h anterior". Aquí
earlier 20m
significa volver al estado del archivo 20 minutos atrás, asumiendo que lo hizogit hard --reset
, 20 minutos atrás. Repita esto con todos los archivos que se escupieron desde elfind
comando. Estoy seguro de que alguien puede escribir un guión que combine estas cosas.fuente
Estoy usando IntelliJ y pude simplemente revisar cada archivo y hacer:
Edit -> reload from disk
Afortunadamente, acababa de hacer lo
git status
correcto antes de borrar mis cambios de trabajo, así que sabía exactamente lo que tenía que recargar.fuente
Recordar la jerarquía de archivos y utilizar la técnica de Mark Longair con la modificación de Phil Oakley produce resultados espectaculares.
Básicamente, si al menos agregó los archivos al repositorio pero no los comprometió, puede restaurar utilizando interactivamente
git show
, inspeccionar el registro y usar la redirección de shell para crear cada archivo (recordando su ruta de interés).HTH!
fuente
Si ha revisado recientemente un,
git diff
entonces hay otra forma de recuperarse de incidentes como este, incluso cuando aún no haya realizado los cambios: si el resultado degit diff
todavía está en el búfer de la consola, puede desplazarse hacia arriba, copiar y pegar el diff en un archivo y utilizar lapatch
herramienta para aplicar el diff a su árbol:patch -p0 < file
. Este enfoque me salvó algunas veces.fuente