Pregunta ¿Puedes explicar qué hace "git reset" en inglés sencillo?


he visto publicaciones interesantes explicando sutilezas sobre git reset.

Lamentablemente, cuanto más leo sobre él, más parece que no lo entiendo completamente. Vengo de un fondo SVN y Git es un paradigma completamente nuevo. Conseguí mercurial fácilmente, pero Git es mucho más técnico.

creo git reset esta cerca de hg revert, pero parece que hay diferencias.

Entonces, ¿qué es exactamente? git reset ¿hacer? Por favor incluya explicaciones detalladas sobre:

  • las opciones --hard, --soft y --merge;
  • la notación extraña que usa con HEAD como HEAD^ y HEAD~1;
  • casos de uso concreto y flujos de trabajo;
  • consecuencias en la copia de trabajo, el HEAD y su nivel de estrés global.

591
2018-03-27 16:44


origen


Respuestas:


En general, git resetLa función es tomar la rama actual y restablecerla para apuntar a otro lugar, y posiblemente llevar el índice y el árbol de trabajo. Más concretamente, si su rama principal (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, usarás git reset B para 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 y envío. Si corrieras git checkout B, obtendrías esto:

- A - B (HEAD) - C (master)

Terminaste en un estado HEAD separado. HEAD, árbol de trabajo, indexar todos los partidos B, pero la rama principal se quedó atrás en C. Si haces un nuevo commit D en este punto, obtendrás esto, que probablemente no sea lo que quieres:

- A - B - C (master)
       \
        D (HEAD)

Recuerde, el reinicio no hace commits, simplemente actualiza una rama (que es un puntero a una confirmación) para apuntar a una confirmación diferente. El resto es solo detalles de lo que sucede con su índice y árbol de trabajo.

Casos de uso

Cubro muchos de los casos de uso principales para git reset dentro de mis descripciones de las diversas opciones en la siguiente sección. Realmente se puede usar para una gran variedad de cosas; el hilo conductor es que todos implican reiniciar la rama, el índice y / o el árbol de trabajo para señalar / hacer coincidir una confirmación determinada.

Cosas a tener cuidado de

  • --hard puede hacer que realmente pierdas el trabajo. Modifica tu árbol de trabajo.

  • git reset [options] commit puede hacer que (en cierto modo) pierda compromisos. En el ejemplo de juguete anterior, hemos perdido el compromiso C. Todavía está en el repositorio, y puedes encontrarlo mirando a git reflog show HEAD o git reflog show master, pero en realidad 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 man, el uso más común es de la forma git reset [<commit>] [paths...], que restablecerá las rutas dadas a su estado a partir de la confirmación dada. Si no se proporcionan las rutas, se reinicia 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 entre 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/foo restablece todo en path / to / foo a su estado en other-branch, git reset -- .restablece el directorio actual a su estado en HEAD, y un simple git reset restablece todo a su estado en HEAD.

El árbol de trabajo principal y las opciones de índice

Hay cuatro opciones principales para controlar lo que sucede con su árbol de trabajo y su índice durante el reinicio.

Recuerda, el índice es el "área de preparación" de git, es donde van las cosas cuando dices git add en preparación para comprometerse.

  • --hard hace que todo coincida con la confirmación que ha restablecido. Este es el más fácil de entender, probablemente. Todos sus cambios locales se ven afectados. Un uso principal es eliminar tu trabajo pero no cambiar las confirmaciones: git reset --hard medio git reset --hard HEAD, es decir, no cambie la rama, sino deshágase de todos los cambios locales. El otro es simplemente mover una rama de un lugar a otro y mantener el árbol de índice / trabajo sincronizado. Este es el que realmente puede hacerle perder trabajo, porque modifica su árbol de trabajo. Esté muy seguro de que quiere deshacerse del trabajo local antes de ejecutar cualquier reset --hard.

  • --mixed es el predeterminado, es decir git reset medio 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 la confirmación original y la que restablece se mostrará como modificaciones locales (o archivos sin seguimiento) con estado de git. Úselo cuando se dé cuenta de que hizo algunos commits malos, pero quiere mantener todo el trabajo que ha hecho para poder arreglarlo y volver a comprometerse. Para comprometerse, tendrá que agregar archivos al índice nuevamente (git add ...)

  • --soft no toca el índice o árbol de trabajo. Todos sus archivos están intactos como con --mixed, pero todos los cambios aparecen como changes to be committed con estado de git (es decir, registrado como preparación para el compromiso). Úselo cuando se dé cuenta de que ha cometido errores, pero el trabajo es bueno; todo lo que debe hacer es volver a comprometerlo de manera diferente. El índice no ha sido modificado, por lo que puedes comprometerte de inmediato si así lo deseas; la confirmación resultante tendrá el mismo contenido que antes de reiniciar.

  • --merge se agregó recientemente y está destinado a ayudarlo a cancelar una fusión fallida. Esto es necesario porque git merge en realidad le permitirá intentar una fusión con un árbol de trabajo sucio (uno con modificaciones locales) siempre que esas modificaciones estén en archivos no afectados por la fusión. git reset --merge restablece el índice (como --mixed - todos los cambios aparecen como modificaciones locales) y restablece los archivos afectados por la combinación, pero deja a los demás en paz. Con suerte, esto restaurará todo a como estaba antes de la mala fusión. Por lo general, lo usará como git reset --merge (sentido git reset --merge HEAD) porque solo quiere restablecer la combinación, no mover realmente la rama. (HEAD no se ha actualizado aún, ya que la fusión falló)

    Para ser más concretos, supongamos 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 abortarla. Tu usas git reset --merge. Devuelve C y D a cómo estaban en HEAD, pero deja solo sus modificaciones a A y B, ya que no fueron parte del intento de fusión.

¿Quiere saber más?

Yo pienso man git reset es realmente bastante bueno para esto - tal vez necesites un poco de la percepción de cómo funciona realmente 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 en el árbol de trabajo para todas las diversas opciones y casos son muy útiles. (Pero sí, son muy densas, transmiten una gran cantidad de la información anterior de forma muy concisa).

Extraña notación

La "notación extraña" (HEAD^ y HEAD~1) que mencionas es simplemente una abreviatura para especificar confirmaciones, sin tener que usar un nombre hash como 3ebe3f6. Está completamente documentado en sección "especificar revisiones" de la página man 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~1 y significa el primer padre del compromiso. HEAD~2 significa el primer padre del primer padre del compromiso. Pensar en HEAD~n como "n commits before HEAD" o "the nth generation ancestro of HEAD".
  • HEAD^ (o HEAD^1) también significa el primer padre del compromiso. HEAD^2 significa que el compromiso segundo padre. Recuerde, una confirmación de fusión normal tiene dos padres: el primer padre se fusiona en la confirmación, y el segundo padre es la confirmación que se fusionó. En general, las fusiones pueden tener arbitrariamente muchos padres (fusiones de pulpos).
  • los ^ y ~ los operadores se pueden unir, como en HEAD~3^2, el segundo padre del ancestro de tercera generación de HEAD, HEAD^^2, el segundo padre del primer padre de HEAD, o incluso HEAD^^^, que es equivalente a HEAD~3.

caret and tilde


880
2018-03-27 16:48



Recuerde que en git tienes:

  • el HEAD puntero, que le dice en qué compromiso está trabajando
  • el árbol de trabajo, que representa el estado de los archivos en su sistema
  • el área de ensayo (también llamado el índice), que "etapas" cambios para que luego puedan ser comprometidos juntos

Por favor incluya explicaciones detalladas sobre:

--hard, --soft y --merge;

En orden creciente de peligrosidad:

  • --soft movimientos HEAD pero no toca el área de preparación o el árbol de trabajo.
  • --mixed movimientos HEAD y actualiza el área de preparación, pero no el árbol de trabajo.
  • --merge movimientos HEAD, restablece el área de preparación e intenta mover todos los cambios en su árbol de trabajo al nuevo árbol de trabajo.
  • --hard movimientos HEAD  y ajusta su área de preparación y árbol de trabajo a la nueva HEAD, tirando todo.

casos de uso concreto y flujos de trabajo;

  • Utilizar --soft cuando desee pasar a otra confirmación y arreglar las cosas sin "perder su lugar". Es bastante raro que necesites esto.

-

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

-

  • Utilizar --mixed (que es el valor predeterminado) cuando desea ver qué aspecto tienen las cosas en otra confirmación, pero no desea perder los cambios que ya tiene.

  • Utilizar --merge cuando desee trasladarse a un lugar nuevo, pero incorpore los cambios que ya tiene en ese árbol de trabajo.

  • Utilizar --hard para limpiar todo y comenzar una nueva cuenta en el nuevo compromiso.


75
2018-03-27 17:08



El cargo Restablecer Desmitificado en el blog Pro Git da una muy pan comido explicación sobre git reset y git checkout.

Después de toda la discusión útil en la parte superior de esa publicación, el autor reduce las reglas a los siguientes tres simples pasos:

Eso es básicamente eso. los reset comando sobrescribe estos tres árboles en un orden específico, deteniéndose cuando se lo indique.

  1. Mueva cualquier rama a la que apunte HEAD (pare si --soft)
  2. LUEGO, haz que el índice se vea así (detente aquí a menos --hard)
  3. LUEGO, haz que el Directorio de trabajo se vea así

También hay --merge y --keep opciones, pero preferiría mantener las cosas más simples por ahora, eso será para otro artículo.


33
2017-07-19 14:37



Cuando compromete algo a git primero tiene que organizar (agregar al índice) sus cambios. Esto significa que debe agregar todos los archivos que desea incluir en esta confirmación antes de que git los considere parte de la confirmación. Veamos primero la imagen de un repositorio de git: enter image description here

entonces, es simple ahora Tenemos que trabajar en el directorio de trabajo, crear archivos, directorios y todo. Estos cambios son cambios sin seguimiento. Para rastrearlos, debemos agregarlos al índice git mediante el uso de git agregar mando. Una vez que se agregan al índice git. Ahora podemos enviar estos cambios, si queremos enviarlos al repositorio de git.

Pero de repente nos enteramos al comprometernos que tenemos un archivo adicional que añadimos en el índice y no es necesario para insertar en el repositorio de git. Significa que no queremos ese archivo en el índice. Ahora la pregunta es cómo eliminar ese archivo del índice git, ya que usamos git agregar para ponerlos en el índice, sería lógico usar git rm? ¡Incorrecto! git rm simplemente eliminará el archivo y agregará la eliminación al índice. Entonces, ¿qué hacer ahora?

Utilizar:-

git reset

Borra su índice, deja intacto su directorio de trabajo. (simplemente desestabilizar todo).

Se puede usar con varias opciones con él. Hay tres opciones principales para usar con git reset: --hard, --soft y --mixed. Estos afectan lo que se restablece además del puntero HEAD cuando se restablece.

Primero, --difícil restablece todo. Su directorio actual sería exactamente como lo hubiera sido si hubiera estado siguiendo esa rama todo el tiempo. El directorio de trabajo y el índice se cambian a esa confirmación. Esta es la versión que uso más a menudo. git reset --hard es algo así como svn revertir .

A continuación, todo lo contrario, -suave, no restablece el árbol de trabajo ni el índice. Solo mueve el puntero HEAD. Esto deja su estado actual con cualquier cambio diferente a la confirmación que está cambiando en su directorio, y "en etapas" para la confirmación. Si realiza una confirmación localmente pero no ha enviado la confirmación al servidor de git, puede restablecer la confirmación anterior y volver a enviarla con un buen mensaje de confirmación.

Finalmente, --mezcladorestablece el índice, pero no el árbol de trabajo. Entonces, los cambios siguen ahí, pero están "sin escena" y deberían ser agregados o git commit -a. usamos esto a veces si cometimos más de lo que queríamos con git commit -a, podemos anular la confirmación con git reset --mixed, agregar las cosas que queremos comprometer y simplemente comprometerlas.

Diferencia entre git revert y git reset : -


En palabras simples, git reset es un comando para "corregir errores sin compromiso" y git revertir es un comando para "error corregido".

Significa que si hemos cometido algún error en algún cambio y nos hemos comprometido y hemos enviado lo mismo a git repo, entonces git revertir es la solución. Y si en caso de que hayamos identificado el mismo error antes de presionar / comprometer, podemos usar git reset para arreglar el problema

Espero que te ayude a deshacerte de tu confusión.


22
2017-07-07 17:15



TL; DR

git reset restablece la Etapa a la última confirmación. Utilizar --hard también restablecer los archivos en su directorio de trabajo a la última confirmación.

VERSIÓN MÁS LARGA

Pero eso es obviamente simplista, de ahí las muchas respuestas bastante detalladas. Tenía más sentido para mí leer sobre git reset en el contexto de deshacer cambios P.ej. mira esto:

Si Git Revert es una forma "segura" de deshacer cambios, puedes pensar en Git   restablecer como el método peligroso. Cuando deshacer con git reset (y el   confirmaciones ya no se referencian por ninguna referencia o reflog), hay   no hay forma de recuperar la copia original; es un deshacer permanente. Cuidado debe   ser tomado al usar esta herramienta, ya que es uno de los únicos comandos de Git que tiene el potencial de perder su trabajo.

De https://www.atlassian.com/git/tutorials/undoing-changes/git-reset 

y esto

En el nivel de confirmación, restablecer es una forma de mover la punta de una rama a una confirmación diferente. Esto se puede usar para eliminar confirmaciones de la rama actual.

De https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations 


6
2017-07-13 17:37



Tenga en cuenta que esta es una explicación simplificada que pretende ser un primer paso para comprender esta compleja funcionalidad.

Puede ser útil para los estudiantes visuales que desean visualizar cómo se ve el estado de su proyecto después de cada uno de estos comandos:


Para aquellos que usan Terminal con color encendido (git config --global color.ui auto):

git reset --soft A y verás las cosas de B y C en verde (puestas en escena y listas para comprometerse)

git reset --mixed A (o git reset A) y verá las cosas de B y C en rojo (sin escena y listo para ser escenificado (verde) y luego comprometido)

git reset --hard A y ya no verás los cambios de B y C en ningún lado (será como si nunca hubieran existido)


O para aquellos que usan un programa de GUI como 'Tower' o 'SourceTree'

git reset --soft A y verá las cosas de B y C en el área de 'archivos preparados' listos para comprometerse

git reset --mixed A (o git reset A) y verá las cosas de B y C en el área 'archivos sin grabar' listas para ser movidas a etapas y luego comprometidas

git reset --hard A y ya no verás los cambios de B y C en ningún lado (será como si nunca hubieran existido)


2
2017-11-21 12:35



Hay un artículo realmente bueno para explicar Restablecer (incluir el pago / retroceso y su comparación), con suerte, ayuda. https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/summary


1
2018-03-09 23:49