git

¿Cómo hacer commit de líneas especificas de un archivo?

En nuestro trabajo diario como desarrolladores, modificamos archivos y los almacenamos de manera ordenada en commits que identifican claramente los cambios, en lugar de realizar una sola confirmación con el título varios cambios.

En nuestro trabajo diario como desarrolladores, modificamos archivos y los almacenamos de manera ordenada en commits que identifican claramente los cambios, en lugar de realizar una sola confirmación con el título varios cambios.

Pero, qué ocurre si realizamos varios cambios en un mismo archivo que deben corresponder a commits diferentes?

Supongamos que tenemos un archivo inicial llamado main.go como este:

package main

import "fmt"

func main() {
	  fmt.Println("Hola EDteam")
	  fmt.Println("Hola Comunidad")
	  fmt.Println("Hola team")
}

Luego realizamos tres cambios:

  • Agregamos una nueva línea al inicio de la función main.
  • Eliminamos el saludo a la comunidad.
  • Agregamos un mensaje de despedida.
package main

import "fmt"

func main() {
  fmt.Println("Agregamos esta nueva línea")
  fmt.Println("Hola EDteam")
  fmt.Println("Hola team")
  fmt.Println("Hasta pronto")
}

Pero no queremos crear un commit con los 3 cambios, en su lugar queremos crear un commit para cada uno, así que podemos agregar el flag -p o --path del comando git add para hacerlo:

Ejecutamos el comando git add -p main.go y git nos muestra una salida como esta:

diff --git a/main.go b/main.go
index 67d8ba2..cdcfdc0 100644
--- a/main.go
+++ b/main.go
@@ -3,7 +3,8 @@ package main
 import "fmt"

 func main() {
+       fmt.Println("Agregamos esta nueva línea ")
        fmt.Println("Hola EDteam")
-       fmt.Println("Hola Comunidad")
        fmt.Println("Hola team")
+       fmt.Println("Hasta pronto")
 }
Stage this hunk [y,n,q,a,d,s,e,?]?

En donde nos pregunta qué hacer con el fragmento de código, para ello debemos especificar alguna de las opciones que el comando provee, te listo las más usadas pero si quieres conocer más puedes pasar la opción ?.

  • y: Incluir al área de preparación el fragmento.
  • n: No incluir al área de preparación el fragmento.
  • q: Salir, No incluir al área de preparación el fragmento actual o cualquiera de los restantes.
  • a : Agregar este fragmento al área de preparación y todos los restantes.
  • s : Dividir el fragmento actual en fragmentos más pequeños.
  • e : Editar manualmente el fragmento actual.

En nuestro ejemplo git nos establece todo nuestros cambios como un único fragmento, pasamos la opción s para dividirlo en partes más pequeñas, en este caso será divido en 3 partes, luego git nos preguntará qué hacer con cada fragmento, al primer fragmento le indicaremos la opción y para agregarlo al área de preparación.

Split into 3 hunks.
@@ -3,4 +3,5 @@
 import "fmt"

 func main() {
+       fmt.Println("Agregamos esta nueva línea ")
        fmt.Println("Hola EDteam")
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y

Y a los dos fragmentos siguientes la opción n para excluirlos.

@@ -6,3 +7,2 @@
        fmt.Println("Hola EDteam")
-       fmt.Println("Hola Comunidad")
        fmt.Println("Hola team")
Stage this hunk [y,n,q,a,d,K,j,J,g,/,e,?]? n

@@ -8,2 +8,3 @@
        fmt.Println("Hola team")
+       fmt.Println("Hasta pronto")
 }
Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n

De esta manera agregamos solamente la primera línea de la función main, ahora podemos confirmar nuestro primer cambio git commit -m 'Agrega una nueva línea al inicio de la función'

Para agregar nuestro segundo cambio realizamos el mismo proceso:

  • git add -p main.go
  • Indicamos la opción s para separar el fragmento, git lo dividirá en dos partes, así que agregamos el fragmento actual con la opción y
Split into 2 hunks.
@@ -5,5 +5,4 @@
 func main() {
        fmt.Println("Agregamos esta nueva línea ")
        fmt.Println("Hola EDteam")
-       fmt.Println("Hola Comunidad")
        fmt.Println("Hola team")
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
  • descartamos el siguiente con la opción n.
@@ -9,2 +8,3 @@
        fmt.Println("Hola team")
+       fmt.Println("Hasta pronto")
 }
Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n
  • Confirmamos el segundo cambio: git commit -m 'Elimina el saludo de la comunidad'

Finalmente confirmamos directamente el último cambio git commit -a -m 'Agrega mensaje de despedida'