Restablecimiento completo de un solo archivo

1006

Actualmente tengo tres archivos modificados en mi directorio de trabajo. Sin embargo, quiero que uno de ellos se restablezca al estado HEAD.

En SVN, usaría svn revert <filename>(seguido de svn update <filename>si fuera necesario) pero en Git debería usar git reset --hard. Sin embargo, este comando no puede funcionar en un solo archivo.

¿Hay alguna forma en Git para descartar los cambios en un solo archivo y sobrescribirlo con una nueva copia HEAD?

Emiliano
fuente
3
git checkouta continuación está la respuesta. En git, "revertir" es algo que le haces a un commit. "Revertir" reproduce el inverso de una confirmación histórica en su directorio de trabajo, para que pueda hacer una nueva confirmación que "deshaga" la confirmación revertida. Creo que este es un punto frecuente de confusión para las personas que vienen a git desde svn.
Dan Ray
Si le interesa por qué no puede hacer un restablecimiento completo con rutas, consulte mi respuesta allí .
usuario
Esta pregunta supone que uno sabe qué es un restablecimiento completo.

Respuestas:

1811

Puede usar el siguiente comando:

git checkout HEAD -- my-file.txt

... que actualizará tanto la copia de trabajo my-file.txtcomo su estado en el índice con la de HEAD.

--básicamente significa: tratar cada argumento después de este punto como un nombre de archivo . Más detalles en esta respuesta . Gracias a VonC por señalar esto.

Mark Longair
fuente
58
Respuesta más completa. +1;) Para el '-', vea también stackoverflow.com/questions/6561142/… (y, más generalmente, stackoverflow.com/questions/1192180/… )
VonC
8
Además, no olvide que puede hacer referencia a un commit anterior HEAD~1para indicar el penúltimo commit.
Ryanmt
14
Puede dejar de lado HEADsi está a la cabeza de la rama actual - vea norbauer.com/rails-consulting/notes/…
cxw
44
¿Alguna idea de por qué el resetcomando (como se dice) "no puede hacer un restablecimiento checkoutcompleto con rutas", y luego por qué el comando no se usa (no se puede?) Para restablecer todo el conjunto? (Me refiero a por qué se ha diseñado así.)
Sz.
1
@cxw Desafortunadamente, esto no es del todo cierto. Desde la página de manual de git checkout: "Sobrescribir rutas en el árbol de trabajo reemplazándolas por los contenidos en el índice o en el <tree-ish>". Es decir, si <tree-ish>se omite, cualquier contenido en el índice se utilizará para actualizar el árbol de trabajo. Esto puede o no diferir de HEAD.
tuntap
137

Restablecer a la cabeza:

Para restablecer un solo archivo a HEAD:

git checkout @ -- myfile.ext

Tenga en cuenta que @es la abreviatura de HEAD. Una versión anterior de git puede no admitir la forma corta.

Restablecer al índice:

Para restablecer un solo archivo al índice , suponiendo que el índice no esté vacío, de lo contrario a HEAD:

git checkout -- myfile.ext

El punto es que, para estar seguro, no desea omitir el comando @o no hacerlo, a HEADmenos que solo quiera restablecer el índice .

Acumenus
fuente
1
¿Qué pasa con el "-" antes de myfile.ext?
Lance Kind
3
@LanceKind Según tengo entendido, se usa para demarcar una lista de nombres de archivo que le sigue. Sin él, hay casos en los que git interpreta los argumentos incorrectamente.
Acumenus
2
No solo nombres de archivos. La convención ampliamente utilizada separa las opciones de los argumentos posicionales en muchas utilidades. Ver man bashpágina También se menciona en esta respuesta: unix.stackexchange.com/a/187548/142855
boweeb
1
Convencionalmente, --se usa para decirle al programa I've finished specifying "options", and from here on, everything will be a positional argument.. Convencionalmente, las "opciones" son los tokens como los --recursiveque pueden aparecer en cualquier orden, o incluso combinarse en su forma abreviada, como con rm -rf. Por el contrario, los "argumentos posicionales" se parecen mucho más a los argumentos pasados ​​a una función en un lenguaje de programación: su posición en la lista de tokens define qué hará exactamente el programa con ellos (a menudo son nombres de archivos). --elimina la ambigüedad de cuál es cuál.
iono
42

Para volver a upstream / master do:

git checkout upstream/master -- myfile.txt
Ann Raiho
fuente
19

Desde Git 2.23 (agosto de 2019) puede usar restore( más información ):

git restore pathTo/MyFile

Lo anterior se restaurará MyFileel HEAD(la última confirmación) en la rama actual.

Si desea obtener los cambios de otra confirmación, puede retroceder en el historial de confirmación. El siguiente comando obtendrá MyFiledos confirmaciones anteriores a la última. Ahora necesita la opción -s( --source) ya que ahora usa master~2y no master(el predeterminado) a medida que restaura la fuente:

git restore -s master~2 pathTo/MyFile

¡También puede obtener el archivo de otra sucursal!

git restore -s my-feature-branch pathTo/MyFile
AxeEffect
fuente
1
La forma más fácil hasta ahora. Lamentablemente, esta respuesta no está recibiendo suficiente atención.
Singrium
5

La referencia a HEAD no es necesaria.

git checkout -- file.js es suficiente

Emanuel Friedrich
fuente
4

puede usar el siguiente comando para restablecer un solo archivo

git checkout HEAD -- path_to_file/file_name

Lista todos los archivos modificados para obtener path_to_file/filenamecon el siguiente comando

git status
HariKishore
fuente
1

Puede usar el siguiente comando:

git reset -- my-file.txt

que actualizará tanto la copia de trabajo de my-file.txtcuando se agrega.

ADDYQU
fuente
No cambia el contenido del archivo modificado, según lo solicitado.
Rafael
Cuando agrega a la reserva ¿Editó el archivo?
ADDYQU
1
Ese no es específicamente el punto @ADDQU. La pregunta es cómo "restablecer por completo" un archivo, no eliminarlo de la lista por etapas.
Rafael
@Rafael Tienes razón, pero quiero hacerte saber que también hay una manera.
ADDYQU
0

Puede usar el siguiente comando:

git checkout filename

Si tiene una rama con el mismo nombre de archivo, debe usar este comando:

git checkout -- filename
Milad Rahimi
fuente
1
Esto no "restablecerá por completo" el archivo, solo copia el estado del índice en el árbol de trabajo. Un "restablecimiento completo" primero restablecería el índice.
AH
-21

Una manera simple, fácil y práctica de sacarte del agua caliente, especialmente si no estás tan cómodo con git:

  1. Ver el registro de su archivo

    git log myFile.js

    commit 1023057173029091u23f01w276931f7f42595f84f Autor: kmiklas Fecha: martes 7 de agosto 09:29:34 2018 -0400

    JIRA-12345 - Refactor con nueva arquitectura.

  2. Nota hash de archivo:

    1023057173029091u23f01w276931f7f42595f84f

  3. Mostrar el archivo usando el hash. Asegúrate de que sea lo que quieres:

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js

  4. Redirigir archivo a una copia local

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js> myFile.07aug2018.js

  5. Haga una copia de seguridad de su archivo actual.

    cp myFile.js myFile.bak.js

  6. Abra ambos archivos en su editor de texto favorito.

    vim myFile.js
    vim myFile.07aug2018.js

  7. Copie y pegue el código de myFile.07aug2018.js en myFile.js y guárdelo.

  8. Comprometerse y empujar myFile.js

  9. Vuelva a ver el registro y confirme que su archivo esté correctamente en su lugar.

  10. Dígale a sus clientes que tomen lo último, felizmente véanlo funcionar con la versión anterior en su lugar.

No es la solución más sexy o más centrada en git, y definitivamente un reinicio / reversión "manual", pero funciona. Requiere un conocimiento mínimo de git y no perturba el historial de confirmaciones.

kmiklas
fuente
2
Esta respuesta es mucho más compleja y propensa a errores que cualquiera de las soluciones anteriores a años.
Artif3x
2
¿Por qué alguien debería usar esta solución? La verdadera respuesta es solo un simple comando.
Milad Rahimi
1
Esta es la solución óptima para ciertas circunstancias. Tiene mérito para aquellos en apuros, donde git no funciona correctamente, y para aquellos que necesitan una solución.
kmiklas