En general, git resetla función es tomar la rama actual y restablecerla para que apunte a otro lugar, y posiblemente traer el índice y el árbol de trabajo. Más concretamente, si su rama maestra (actualmente desprotegida) es así:
- A - B - C (HEAD, master)
y te das cuenta de que quieres que el maestro apunte a B, no a C, lo usarás git reset Bpara moverlo allí:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Digresión: esto es diferente de un pago. Si corrieras git checkout B, obtendrías esto:
- A - B (HEAD) - C (master)
Has terminado en un estado HEAD separado. HEAD, árbol de trabajo, indexar todas las coincidencias B, pero la rama maestra se quedó atrás en C. Si realiza una nueva confirmación Den este momento, obtendrá esto, que probablemente no sea lo que desea:
- A - B - C (master)
\
D (HEAD)
Recuerde, reset no realiza confirmaciones, solo actualiza una rama (que es un puntero a una confirmación) para apuntar a una confirmación diferente. El resto son solo detalles de lo que sucede con su índice y árbol de trabajo.
Casos de uso
Cubro muchos de los principales casos de uso git resetdentro de mis descripciones de las diversas opciones en la siguiente sección. Realmente se puede usar para una amplia variedad de cosas; El hilo común es que todos ellos implican restablecer la rama, el índice y / o el árbol de trabajo para apuntar / coincidir con una confirmación determinada.
Cosas a tener en cuenta
--hardpuede hacer que realmente pierdas el trabajo. Modifica tu árbol de trabajo.
git reset [options] commitpuede hacer que (tipo de) pierda confirmaciones. En el ejemplo de juguete anterior, perdimos el compromiso C. Todavía está en el repositorio, y puede encontrarlo mirando git reflog show HEADo git reflog show master, pero ya no es accesible desde ninguna rama.
Git elimina permanentemente tales confirmaciones después de 30 días, pero hasta entonces puede recuperar C al señalar una rama nuevamente ( git checkout C; git branch <new branch name>).
Argumentos
Parafraseando la página de manual, el uso más común es el formulario git reset [<commit>] [paths...], que restablecerá las rutas dadas a su estado desde la confirmación dada. Si no se proporcionan las rutas, se restablece todo el árbol, y si no se proporciona la confirmación, se considera HEAD (la confirmación actual). Este es un patrón común en los comandos de git (por ejemplo, checkout, diff, log, aunque la semántica exacta varía), por lo que no debería ser demasiado sorprendente.
Por ejemplo, git reset other-branch path/to/foorestablece todo en path / to / foo a su estado en otra rama, git reset -- .restablece el directorio actual a su estado en HEAD, y un simple git resetrestablece todo a su estado en HEAD.
El árbol de trabajo principal y las opciones de índice
Hay cuatro opciones principales para controlar lo que le sucede a su árbol de trabajo e índice durante el reinicio.
Recuerde, el índice es el "área de preparación" de git: es donde van las cosas cuando usted dice git adden preparación para comprometerse.
--hardhace que todo coincida con la confirmación a la que ha restablecido. Este es el más fácil de entender, probablemente. Todos sus cambios locales se ven afectados. Un uso principal es volar su trabajo pero no cambiar commits: git reset --hardsignifica git reset --hard HEAD, es decir, no cambie la rama sino que elimine todos los cambios locales. El otro es simplemente mover una rama de un lugar a otro y mantener sincronizado el árbol de índice / trabajo. Este es el que realmente puede hacerte perder el trabajo, porque modifica tu árbol de trabajo. Asegúrese de que quiere tirar el trabajo local antes de ejecutarlo reset --hard.
--mixedes el valor predeterminado, es decir, git resetsignifica git reset --mixed. Restablece el índice, pero no el árbol de trabajo. Esto significa que todos sus archivos están intactos, pero cualquier diferencia entre el commit original y el que restablece se mostrará como modificaciones locales (o archivos sin seguimiento) con el estado de git. Úselo cuando se dé cuenta de que realizó algunas confirmaciones incorrectas, pero desea conservar todo el trabajo que ha realizado para poder arreglarlo y volver a comprometerse. Para confirmar, tendrá que agregar archivos al índice nuevamente ( git add ...).
--softno toca el índice ni el árbol de trabajo. Todos sus archivos están intactos como con --mixed, pero todos los cambios se muestran como changes to be committedcon el estado de git (es decir, registrado en preparación para la confirmación). Use esto cuando se dé cuenta de que ha cometido algunos errores, pero el trabajo es bueno, todo lo que necesita hacer es volver a comprometerse de manera diferente. El índice no se ha modificado, por lo que puede confirmar de inmediato si lo desea: la confirmación resultante tendrá el mismo contenido que antes de restablecer.
--mergese agregó recientemente y está destinado a ayudarlo a cancelar una fusión fallida. Esto es necesario porque en git mergerealidad le permitirá intentar una fusión con un árbol de trabajo sucio (uno con modificaciones locales) siempre que esas modificaciones estén en archivos que no se vean afectados por la fusión. git reset --mergerestablece el índice (como --mixed: todos los cambios se muestran como modificaciones locales) y restablece los archivos afectados por la fusión, pero deja a los demás solos. Con suerte, esto restaurará todo a como estaba antes de la mala fusión. Por lo general, lo usará como git reset --merge(significado git reset --merge HEAD) porque solo desea restablecer la fusión, no mover la rama. ( HEADno se ha actualizado todavía, ya que la fusión falló)
Para ser más concreto, suponga que ha modificado los archivos A y B, e intenta fusionarse en una rama que modificó los archivos C y D. La fusión falla por alguna razón, y decide cancelarla. Utiliza git reset --merge. Devuelve a C y D a su estado original HEAD, pero deja solo sus modificaciones en A y B, ya que no formaron parte del intento de fusión.
¿Quiere saber más?
Creo que man git resetes realmente bastante bueno para esto, quizás necesites un poco de la forma en que funciona git para que realmente se hundan. En particular, si se toma el tiempo de leerlos cuidadosamente, esas tablas que detallan los estados de los archivos en el índice y el árbol de trabajo para todas las opciones y casos son muy útiles. (Pero sí, son muy densos: transmiten una gran cantidad de la información anterior en una forma muy concisa).
Notación extraña
La "notación extraña" ( HEAD^y HEAD~1) que usted menciona es simplemente una abreviatura para especificar confirmaciones, sin tener que usar un nombre hash como 3ebe3f6. Está completamente documentado en la sección "especificando revisiones" de la página de manual para git-rev-parse, con muchos ejemplos y sintaxis relacionada. El caret y la tilde en realidad significan cosas diferentes :
HEAD~es la abreviatura de HEAD~1y significa el primer padre del commit. HEAD~2significa el primer padre del primer padre del commit. Piense HEAD~nen "n commits before HEAD" o "el ancestro de la enésima generación de HEAD".
HEAD^(o HEAD^1) también significa el primer padre del commit. HEAD^2significa el segundo padre del commit . Recuerde, un commit de fusión normal tiene dos padres: el primer padre es el commit de fusión y el segundo padre es el commit que se fusionó. En general, las fusiones pueden tener arbitrariamente muchos padres (fusiones de pulpos).
- Los
^y ~los operadores pueden ser ensartados, como en HEAD~3^2, la segunda matriz de la ancestro tercera generación de HEAD, HEAD^^2, la segunda matriz de la primera matriz de HEAD, o incluso HEAD^^^, lo que es equivalente a HEAD~3.
