¿Puedo dividir un trozo ya dividido con git?


Recientemente he descubierto la opción patch de git para el comando add, y debo decir que realmente es una característica fantástica. También descubrí que un trozo grande se podía dividir en trozos más pequeños pulsando la tecla s, lo que aumenta la precisión del commit. Pero, ¿qué pasa si quiero aún más precisión, si el trozo partido no es lo suficientemente pequeño?

Por ejemplo, considere este trozo ya dividido:

@@ -34,12 +34,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

¿Cómo puedo añadir la eliminación de comentarios CSS solo a la próxima confirmación ? El s la opción ya no está disponible!

Author: greg0ire, 2011-06-08

4 answers

Si está usando git add -p e incluso después de dividir con s, no tiene un cambio lo suficientemente pequeño, puede usar e para editar el parche directamente.

Esto puede ser un poco confuso, pero si con cuidado siga las instrucciones en la ventana del editor que se abrirá después de presionar e, entonces estará bien. En el caso de que hayas citado, deberías reemplazar el - con un espacio al principio de estas líneas:

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {

... y suprímase la siguiente línea, es decir, la que comienza con +. Si a continuación guarda y sale de su editor, solo la eliminación del comentario CSS se llevará a cabo.

 189
Author: Mark Longair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 22:15:05

Digamos que su example.css se ve así:

.classname {
  width: 440px;
}

/*#field_teacher_id {
  display: block;
} */

form.table-form #field_teacher + label,
form.table-form #field_producer_distributor + label {
  width: 300px;
}

.another {
  width: 420px;
}

Ahora vamos a cambiar los selectores de estilo en el bloque central, y mientras estamos en ello, eliminar algún viejo estilo comentado que ya no necesitamos.

.classname {
  width: 440px;
}

#user-register form.table-form .field-type-checkbox label {
  width: 300px;
}

.another {
  width: 420px;
}

Eso fue fácil, ahora comprometámonos. Pero espere, quiero mantener la separación lógica de los cambios en el control de versiones para una revisión simple del código paso a paso, y para que mi equipo y yo podamos buscar fácilmente el historial de confirmaciones para obtener detalles.

Eliminar código antiguo es lógicamente separado del otro cambio selector de estilo. Vamos a necesitar dos commits distintos, así que vamos a añadir trozos para un parche.

git add --patch
diff --git a/example.css b/example.css
index 426449d..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Stage this hunk [y,n,q,a,d,/,e,?]?

Whoops, parece que los cambios están demasiado cerca, por lo que git los ha juntado.

Incluso tratando de dividir presionando s tiene el mismo resultado porque la división no es lo suficientemente granular para nuestros cambios de precisión. Se requieren líneas sin cambios entre líneas cambiadas para que git pueda dividir automáticamente el parche.

Por lo tanto, vamos a editar manualmente presionando e

Stage this hunk [y,n,q,a,d,/,e,?]? e

Git abrirá el parche en nuestro editor de elección.

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

Repasemos la meta: {[24]]}

¿Cómo puedo añadir la eliminación de comentarios CSS solo a la próxima confirmación ?

Queremos dividir esto en dos confirmaciones:

  1. La primera confirmación implica eliminar algunas líneas (eliminación de comentarios).

    Para eliminar las líneas comentadas, simplemente déjalas en paz, ya están marcadas para rastrear las eliminaciones en el control de versiones tal y como queremos.

    -/*#field_teacher_id {
    - display: block;
    -} */

  2. El segundo commit es un cambio, que es seguido registrando tanto las eliminaciones como las adiciones:

    • Eliminaciones (antiguas líneas de selector eliminadas)

      Para mantener las líneas de selector antiguas (no las borre durante esta confirmación), queremos...

      Para eliminar '-' líneas, hazlas ''

      ...lo que literalmente significa reemplazar el signo menos - con un espacio carácter.

      Así que estas tres líneas...

      -
      -form.table-form #field_teacher + label,
      -form.table-form #field_producer_distributor + label {

      ...se convertirá en ( observe el espacio único en la primera de las 3 líneas):


      form.table-form #field_teacher + label,
      form.table-form #field_producer_distributor + label {

    • Adiciones (nueva línea de selector añadida)

      Para no prestar atención a la nueva línea de selector añadida durante este compromiso, queremos...

      Para eliminar las líneas'+', elimínelas.

      ...lo que literalmente significa borrar toda la línea:

      +#user-register form.table-form .field-type-checkbox label {

      (Bonus: Si estás usando vim como editor, presiona dd para eliminar una línea. Nano los usuarios presionan Ctrl+K )

Su editor debe tener este aspecto cuando guardar:

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

Ahora vamos a comprometernos.

git commit -m "remove old code"

Y solo para asegurarnos, veamos los cambios de la última confirmación.

git show
commit 572ecbc7beecca495c8965ce54fbccabdd085112
Author: Jeff Puckett <[email protected]>
Date:   Sat Jun 11 17:06:48 2016 -0500

    remove old code

diff --git a/example.css b/example.css
index 426449d..d04c832 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,6 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {

Perfecto - se puede ver que solo las eliminaciones fueron incluidas en ese commit atómico. Ahora terminemos el trabajo y comprometámonos con el resto.

git add .
git commit -m "change selectors"
git show
commit 83ec3c16b73bca799e4ed525148cf303e0bd39f9
Author: Jeff Puckett <[email protected]>
Date:   Sat Jun 11 17:09:12 2016 -0500

    change selectors

diff --git a/example.css b/example.css
index d04c832..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,7 @@
   width: 440px;
 }

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Finalmente puede ver que la última confirmación solo incluye los cambios del selector.

 35
Author: Jeff Puckett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-14 15:11:00

Si puedes usar git gui, te permite realizar cambios línea por línea. Desafortunadamente, no se como hacerlo desde la línea de comandos-o incluso si es posible.

Otra opción que he usado en el pasado es revertir parte del cambio (mantener el editor abierto), confirmar los bits que quiero, deshacer y volver a guardar desde el editor. No es muy elegante,pero hace el trabajo. :)


EDITAR (uso de git-gui):

No estoy seguro de si el git-gui es el mismo en msysgit y linux versiones, solo he utilizado el msysgit uno. Pero asumiendo que es lo mismo, cuando lo ejecuta, hay cuatro paneles: el panel superior izquierdo es los cambios de su directorio de trabajo, el panel inferior izquierdo es los cambios de sus etapas, el panel superior derecho es la diferencia para el archivo seleccionado (sea dir de trabajo o staged), y el panel inferior derecho es para la descripción de la confirmación (sospecho que no la necesitará). Al hacer clic en un archivo en la parte superior derecha, verá la diferencia. Si haces clic derecho en una línea de diferencia, verás un menú contextual. Las dos opciones para nota: "stage hunk for commit" y "stage line for commit". Usted sigue seleccionando "stage line for commit" en las líneas que desea confirmar, y ya está. Incluso puede seleccionar varias líneas y escenificarlas si lo desea. Siempre puede hacer clic en el archivo en el cuadro de ensayo para ver lo que está a punto de cometer.

En cuanto a la confirmación, puede usar la herramienta gui o la línea de comandos.

 9
Author: vhallac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-08 10:14:32

Una forma de hacerlo es omitir el fragmento, git add cualquier otra cosa que necesite, y luego ejecutar git add de nuevo. Si este es el único trozo, podrás dividirlo.

Si te preocupa el orden de las confirmaciones, simplemente usa git rebase -i.

 1
Author: Abizern,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-14 18:11:57