¿Cuál es el beneficio del proceso de confirmación en dos etapas (puesta en escena) de git?

175

Estoy aprendiendo git y noté que tiene un proceso de confirmación de dos pasos:

  1. git add <files>
  2. git commit

El primer paso coloca revisiones en lo que se llama un "área de ensayo" o "índice".

Lo que me interesa es por qué se toma esta decisión de diseño y cuáles son sus beneficios.

Además, como usuario de git, ¿haces esto o simplemente lo usas git commit -a?

Pregunto esto porque vengo de bzr (Bazar) que no tiene esta característica.

thomasrutter
fuente
3
+1 por preguntar. Uso Tortoise SVN, que tiene el mismo enfoque y nunca entendí por qué.
DPD
3
El área de preparación no es tan inusual. El equivalente en, por ejemplo, TFS sería marcar o desmarcar la casilla junto a un archivo antes de registrarse. Solo se comprometen los archivos marcados. La diferencia con Git es que si usa git add -p, puede elegir confirmar una parte de un archivo sin comprometer otra parte del mismo archivo .
Kyralessa
Descubrí que este enlace resume la mayor parte de lo que se respondió aquí y agrega algunos casos de uso más para justificar la necesidad de la puesta en escena.
Veverke
2
Esta pregunta ya está respondida, pero aquí también hay una buena explicación: stackoverflow.com/questions/4878358/…
guitar_freak
1
No lo olvides git statusy posiblemente git push. Para todo el bombo sobre git, (y el código para compartir de GitHub es maravilloso) las partes son muy molestas
user949300

Respuestas:

83

Dividir el trabajo en commits separados. Probablemente haya abierto muchas veces un archivo para escribir una corrección de una sola línea, pero al mismo tiempo descubrió que el formato era incorrecto, que podría mejorarse alguna documentación u otra corrección no relacionada. Con otros RCS , tendrías que escribir eso o guardarlo en la memoria, terminar la reparación por la que viniste, comprometerlo y luego volver a arreglar las otras cosas (o crear un compromiso de bola de barro con cosas no relacionadas) . Con Git, solo arreglas todo de una vez, y stage + confirma la línea individual por separado, con git add -io git-gui.

No rompas la construcción. Estás trabajando en una modificación complicada. Así que intentas cosas diferentes, algunas de las cuales funcionan mejor que otras, algunas que rompen cosas. Con Git, organizaría las cosas cuando la modificación mejorara las cosas y checkout(o modificara un poco más) cuando la modificación no funcionara. No tendrá que confiar en la funcionalidad de deshacer del editor, puede hacer checkoutel repositorio completo en lugar de solo archivo por archivo, y cualquier error a nivel de archivo (como eliminar un archivo que no se ha confirmado o guardar + cerrar después de un mala modificación) no lleva a perder mucho trabajo.

l0b0
fuente
3
Procedente de un DVCS (bzr) que no tiene esta característica, que se parece mucho a lo que actualmente logro con una combinación de uso liberal de los buffers "deshacer" de mi editor, el comando "revert <file>" y los commits selectivos (" cometer <archivo> "). Parece que esta característica de git tiene el potencial de ser más metódica.
thomasrutter
1
Con respecto a "otros RCSes", eso no es necesariamente cierto. De hecho, puede lograr esas mismas funcionalidades en Mercurial usando parches .
Lucio Paiva
1
@ l0b0, sobre tu segundo punto. Si solo hubiera una confirmación de una sola etapa, podría haber confirmado los cambios (que usa con git add) directamente como confirmación. Si descubrieras que hiciste algo mal, habrías eliminado la confirmación y regresado a donde estabas antes de realizar la confirmación. Con el concepto de puesta en escena, ¿no solo estás haciendo eso, sino que agregas más complejidad?
alpha_989
Su primer punto tiene sentido, aunque hasta ahora no lo he usado. Teóricamente, ¿por qué no puedes hacer algo así git add -icon un commit de una sola etapa? Simplemente elegiría un montón de archivos (o líneas dentro de los archivos) relacionados con una sola característica, y realizaría una confirmación. Luego volvería y haría una segunda confirmación relacionada con otra función ..
alpha_989
@ thomasrutter, según su declaración, parece que está sugiriendo que el área de preparación crea "puntos de deshacer manuales". En VIM con persistente-deshacer, puede obtener un historial ilimitado de manera muy confiable. Esto también se rastrea automáticamente en forma de git-branchtipo ( jovicailic.org/2017/04/vim-persistent-undo ). Además, su historial de deshacer se rastrea automáticamente cada vez que entra en modo normal. Por lo tanto, reduce su carga mental de tener que crear "puntos de deshacer manuales". ¿Por qué el uso de sus editores "deshacer" buffers no es tan metódico?
alpha_989
65

Una de las ventajas para mí es la capacidad de "agregar" archivos progresivamente. Antes de comprometerme, reviso cada archivo. Una vez que se revisa el archivo, lo agrego. Cuando yo git statuso git diff, git me muestra solo los archivos que se han modificado y que aún no se han agregado. Cuando haya revisado todos los archivos y los haya agregado, entonces puedo confirmar.

Entonces sí, encuentro que el área de preparación es muy útil.

Y no, nunca lo uso git commit -a. Sin embargo, a menudo lo uso git add -u. De esta manera todavía puedo visualizar lo que se debe comprometer.

David
fuente
2
Exactamente. La ventaja es un control mucho más fino sobre exactamente lo que está compitiendo.
Josh K
¿Qué sucede cuando se presenta un archivo varias veces? ¿se "fusiona" en el área de preparación?
m4l490n
21

El beneficio es bastante simple: le da control total sobre qué archivos desea confirmar cuando. Para el caso, puede usar git add -ppara controlar qué líneas desea confirmar.

Rein Henrichs
fuente
2
Siempre me he preguntado cómo hacer esto. Desearía que hubiera un archivo .gitignorelinespara que pudieras hacer cambios locales en las líneas individuales que podrían sobrevivir a las confirmaciones y permanecer intactas.
alex gray
3
@ReinHenrichs, piense en los archivos de configuración que cada desarrollador debe cambiar.
Ian
1
@Ian ¿Entonces parte del archivo cambia con poca frecuencia y se comparte y parte del archivo cambia a menudo, de manera incompatible, y no se comparte? Apoyar esta falsa connascencia definitivamente suena como una antifunción.
Rein Henrichs
1
@ReinHenrichs, sí, y es muy común cuando el archivo contiene el nombre del servidor de la base de datos y cada desarrollador tiene su propia base de datos.
Ian
44
@Ian Su problema está realmente ahí, que tiene un archivo que se supone que es la configuración de la aplicación y que también contiene alguna configuración específica de máquina / desarrollador. Todos los sistemas de configuración que conozco le permiten dividir eso en varios archivos. Entonces, por ejemplo, tiene su app.confque contiene las cosas que desea compartir, y luego una db.confque acaba de poner en la lista .gitignore. Problema resuelto. Si está utilizando algo patentado, realmente debería considerar obtener algo tan simple allí. O póngalo a través de un preprocesador en un evento de precompilación. Muchas soluciones allí.
Aidiakapi
1

Uno de los beneficios que me gusta es la capacidad de cometer una parte de un cambio. Es decir, usando git add -e. A veces no me comprometo tan a menudo como debería, y el comando git add -e me permite desentrañar mis cambios hasta cierto punto.

leed25d
fuente