2011-06-08 22 views
133

Recientemente descubrí 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 puede dividir en trozos más pequeños presionando la tecla s, que se suma a la precisión de la confirmación. Pero, ¿y si quiero aún más precisión, si el trozo de división no es lo suficientemente pequeño?¿Puedo dividir un trozo ya dividido con git?

Por ejemplo, considere este trozo ya dividir:

@@ -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 el comentario eliminación CSS sólo para la próxima confirmación? ¡La opción s ya no está disponible!

Respuesta

175

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

Esto puede ser un poco confuso, pero si cuidadosamente sigue las instrucciones que aparecen en la ventana del editor que se abre después de pulsar e, entonces estará bien. En el caso de que he citado, que se quiere sustituir el - con un espacio al principio de estas líneas:

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

... y borrar el la siguiente línea, es decir, la que comienza con +.Si luego guarda y sale de su editor, solo se realizará la eliminación del comentario de CSS.

+7

¡Solución genial! Vi eso pero lo entendí mal ... pensé que los cambios también se eliminarían del árbol de trabajo. – greg0ire

+6

De hecho, no es muy obvio a partir del texto de ayuda. En realidad, me estoy usando mucho, ya que creo que git realmente lo anima a hacer que cada compromiso sea lo más preciso y hermoso posible :) –

+1

Su solución no requiere ningún software adicional, por lo que creo que debería ser LA respuesta a mi pregunta . ¡Aceptado! – greg0ire

1

Una forma de hacerlo es omitir el fragmento, git add lo que sea que necesite, y luego ejecutar git add nuevamente. Si este es el único pedazo, podrás dividirlo.

Si le preocupa el orden de las confirmaciones, simplemente use git rebase -i.

+0

Esto es lo que probé, y el problema en mi pregunta es el único cuando ejecuto 'git add -p' de nuevo, pero no puedo dividirlo. Entiendo esto: '¿Poner en escena este trozo [y, n, q, a, d, /, e,?]?' Y luego presionar 's' imprime la ayuda. Por cierto, ¿quisiste 'agregar parche', no' parche agregar'? ¿O hay un complemento 'git patch' que debo instalar? – greg0ire

+0

¿Cometiste los trozos montados antes de volver a ejecutar esto? Y no, Mercurial tiene complementos, Git no. – Abizern

+0

No, no lo hice, quiero que estén en el mismo compromiso (pero supongo que si tu solución funciona, puedo usarla --mendar para lograr esto). Lo probaré. – greg0ire

9

Si puede usar git gui, le permite realizar cambios de etapa línea por línea. Desafortunadamente, no sé cómo hacerlo desde la línea de comandos, o incluso si es posible.

Otra opción que he utilizado en el pasado es deshacer 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 las versiones msysgit y Linux, sólo he utilizado el msysgit uno. Pero asumiendo que es lo mismo, cuando lo ejecuta, hay cuatro paneles: panel superior izquierdo es su directorio de trabajo cambia, abajo a la izquierda son sus cambios de etapas, arriba a la derecha es el diff para el archivo seleccionado (ya sea que funcione dir o en etapas), y abajo a la derecha es para la descripción del compromiso (sospecho que no lo necesitará). Cuando haces clic en un archivo en la esquina superior derecha, verás la diferencia. Si haces clic derecho en una línea diff, verás un menú contextual. Las dos opciones a tener en cuenta son "fase final para la confirmación" y "línea de la etapa para la confirmación". Sigue seleccionando "línea de escenario para la confirmación" en las líneas que desea confirmar, y listo. Incluso puede seleccionar varias líneas y ponerlas en escena si lo desea. Siempre puede hacer clic en el archivo en el cuadro de etapas para ver qué está cometiendo.

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

+0

Su segunda proposición es bastante evidente, pero la primera es interesante, ¿podría detallar un poco más? Instalé 'git-gui' pero no tengo idea de cómo lograr lo que estás describiendo. – greg0ire

+0

Edité la respuesta para describir el uso de "etapa esta línea". – vhallac

+0

tanques mucho! ¡Esto funciona! Incluso pude seleccionar las líneas que quería representar e indexarlas con un solo clic. – greg0ire

28

digamos que su example.css se parece a esto:

.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, elimine algo de estilo antiguo de salida comentado que no necesitamos nunca más.

.classname { 
    width: 440px; 
} 

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

.another { 
    width: 420px; 
} 

Eso fue fácil, ahora vamos a cometer. Pero espere, quiero mantener la separación lógica de los cambios en el control de la versión para una simple revisión del código paso a paso, y para que mi equipo y yo podamos buscar fácilmente el historial de compromisos para obtener información específica.

El borrado del código antiguo es lógicamente independiente del otro cambio de selector de estilo. Vamos a necesitar dos commits distintos, así que agreguemos hunks 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,?]? 

Vaya, parece que los cambios son demasiado cerca, por lo que git ellos ha hunked juntos.

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

Por lo tanto, vamos a editar manualmente pulsando e

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

git se 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 el objetivo:

¿Cómo puedo añadir el comentario eliminación CSS sólo para la próxima confirmación?

Nos quieren dividir esto en dos confirmaciones:

  1. El primer commit supone la supresión de algunas líneas (eliminación comentario).

    Para eliminar las líneas comentadas, simplemente déjalos en blanco, ya están marcadas para rastrear las eliminaciones en el control de versión como queremos.

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

  2. El segundo cometer es un cambio, lo que se realiza un seguimiento mediante el registro de ambas supresiones y adiciones:

    • Deleciones (antiguas líneas selectoras eliminados)

      Para mantener las líneas selectoras antiguas (no las elimine durante esta confirmación), queremos ...

      Para retirar '-' líneas, los hacen ''

      ... que literalmente significa la sustitución de los signos menos -con un espacio carácter.

      por lo que estas tres líneas ...

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

      ... se convertirá en (aviso el espacio individual 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 selección añadido)

      Para no prestar atención a la nueva línea de selección añadido durante este comprometemos, queremos ...

      Para retirar '+' líneas , borra los.

      ... que literalmente significa eliminar toda la línea:

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

      (Bono: Si usted se esté utilizando nano como editor, a continuación, la combinación de teclas para borrar una línea es Ctrl + K)

Su editor debe tener este aspecto cuando se guarda:

# 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 cometer.

git commit -m "remove old code" 

Y para asegurarse, veamos los cambios desde 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 sólo las supresiones se incluyeron en esa confirmación atómica. Ahora terminemos el trabajo y comprometamos 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; 
} 

Por último se puede ver la última confirmación sólo incluye los cambios de selector.

+3

Un poco tarde para la fiesta, pero la respuesta es muy detallada, ¡lindo! – greg0ire

+2

¡Completo, gracias! – lintuxvi

+1

¡Sólido! ¡Gracias! –

Cuestiones relacionadas