2011-12-01 17 views
7

Por lo que sé, cuando quieres deshacer algo en Git tienes que encontrar explícitamente el comando para deshacer lo que sea que hayas hecho y emitirlo. Por ejemplo, una forma entre muchas para deshacer una confirmación y rehacer que es seguir el ejemplo de here,¿Por qué no hay deshacer/rehacer en Git?

$ git commit ... 
$ git reset --soft HEAD^ 
$ edit 
$ git add .... 
$ git commit -c ORIG_HEAD 

O para deshacer un tirón, puede seguir las instrucciones de here,

$ git reset --hard 

Pero estos comandos no necesariamente funcionan indistintamente. ¿Hay alguna razón por la cual Git no permite comandos simples para deshacer y rehacer? ¿Algo que ver con la filosofía detrás de esto? Además, no tengo mucha experiencia con otros sistemas de control de versiones, pero ¿alguno de ellos ofrece un comando simple de deshacer y rehacer?

+0

No estoy seguro, pero creo que puedes hacer esto usando 'git rebase'. Comprueba este http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html – gustavotkg

+2

La idea es que generalmente nunca deseas hacer cosas que te hagan perder partes del historial. Deshacer una confirmación lo eliminaría del historial, por lo que generalmente no es algo que haría. – poke

+0

@poke Bueno, Adobe Photoshop, por ejemplo, mantiene un historial extenso y aún le permite deshacer/rehacer. ¿Por qué no haría Git lo mismo? – john

Respuesta

6

Hay varios problemas con esta noción:

  • No todas las operaciones son reversibles. A veces, esto se debe a que Git no registra suficiente información para deducir el estado anterior, que sería prohibitivamente caro en general. A veces son cosas como git reset --hard o git clean, que destruyen los cambios sin seguimiento. Para deshacerlos, tendrían que respaldarse automáticamente de forma continua. A veces, esto se debe a que la noción de deshacer es ambigua, como usted mismo señaló, hay muchas formas de deshacer un compromiso.

  • Si una operación es reversible e involucra algún tipo de historial, ¿el deshacer/rehacer también debe estar en el historial, o deberían hacerlo desaparecer? ¿Debería deshacerse una confirmación reiniciando o invirtiendo (creando otra confirmación para cancelarla)?

  • Sin iniciar sesión hasta el último detalle, ¿cómo sabría cuál fue la operación más reciente? Supongamos que agregó un archivo al índice y creó una rama. No hay registro de cuál fue el primero.

Incluso si todo estuviera claramente definido, sería una cantidad de trabajo absurda de implementar. ¿Cómo se decide qué constituye una acción única? Un único comando de Git podría hacer muchas cosas. ¿Debería deshacer un paso, todo el asunto? ¿Qué pasa si has ejecutado un trillón de comandos cada uno haciendo un pequeño paso y quieres deshacerlo todo? Y tendría que ser perfecto, completamente perfecto, porque es el tipo de característica que será utilizada por usuarios inexpertos que no tendrán idea de cómo recuperarse de cualquier error.

Así que, al igual que Git le da las herramientas para hacer las cosas, le da las herramientas para ver lo que ha hecho, y deshacer las cosas usted mismo si así lo desea.

Además, con respecto a "rehacer", como lo definió en su pregunta, está repitiendo un comando, no haciendo la operación original otra vez. Cuando redimiste una confirmación, era otra. Volver a ejecutar un comando anterior es algo que los shells de línea de comandos fueron diseñados para hacer. Git no necesita reinventarlo.

4

En realidad el primer ejemplo se puede realizar con:

$ git commit ... 
$ edit 
$ git add ... 
$ git commit --amend 

Su segundo ejemplo debería ser más como git reset --hard <hash>

La respuesta a su pregunta es que es potencialmente posible, pero sí lo es más el de conducir la filosofía git eso significa que no se ha hecho. En teoría, no hay manera de saber si llegó a un compromiso al crearlo o eliminar otro, pero usar el reflog es posible ... realmente no lo había pensado antes de esa manera.

No creo que 'deshacer' y 'rehacer' sean algo muy común en el control de fuente, pero corríjanme si me equivoco.

EDITAR: Posiblemente podría manipular un script que podría hacer lo que busca después de usar el reflog: no estoy seguro de si hay suficiente información allí, pero podría valer la pena intentarlo.

1

git es en realidad varias herramientas pequeñas que actúan en el repositorio, índice y directorio de trabajo, por lo que no tiene una parte 'núcleo' para cualquier 'deshacer'.

Dicho esto, tiene varios registros, como reflog para que pueda recordar lo que se hizo.

Por último, por convención, muchas acciones de git normalmente se consideran como 'de una sola vía', es decir, no querría que nadie lo vea públicamente, por lo que git intenta 'hacerlo girar alrededor del bloquear 'cuando en público. Si todavía está en su repositorio local, puede realizar una copia de seguridad con varios comandos, pero una operación de deshacer global no es una oferta de comando adecuada.

+0

'one-way only' es una buena manera de pensarlo, ya que una vez que algo está en la naturaleza, deshacer y rehacer se vuelven peligrosos – MattJenko

0

Junto con los otros comentarios me gustaría ver git stash. Muchas veces escondo algo de trabajo, arreglo otra cosa, luego me desabrocho y continúo. O para una aplicación web, esconder mi trabajo finalizado y no confirmado, actualizar el navegador, desapilar, abrir una nueva pestaña y luego comparar los dos hacia adelante y hacia atrás para asegurarme de que una corrección de errores relacionada con la interfaz de usuario no rompa nada más.

Cuestiones relacionadas