tab - Deshacer la restauración de git: difícil con archivos no confirmados en el área de ensayo
git tag commits (7)
Estoy tratando de recuperar mi trabajo. git reset --hard
, pero antes de eso solo he hecho get add .
y no hizo 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 el git reset --hard
en esta situación?
¡Gracias a Mark Longair recuperé mis cosas!
Primero guardé todos los hashes en un archivo:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > allhashes
A continuación los coloco a todos (quitando la cosa ''blob inalcanzable'') en una lista y pongo todos los datos en archivos nuevos ... tienes que elegir tus archivos y cambiarles el nombre nuevamente lo que necesitas ... pero solo necesitaba unos pocos archivos ... espero que esto ayude a alguien ...
commits = ["c2520e04839c05505ef17f985a49ffd42809f",
"41901be74651829d97f29934f190055ae4e93",
"50f078c937f07b508a1a73d3566a822927a57",
"51077d43a3ed6333c8a3616412c9b3b0fb6d4",
"56e290dc0aaa20e64702357b340d397213cb",
"5b731d988cfb24500842ec5df84d3e1950c87",
"9c438e09cf759bf84e109a2f0c18520",
...
]
from subprocess import call
filename = "file"
i = 1
for c in commits:
f = open(filename + str(i),"wb")
call(["git", "show", c],stdout=f)
i+=1
Acabo de hacer un reinicio de git --hard y perdí un commit. Pero conocía el hash de confirmación, así que pude hacer git, seleccionar manualmente COMMIT_HASH para restaurarlo.
Lo hice a los pocos minutos de perder el compromiso, por lo que podría funcionar para algunos de ustedes.
Debería poder recuperar cualquier archivo que haya agregado al índice (por ejemplo, como en su situación, con git add .
) Aunque podría ser un poco laborioso. Para agregar un archivo al índice, git lo agrega a la base de datos de objetos, lo que significa que puede recuperarse siempre que la recolección de basura no se haya realizado todavía. Hay un ejemplo de cómo hacer esto dado en la respuesta de Jakub Narębski aquí:
Sin embargo, lo probé en un repositorio de pruebas, y hubo un par de problemas: --cached
debería ser --cache
, y descubrí que realmente no creaba el .git/lost-found
. Sin embargo, los siguientes pasos me funcionaron:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")
Eso debería dar salida a todos los objetos en la base de datos de objetos que no son alcanzables por ninguna referencia, en el índice o mediante el reflog. La salida se verá algo como esto:
unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03
... y para cada uno de esos blobs, puedes hacer:
git show 907b308
Para dar salida al contenido del archivo.
Demasiada producción?
Actualización en respuesta al comentario de sehe continuación:
Si encuentra que tiene muchos commits y árboles enumerados en el resultado de ese comando, puede eliminar de la salida cualquier objeto al que se haga referencia desde confirmaciones sin referencia. (Por lo general, puedes volver a estos commits 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 un commit).
Primero, guarde la salida del comando, con:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > all
Ahora los nombres de objeto de esas confirmaciones inalcanzables se pueden encontrar con:
egrep commit all | cut -d '' '' -f 3
Para que pueda encontrar solo los árboles y objetos que se han agregado al índice, pero que no se han comprometido en ningún momento, con:
git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") /
$(egrep commit all | cut -d '' '' -f 3)
Eso reduce enormemente la cantidad de objetos que tendrá que considerar.
Actualización: Philip Oakley a continuación sugiere otra forma de reducir el número de objetos a considerar, que es solo considerar los archivos modificados más recientemente en .git/objects
. Puedes encontrar estos con:
find .git/objects/ -type f -printf ''%TY-%Tm-%Td %TT %p/n'' | sort
(Encontré que find
invocación here .) El final de esa lista podría verse así:
2011-08-22 11:43:43.0234896770 .git/objects/b2/1700b09c0bc0fc848f67dd751a9e4ea5b4133b
2011-09-13 07:36:37.5868133260 .git/objects/de/629830603289ef159268f443da79968360913a
En ese caso, puedes ver esos objetos con:
git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b
git show de629830603289ef159268f443da79968360913a
(Tenga en cuenta que debe eliminar /
al final de la ruta para obtener el nombre del objeto).
Dios, tiré de mi cabello hasta que me encontré con esta pregunta y sus respuestas. Creo que la respuesta correcta y concisa a la pregunta solo está disponible si reúne dos de los comentarios anteriores, por lo que aquí todo está en un solo lugar:
Como lo menciona chilicuil, ejecute ''git reflog'' para identificar allí el hash de confirmación al que desea volver.
Como lo mencionó akimsko, probablemente NO quieras elegir a menos que solo pierdas una confirmación, entonces deberías ejecutar ''git reset --hard
Nota para los usuarios de egit Eclipse: No pude encontrar la manera de hacer estos pasos dentro de Eclipse con egit. Cerrar Eclipse, ejecutar los comandos de arriba desde una ventana de terminal y luego volver a abrir Eclipse funcionó bien para mí.
La solución de @ Ajedi32 en los comentarios me funcionó exactamente en esta situación.
git reset --hard @{1}
Tenga en cuenta que todas estas soluciones se basan en que no hay git gc, y algunas de ellas pueden causarlo, así que comprimiré el contenido de su directorio .git antes de intentar cualquier cosa para que tenga una instantánea a la que pueda volver si no lo hace no funciona para usted
Las soluciones anteriores pueden funcionar, sin embargo, hay formas más simples de recuperarse de esto en lugar de pasar por el proceso de deshacer de git
-s. Supongo que la mayoría de los git-resets ocurren en una pequeña cantidad de archivos, y si ya usas VIM, esta podría ser la solución más eficiente en tiempo. La advertencia es que ya debe usar ViM''s
deshacer persistente ViM''s
, que debería usar de cualquier manera, porque le ofrece la posibilidad de deshacer un número ilimitado de cambios.
Estos son los pasos:
En vim, presione
:
y escriba el comandoset undodir
. Si tiene activadopersistent undo
en su.vimrc
, se mostrará un resultado similar aundodir=~/.vim_runtime/temp_dirs/undodir
.En su repositorio, use el
git log
para averiguar la última fecha / hora en que realizó la última confirmación.En su caparazón navegue a su
undodir
usandocd ~/.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 hizo el
git reset --hard
es "2018-03-22", luego use "2018-03-22", luego use "2018-03-23". Esto se debe a una peculiaridad del hallazgo, donde el límite inferior es inclusivo y el límite superior es exclusivo. https://unix.stackexchange.com/a/70404/242983Luego ve a cada uno de los archivos, ábrelos en vim y haz una "anterior 20m". Puede encontrar más detalles sobre "anterior" al usar "h antes". Aquí,
earlier 20m
significa volver al estado del archivo 20 minutos atrás, suponiendo que hiciste elgit hard --reset
, 20 minutos atrás. Repita esto sobre todos los archivos que se escindieron del comandofind
. Estoy seguro de que alguien puede escribir un guión que combinará estas cosas.
Se encontró con el mismo problema, pero no agregó 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 sugerencia ingenua, pero puede ser que salve a alguien que no pensó en ello primero, como yo lo hice.
En mi desesperación, traté de presionar CTRL-Z en mi editor (LightTable), una vez en cada pestaña abierta, esto afortunadamente recuperó el archivo en esa pestaña, a su estado más reciente antes del git reset --hard
. HTH.