├── README.md ├── images ├── git1.png ├── git2.png ├── git3.png ├── git4.png ├── git5.png ├── git6.png └── stage.png └── taller_git.md /README.md: -------------------------------------------------------------------------------- 1 | # tallerDeGit 2 | 3 | Taller de Git de la materia "Introduccion a la Programacion" de la FCEyN - UBA. 4 | -------------------------------------------------------------------------------- /images/git1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git1.png -------------------------------------------------------------------------------- /images/git2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git2.png -------------------------------------------------------------------------------- /images/git3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git3.png -------------------------------------------------------------------------------- /images/git4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git4.png -------------------------------------------------------------------------------- /images/git5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git5.png -------------------------------------------------------------------------------- /images/git6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/git6.png -------------------------------------------------------------------------------- /images/stage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/introprog-dc/tallerDeGit/d0849c227162bf39556fba40045cc7bb49291b2c/images/stage.png -------------------------------------------------------------------------------- /taller_git.md: -------------------------------------------------------------------------------- 1 | # git 2 | 3 | git es una herramienta para la gestion de versiones de archivos. Esto quiere decir que nos facilita el versionado de nuestros archivos, permitiéndonos entre otras cosas: 4 | 5 | 1. entender cual es la última versión de un archivo 6 | 2. entender cual fue la cadena de modificaciones que le fuimos haciendo a lo largo del tiempo 7 | 3. trabajar en equipo con otros sobre los mismos archivos de manera ordenada 8 | 9 | Antes de ponernos a usar git vamos a ver primero otro comando: `diff`. 10 | 11 | ## diff 12 | 13 | Supongamos que estoy trabajando en una presentacion para dar una clase. Y que estoy trabajando en un archivo que se llama `presentacion.txt` donde voy anotando el contenido de la presentacion. 14 | 15 | Para que el ejemplo se entienda más fácilmente, lo vamos a ir haciendo juntos. 16 | 17 | Desde una sesión de Ubuntu, abrir la aplicacion "Editor de Textos" y crear un archivo de texto llamado `presentacion.txt` en el Escritorio. Agregar el siguiente contenido y guardarlo: 18 | 19 | ``` 20 | Esta es mi presentacion. La presentacion tiene estos temas: 21 | * tema 1 22 | * tema 2 23 | ``` 24 | 25 | Supongamos ahora que sigo trabajando en mi presentación, pero como voy a hacer cambios, primero hago un backup de mi archivo. 26 | 27 | Abrir una terminal (CTRL + ALT + T). Nos tiene que aparecer un prompt, que nos dice básicamente el nombre del usuario que estamos usando y la carpeta donde estamos posicionados: 28 | 29 | ``` 30 | Estudiante@pc1:~$ 31 | ``` 32 | 33 | En este caso el usuario se llama `Estudiante`, es un usuario de la máquina que se llama `pc1` y la carpeta donde estamos posicionados se llama `~` que es una forma abreviada de decir que estamos en la carpeta "home" del usuario (es decir, `/home/Estudiante`). 34 | 35 | Podemos cambiar de carpeta usando el comando `cd` (change directory). Como queremos que nuestro archivo quede en el escritorio vamos a hacer `cd Escritorio`: 36 | 37 | ``` 38 | Estudiante@pc1:~$ cd Escritorio/ 39 | Estudiante@pc1:~/Escritorio$ 40 | 41 | ``` 42 | 43 | Notar que el prompt cambio de `~` a `~/Escritorio`. Esto quiere decir que ahora estamos "parados" en la carpeta del Escritorio. 44 | 45 | Confirmamos que nuestro archivo existe en el escitorio: 46 | ``` 47 | Estudiante@pc1:~/Escritorio$ ls -l 48 | total 60 49 | -rw-rw-r-- 1 Estudiante Estudiante 78 may 1 13:14 presentacion.txt 50 | ``` 51 | 52 | Hacemos una copia de nuestra presentación usando el comando `cp` (copy): 53 | 54 | ``` 55 | cp presentacion.txt presentacion_v1.txt 56 | ``` 57 | 58 | Verificamos que tenemos los dos archivos y que ambos tienen el mismo tamano (78 bytes): 59 | 60 | ``` 61 | Estudiante@pc1:~/Escritorio$ ls -l 62 | total 60 63 | -rw-rw-r-- 1 Estudiante Estudiante 78 may 1 13:14 presentacion.txt 64 | -rw-rw-r-- 1 Estudiante Estudiante 78 may 1 13:14 presentacion_v1.txt 65 | ``` 66 | 67 | Ahora que tenemos backupeado nuestro archivo lo vamos a modificar. Desde el editor de texto que teníamos abierto, agregamos un nuevo tema: 68 | 69 | ``` 70 | Esta es mi presentacion. La presentacion tiene estos temas: 71 | * tema 1 72 | * tema 2 73 | * tema 3 74 | ``` 75 | 76 | Guardamos el archivo. 77 | 78 | Si listamos los archivos del Escritorio vamos a poder comprobar que efectivamente los tamaños de los archivos ahora son distintos (87 bytes vs 78 bytes): 79 | 80 | ``` 81 | ls -l 82 | Estudiante@pc1:~/Escritorio$ ls -l 83 | total 64 84 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:15 presentacion.txt 85 | -rw-rw-r-- 1 Estudiante Estudiante 78 may 1 13:15 presentacion_v1.txt 86 | ``` 87 | 88 | En este momento podemos utilizar el comando `diff` para ver las diferencias entre las 2 versiones de nuestra presentación: 89 | 90 | ``` 91 | Estudiante@pc1:~/Escritorio$ diff presentacion.txt presentacion_v1.txt 92 | 4d3 93 | < * tema 3 94 | ``` 95 | 96 | La salida de `diff` nos confirma que efectivamente los archivos son idénticos salvo por 1 línea que es diferente. 97 | Si miramos la salida de `diff` vamos a ver el signo '<' que indica que esa línea está en el archivo "de la izquierda", o el primer parámetro que le pasamos a `diff` (`presentacion.txt` en nuestro caso). 98 | 99 | Veamos qué pasa si ahora modificamos el otro archivo y le agregamos un tema 4. El archivo `presentacion_v1.txt` nos debería quedar asi: 100 | 101 | ``` 102 | Esta es mi presentacion. La presentacion tiene estos temas: 103 | * tema 1 104 | * tema 2 105 | * tema 4 106 | ``` 107 | 108 | Grabamos el archivo presentacion_v1.txt y volvemos a hacer diff: 109 | 110 | ``` 111 | Estudiante@pc1:~/Escritorio$ diff presentacion.txt presentacion_v1.txt 112 | 4c4 113 | < * tema 3 114 | --- 115 | > * tema 4 116 | ``` 117 | 118 | Ahora es mas claro que `diff` nos esta avisando que la línea que menciona al tema 3 sólo está en el primer archivo, y la que menciona al tema 4 está sólo en el segundo archivo. 119 | 120 | NOTA: `diff` tambien nos está diciendo `4c4`, que significa que la línea 4 del primer archivo cambió (c=changed) respecto de la línea 4 del segundo archivo. En el caso anterior nos decía 4d3, lo que significa que la línea 4 del archivo de la izquierda fue eliminada (d=deleted) en el segundo archivo. 121 | 122 | NOTA: la mayoría de los comandos de linux tienen una ayuda disponible en la forma de un "manual de instrucciones". Para ver el de `diff` ejecutar desde una terminal `man diff` 123 | 124 | Ahora que podemos ver los cambios entre las diferentes versiones del archivo podemos trabajar con un poco más de tranquilidad ya que podemos entender más facilmente cuáles son las diferencias entre ellos. 125 | 126 | Por ejemplo, podría darse el caso de que quieren trabajar en en la presentación en una computadora de la facultad durante el día y en mi casa por la noche. Entonces cada vez que copio los archivos podria hacer un diff para verificar que tengo todos los cambios y no estoy pisando por error cambios que me interesan. 127 | 128 | 129 | ## usando git 130 | 131 | git nos va a permitir ir entendiendo las diferencias entre nuestros archivos de forma más sencilla. 132 | 133 | NOTA: como las máquinas de los laboratorios son compartidas vamos a ejecutar una limpieza de archivos y comandos que puedan haber quedado guardados de antes: 134 | 135 | ``` 136 | Estudiante@pc1:~/Escritorio$ rm -rf ~/Escritorio/.git 137 | Estudiante@pc1:~/Escritorio$ git config --global --unset-all user.email 138 | Estudiante@pc1:~/Escritorio$ git config --global --unset-all user.name 139 | ``` 140 | 141 | Ahora sí, vamos a inicializar un "repositorio" que es el nombre que le da git a una colección de archivos: 142 | 143 | ``` 144 | Estudiante@pc1:~/Escritorio$ git init 145 | Inicializado repositorio Git vacío en /home/Estudiante/Escritorio/.git/ 146 | ``` 147 | 148 | Si listamos el contenido de la carpeta vamos a seguir viendo nuestros archivos: 149 | 150 | ``` 151 | Estudiante@pc01:~/Escritorio$ ls -l 152 | total 64 153 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:15 presentacion.txt 154 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:22 presentacion_v1.txt 155 | ``` 156 | 157 | Pero si agregamos la opcion `-a` vamos a poder ver una carpeta oculta llamada `.git`: 158 | 159 | ``` 160 | Estudiante@pc1:~/Escritorio$ ls -l -a 161 | total 76 162 | drwxr-xr-x 6 Estudiante Estudiante 4096 may 1 13:38 . 163 | drwxr-xr-x 97 Estudiante Estudiante 4096 may 1 13:22 .. 164 | drwxrwxr-x 7 Estudiante Estudiante 4096 may 1 13:38 .git 165 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:15 presentacion.txt 166 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:22 presentacion_v1.txt 167 | ``` 168 | 169 | NOTA: también aparecen 2 carpetas más: '.', que representa la carpeta actual y '..' que representa a la carpeta "padre" de la actual. Es por esto que si hacemos `cd ..` cambiamos de carpeta a la que esta en el nivel superior. Y de la misma forma si hacemos `cd .` nos quedamos posicionados en la misma carpeta donde estamos. 170 | 171 | Podemos ver que en la carpeta `.git` hay varios archivos y carpetas: 172 | 173 | ``` 174 | Estudiante@pc1:~/Escritorio$ ls -l .git 175 | total 32 176 | drwxrwxr-x 2 Estudiante Estudiante 4096 may 1 13:38 branches 177 | -rw-rw-r-- 1 Estudiante Estudiante 92 may 1 13:38 config 178 | -rw-rw-r-- 1 Estudiante Estudiante 73 may 1 13:38 description 179 | -rw-rw-r-- 1 Estudiante Estudiante 23 may 1 13:38 HEAD 180 | drwxrwxr-x 2 Estudiante Estudiante 4096 may 1 13:38 hooks 181 | drwxrwxr-x 2 Estudiante Estudiante 4096 may 1 13:38 info 182 | drwxrwxr-x 4 Estudiante Estudiante 4096 may 1 13:38 objects 183 | drwxrwxr-x 4 Estudiante Estudiante 4096 may 1 13:38 refs 184 | 185 | ``` 186 | 187 | Estos archivos y carpetas son internos a git y son los que va a usar para llevar la cuenta de las modificaciones que vamos realizando, por lo que no los vamos a modificar. 188 | 189 | Ahora podemos preguntarle a git cuál es el estado de los archivos a través del comando `git status`: 190 | 191 | ``` 192 | Estudiante@pc1:~/Escritorio$ git status 193 | En la rama master 194 | 195 | No hay commits todavía 196 | 197 | Archivos sin seguimiento: 198 | (usa "git add ..." para incluirlo a lo que se será confirmado) 199 | presentacion.txt 200 | presentacion_v1.txt 201 | 202 | no hay nada agregado al commit pero hay archivos sin seguimiento presentes (usa "git add" para hacerles seguimiento) 203 | ``` 204 | 205 | Lo que nos está diciendo git es que: 206 | 1. Existen 2 archivos de texto (nuestras presentaciones) pero que no están bajo el control de git (es decir, que git los desconoce) 207 | 2. Que podemos usar el comando `git add` para empezar a trackearlos 208 | 209 | Como nos interesa seguir trabajando en nuestra presentación vamos a pedirle a git que lo empiece a "seguir". Para esto usamos `git add`: 210 | 211 | ``` 212 | Estudiante@pc1:~/Escritorio$ git add presentacion.txt 213 | Estudiante@pc1:~/Escritorio$ 214 | ``` 215 | 216 | Vemos que el comando no genera ningun mensaje por pantalla. Así que la forma de confirmar que hubo algun cambio es volver a pedirle el status: 217 | 218 | ``` 219 | Estudiante@pc1:~/Escritorio$ git status 220 | En la rama master 221 | 222 | No hay commits todavía 223 | 224 | Cambios a ser confirmados: 225 | (usa "git rm --cached ..." para sacar del área de stage) 226 | nuevos archivos: presentacion.txt 227 | 228 | Archivos sin seguimiento: 229 | (usa "git add ..." para incluirlo a lo que se será confirmado) 230 | presentacion_v1.txt 231 | ``` 232 | 233 | Esto nos confirma que `presentacion.txt` esta ahora bajo el radar de git, pero sin embargo necesitamos confirmarle a git que realmente queremos que lo siga. Esta confirmación (commitment) lo hacemos a través del comando `git commit`: 234 | 235 | ``` 236 | Estudiante@pc1:~/Escritorio$ git commit -m "version inicial de la presentacion" 237 | [master (root-commit) f1b6010] version inicial de la presentacion 238 | 1 file changed, 4 insertions(+) 239 | create mode 100644 presentacion.txt 240 | ``` 241 | 242 | NOTA: si es nuestro primer commit git nos va a pedir que nos identifiquemos: 243 | 244 | ``` 245 | Estudiante@pc1:~/Escritorio$ git commit -m "version inicial de la presentacion" 246 | 247 | *** Por favor cuéntame quién eres. 248 | 249 | Ejecuta 250 | 251 | git config --global user.email "you@example.com" 252 | git config --global user.name "Tu Nombre" 253 | 254 | para configurar la identidad por defecto de tu cuenta. 255 | Omite --global para configurar tu identidad solo en este repositorio. 256 | 257 | fatal: no se puede tener un nombre de identidad vacío (para ) 258 | ``` 259 | 260 | Como las máquinas de los laboratorios son compartidas vamos a realizar la configuracion de manera local (omitiendo el parametro `--global`): 261 | 262 | ``` 263 | Estudiante@pc1:~/Escritorio$ git config user.email [direccion de mail] 264 | Estudiante@pc1:~/Escritorio$ git config user.name [Nombre y Apellido entre comillas] 265 | ``` 266 | 267 | NOTA: podemos ver la configuracion de git ejecutando `git config --list`. 268 | 269 | 270 | NOTA: git nos pide que cada vez que confirmemos un cambio (commit) pongamos un mensaje breve que nos permita entender (a nosotros mismos o a otros) de qué se trata el cambio que estamos haciendo. Este mensaje es el que le pasamos cuando pusimos la opcion `-m mensaje` como parametro de `git commit`: 271 | 272 | ``` 273 | Estudiante@pc1:~/Escritorio$ git commit -m "version inicial de la presentacion" 274 | [master (root-commit) f1b6010] version inicial de la presentacion 275 | 1 file changed, 4 insertions(+) 276 | create mode 100644 presentacion.txt 277 | ``` 278 | 279 | Si volvemos a pedir el status vamos a ver que ahora git ya no nos dice nada sobre `presentacion.txt` (aunque nos sigue diciendo que existe `presentacion_v1.txt`, pero que no le esta haciendo seguimiento): 280 | 281 | ``` 282 | Estudiante@pc1:~/Escritorio$ git status 283 | En la rama master 284 | Archivos sin seguimiento: 285 | (usa "git add ..." para incluirlo a lo que se será confirmado) 286 | presentacion_v1.txt 287 | 288 | no hay nada agregado al commit pero hay archivos sin seguimiento presentes (usa "git add" para hacerles seguimiento) 289 | ``` 290 | 291 | Ahora que hemos confirmado el cambio sobre `presentacion.txt`, esto significa que podemos preguntarle a git específicamente por su historial de cambios: 292 | 293 | ``` 294 | Estudiante@pc1:~/Escritorio$ git log presentacion.txt 295 | commit f1b601081919422cd86112a137bad52c9c0dce61 (HEAD -> master) 296 | Author: Usuario generico 297 | Date: Mon May 1 13:52:14 2023 -0300 298 | 299 | version inicial de la presentacion 300 | ``` 301 | 302 | NOTA: podemos ver que nuestro commit tiene un valor hexadecimal asociado que es el resultado de aplicar una función de hash sobre nuestros cambios. Cada vez que hacemos un commit, git calcula un nuevo hash y lo asocia al commit. Esto le permite identificar de manera unívoca a cada uno de los commits que vamos haciendo. 303 | 304 | Ahora podemos seguir trabajando en nuestra presentación y seguirle sumando cambios. Por ejemplo, podemos agregar un tema 5 y eliminar el tema 1: 305 | 306 | ``` 307 | Esta es mi presentacion. La presentacion tiene estos temas: 308 | * tema 2 309 | * tema 3 310 | * tema 5 311 | ``` 312 | 313 | Dado que `presentacion.txt`` está bajo la gestión de git, entonces podemos preguntarle cuáles son las diferencias con la versión que git conoce. Para esto usamos el comando `git diff`: 314 | 315 | ``` 316 | Estudiante@pc1:~/Escritorio$ git diff presentacion.txt 317 | diff --git a/presentacion.txt b/presentacion.txt 318 | index 7f110c6..c13e96b 100644 319 | --- a/presentacion.txt 320 | +++ b/presentacion.txt 321 | @@ -1,4 +1,4 @@ 322 | Esta es mi presentacion. La presentacion tiene estos temas: 323 | -* tema 1 324 | * tema 2 325 | * tema 3 326 | +* tema 5 327 | ``` 328 | 329 | La salida es parecida a la que vimos cuando ejecutabamos `diff` a mano, pero es un poco más detallada: 330 | 331 | * nos dice que hay una línea que fue eliminada (-) 332 | * nos dice que hay una línea que fue agregada (+) 333 | * nos dice que los cambios estan entre las lineas 1 y 4 del archivo 334 | 335 | Es decir, que además de darnos las diferencias, nos muestra un poco más de contexto para que nos resulte más fácil entenderlas. 336 | 337 | Si estamos satisfechos con los cambios que hicimos, entonces le decimos a git que queremos agregar los cambios del archivo (`git add`) y se lo confirmamos (`git commit`): 338 | 339 | ``` 340 | Estudiante@pc1:~/Escritorio$ git add presentacion.txt 341 | Estudiante@pc1:~/Escritorio$ git commit -m "agregue tema. saque tema" 342 | [master 2cc3337] agregue tema. saque tema 343 | 1 file changed, 1 insertion(+), 1 deletion(-) 344 | ``` 345 | 346 | Nuevamente, en la última línea del mensaje, git nos está resumiendo los cambios que detectó desde la última vez que le mandamos el archivo (1 inserción, 1 borrado). 347 | 348 | Si pedimos la historia del archivo vamos a ver los 2 cambios/versiones, ordenados de más reciente a menos reciente: 349 | 350 | ``` 351 | Estudiante@pc1:~/Escritorio$ git log 352 | commit 2cc3337d5efbe503a3f69af0084eab5b51475262 (HEAD -> master) 353 | Author: Usuario generico 354 | Date: Mon May 1 14:04:22 2023 -0300 355 | 356 | agregue tema. saque tema 357 | 358 | commit f1b601081919422cd86112a137bad52c9c0dce61 359 | Author: Usuario generico 360 | Date: Mon May 1 13:52:14 2023 -0300 361 | 362 | version inicial de la presentacion 363 | ``` 364 | 365 | De está forma evitamos tener que ir recordando los cambios que vamos haciendo, ya que git lo hace por nosotros. También nos permite volver a versiones anteriores y muchas cosas más. Pero antes de verlas, vamos a ver un poco más en detalle por qué el proceso de cambios se hace en 2 etapas. 366 | 367 | ## stages 368 | 369 | Podemos pensar que en principio hay 2 mundos: uno donde nosotros somos dueños de los archivos y sobre los que git no sabe nada ni tiene potestad, y otro donde git es el responsable de gestionar los cambios de los archivos que conoce. 370 | 371 | Entonces lo que queremos hacer es ir avisándole sobre los archivos que queremos incluir bajo su control de versiones. Podemos pensar que la forma en que vamos pasando archivos de un mundo al otro es a traves de `git add`. 372 | 373 | La gran ventaja que tiene git es que no se olvida de nada de lo que va pasando. Es decir, cada modificación de un archivo la registra. Esto puede ser un problema, por ejemplo, si queremos que se "olvide" de algunos archivos que ya no nos sirven más. El proceso para eliminar un archivo del control de versiones es: 374 | 375 | 1. git rm [archivo] 376 | 2. git commit [archivo] -m [mesaje] 377 | 378 | El inconveniente es que si bien git nos va a confirmar que ya no sabe nada de nuestro archivo borrado la realidad es que sigue guardando toda la historia hasta ese momento. Es decir, hay archivos dentro de la carpeta `.git` que siguen guardando la información de cambios histórica del archivo. 379 | Esto puede ser un problema si somos ansiosos y agregamos un montón de archivos y luego nos arrepentimos, ya que igual quedarian en la historia de git. 380 | 381 | Para evitar ese problema (y otros) git usa un tercer "mundo" que es un intermedio entre el mundo de git y el de nuestros archivos no-versionados. Esta area de pruebas o `stage` es donde se van agregando los cambios hasta que se confirman (commit). El comando commit es el que termina pasando los cambios al mundo de git. 382 | 383 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/stage.png?raw=true) 384 | 385 | 386 | Es por esta razón que cada vez que hacemos un add, tenemos que hacer un commit si queremos que nuestro cambio sea tomado efectivamente por git. 387 | 388 | NOTA: podría darse el caso de que hayamos agregado algun archivo por error. Esto es muy común si hicimos `git add .` o `git add presentacion*` porque en esos casos git va a interepretar que queremos incorporar un grupo de archivos. Entonces podría ser que se haya agregado algun archivo por error. En estos casos, la salida de `git status` nos dice como solucionarlo: 389 | 390 | ``` 391 | Estudiante@pc1:~/Escritorio$ ls -l presen* 392 | -rw-rw-r-- 1 Estudiante Estudiante 96 may 7 13:40 presentacion.txt 393 | -rw-rw-r-- 1 Estudiante Estudiante 87 may 1 13:22 presentacion_v1.txt 394 | Estudiante@pc1:~/Escritorio$ git add presen* 395 | Estudiante@pc1:~/Escritorio$ git status . 396 | On branch master 397 | Changes to be committed: 398 | (use "git restore --staged ..." to unstage) <---- ACA 399 | modified: presentacion.txt 400 | new file: presentacion_v1.txt 401 | ``` 402 | 403 | Entonces si queremos sacar `presentacion_v1.txt`, lo hacemos con `git restore --staged`: 404 | 405 | 406 | ``` 407 | Estudiante@pc1:~/Escritorio$ git restore --staged presentacion_v1.txt 408 | Estudiante@pc1:~/Escritorio$ git status . 409 | On branch master 410 | Changes to be committed: 411 | (use "git restore --staged ..." to unstage) 412 | modified: presentacion.txt 413 | 414 | Untracked files: 415 | (use "git add ..." to include in what will be committed) 416 | presentacion_v1.txt 417 | ``` 418 | 419 | Nuevamente, esto es posible porque existe el stage intermedio que permite "arrepentirse" antes de confirmar con `git commit`. 420 | 421 | ## trabajo en grupo 422 | 423 | Hasta ahora todos los ejemplos que hicimos fueron considerando el trabajo individual de 1 sola persona. Sin embargo, esto no es un escenario realista en el contexto de un proyecto de desarrollo de software, donde hay grupos de programadores trabajando sobre el mismo código. 424 | Sin ir más lejos, el trabajo práctico de la materia se realiza de manera grupal. 425 | 426 | Cuando hay varias personas trabajando sobre el mismo grupo de archivos es necesario que haya algun tipo de acuerdo en la forma en que se va a trabajar, para lograr que los cambios se hagan de manera ordenada. 427 | 428 | Retomando el ejemplo de la presentación, podría pedirle a mis compañeros de equipo que me ayuden a completar los slides para avanzar más rápido. Para esto vamos a necesitar que todos accedan al mismo repositorio (hasta ahora mi repositorio era local, por lo que solo podía ser usado por mí en la computadora donde lo cree usando `git init`). 429 | 430 | ### repositorio remoto 431 | 432 | Para poder compartir el repositorio entre varias personas lo que vamos a hacer es armar un repositorio de git remoto, es decir, que va a estar corriendo como un servicio en alguna máquina de la red que sea accesible por todos los integrantes del proyecto. Una posibilidad seria instalar y configurar ese servicio en una máquina del laboratorio, de esa forma seria accessible desde cualquier otra máquina en la red del laboratorio. 433 | 434 | Generalmente lo que se suele hacer es hacer que ese servicio este disponible a través de un servicio web, de la misma forma que una pagina web. Por ejemplo, los siguientes son servicios que ofrecen git y pueden ser utilizados por cualquiera que tenga acceso a Internet: 435 | 436 | * http://www.github.com 437 | * http://www.gitlab.com 438 | 439 | Por ejemplo, si la decision es usar github entonces todos los integrantes del proyecto deberían crearse una cuenta en ese servicio y a partir de ese momento podrian utilizar los mismos comandos de git que estuvimos viendo (más algunos comandos adicionales que vamos a ver en breve). 440 | 441 | La idea principal del repositorio remoto es que va funcionar como la "verdad última" (`ultimate source of truth`) respecto de cuál es la última versión de cada uno de los archivos que este bajo la administración de git. 442 | 443 | ### flujo de trabajo 444 | 445 | Para hacer esta parte vamos a usar este repositorio: https://github.com/introprog-dc/tallerDeGit 446 | 447 | La idea es usar este proyecto es entender mejor cómo funciona un flujo de trabajo de múltiples personas colaborando en un mismo repositorio. 448 | 449 | Lo primero es que cada uno de los integrantes del proyecto obtenga una copia del repositorio. Esto se puede hacer de varias maneras, pero nosotros lo vamos a hacer a traves de un `fork` para evitar pisarnos con otros alumnos haciendo las mismas pruebas. 450 | 451 | Entonces lo primero que vamos a hacer es clickear en el botón `fork`: 452 | 453 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/git1.png?raw=true) 454 | 455 | Para poder realizar esta acción github nos va a pedir que nos logueemos con una cuenta de usuario válida (o que creemos una nueva). 456 | 457 | Una vez logueados, confirmamos el nombre que va a tener nuestro fork, y finalmente clickeamos en `create fork` 458 | 459 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/git2.png?raw=true) 460 | 461 | Ahora vemos una copia (fork) del repositorio original. Esta copia es el repositorio que vamos a usar como proyecto. 462 | 463 | Entonces cada uno de los integrantes del grupo debe clonar usando `git clone`. Para esto podemos clickear en el botón que dice `code` y copiar la URL que figura ahí. Como siempre, abrimos una terminal en nuestra computadora y hacemos `git clone`. 464 | 465 | NOTA: antes de poder clonar, vamos a generar un token: https://github.com/settings/tokens. Esto lo vamos a hacer para simplificar nuestros ejemplos. En la vida real sería más prolijo configurar una clave SSH para interactuar con el repositorio remoto. 466 | 467 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/git4.png?raw=true) 468 | 469 | Seleccionar la opción para generar un token "classic", y asegurarse luego de tildar la opción "repo". 470 | 471 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/git5.png?raw=true) 472 | 473 | NOTA: es MUY importante anotar el token en algun lugar seguro (idealmente un password manager) ya que github nos lo va a mostrar 1 sola vez. Si nos olvidamos el token vamos a tener que generar uno nuevo. 474 | 475 | NOTA: también es muy importante que al finalizar nuestro trabajo en las máquinas de los laboratorios borremos el repositorio local, ya que el token queda guardado en los archivos internos de git, por lo que otra persona podria hacer cambios en nuestro fork (el repositorio original desde donde forkeamos se mantendria inalterado). 476 | 477 | ![](https://github.com/introprog-dc/tallerDeGit/blob/main/images/git6.png?raw=true) 478 | 479 | Ahora sí, usando nuestro nombre de usuario vamos a clonar el repositorio. Como el repositorio es público, git no nos va a pedir el token para clonar, pero sí para pushear en el repo (lo haremos más adelante). 480 | 481 | ``` 482 | Estudiante@pc1:$ git clone https://github.com/miNombreDeUsuario/tallerDeGit 483 | Cloning into 'tallerDeGit'... 484 | remote: Enumerating objects: 9, done. 485 | remote: Counting objects: 100% (9/9), done. 486 | remote: Compressing objects: 100% (7/7), done. 487 | remote: Total 9 (delta 1), reused 0 (delta 0), pack-reused 0 488 | Receiving objects: 100% (9/9), 9.82 KiB | 2.45 MiB/s, done. 489 | Resolving deltas: 100% (1/1), done. 490 | 491 | ``` 492 | 493 | Si hacemos `ls -l` vemos que se creó un nuevo directorio llamado `tallerDeGit`: 494 | 495 | ``` 496 | Estudiante@pc1:~/Escritorio$ ls -l 497 | drwxrwxr-x 3 Estudiante Estudiante 4096 may 3 20:41 tallerDeGit/ 498 | ``` 499 | 500 | Para poder trabajar más cómodos vamos a posicionarnos dentro de la carpeta, haciendo `cd`: 501 | 502 | ``` 503 | Estudiante@pc1:~/Escritorio$ cd tallerDeGit 504 | Estudiante@pc1:~/Escritorio/tallerDeGit$ 505 | ``` 506 | 507 | En este momento podemos usar los comandos que vimos anteriormente. Por ejemplo, podemos ejecutar `git log` para ver los cambios que se hicieron hasta el momento en el repositorio original. 508 | 509 | NOTA: la salida de `git log` puede ser larga, por lo que tiene incoporado un mecanismo que va mostrando las siguientes lineas a medida que vamos presionando ENTER. Para volver a tomar control de la terminal hay que apretar la tecla `q`. 510 | 511 | En este momento vamos a modificar uno de los archivos. Podemos agregar, borrar o cambiar el contenido existente. Por ejemplo, podemos modificar el archivo `README.md`: 512 | 513 | * Editar y modificar el archivo `README.md` usando un editor de texto. Guardar el cambio. 514 | * Agregar el cambio al stage: `git add` 515 | * Agregar el cambio a un commit: `git commit` 516 | * Enviar el cambio al repositorio global: `git push` 517 | 518 | Como siempre, vamos a llevar el archivo al área de stage con `git add` y vamos a confirmar el cambio con `git commit -m [mensaje]`. 519 | La diferencia principal es que los cambios que tenemos commiteados solo están por ahora en nuestra máquina. Para que el repositorio remoto se entere de que hicimos cambios se lo tenemos que notificar usando el comando `git push`. Escribimos nuestro nombre de usuario de github y luego el token como la contraseña. 520 | 521 | NOTA: la terminal no nos va a dar feedback sobre las teclas que tipeemos cuando ingresamos la contraseña. Esto es por seguridad, ya que de otra forma la persona que esta al lado nuestor podria espiarla. 522 | 523 | ``` 524 | Estudiante@pc1:~/Escritorio/tallerDeGit$ git push 525 | Username for 'https://github.com': miNombreDeUsuario 526 | Password for 'https://miNombreDeUsuario@github.com': 527 | Enumerating objects: 5, done. 528 | Counting objects: 100% (5/5), done. 529 | Delta compression using up to 8 threads 530 | Compressing objects: 100% (2/2), done. 531 | Writing objects: 100% (3/3), 314 bytes | 314.00 KiB/s, done. 532 | Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 533 | To https://github.com/miNombreDeUsuario/tallerDeGit 534 | c1dd4ca..721f61f main -> main 535 | ``` 536 | 537 | Ahora sí, si vamos a la interfaz web del proyecto, vveremos que se registró el cambio que acabamos de confirmar. 538 | 539 | El resto de las personas que trabajan con nosotros en el proyecto van a estar realizando cambios tambien en sus copias locales, y pusheandolas eventualmente al repositorio remoto. Para obtener esos cambios realizados por otros (si los hubiera) es que vamos a realizar `git pull`: 540 | 541 | ``` 542 | Estudiantepc1:~/Escritorio/tallerDeGit$ git pull 543 | Already up to date. 544 | ``` 545 | 546 | Básicamente lo que hace `git pull` es hacer un diff de nuestro repositorio local contra el remoto, y aplicar las diferencias (patches) en el orden correcto para que ambos queden sincronizados. 547 | La mayor parte del tiempo es probable que los cambios realizados por distintos colaboradores no se interfieran entre sí. En esos casos alcanza con el flujo `pull -> add -> commit -> push`. Sin embargo, pueden darse situaciones donde se generen conflictos. Veamos como manejarnos en esos casos. 548 | 549 | ### resolviendo conflictos 550 | 551 | Supongamos el siguiente escenario: 552 | 553 | 1. los usuarios U1 y U2 trabajan en el mismo proyecto 554 | 2. el usuario U1 clona el repositorio remoto. el usuario U2 hace lo mismo al mismo tiempo. Es decir, que los repositorios locales de U1 y U2 comienzan sincronizados 555 | 3. U1 modifica un archivo (README.md). commitea y pushea el cambio al repositorio remoto 556 | 4. U2 tambien modifica el mismo archivo, pero lo hace despues que U1. Entonces cuando U2 hace commit y push, git le avisa que su repositorio no está al día, por lo que debe hacer primero un `git pull` 557 | 5. U2 hace un `git pull` pero dado que hay una nueva versión del README.md en el repositorio remoto, git intenta fusionar (mergear) ambas copias en el repositorio local de U2. Pueden darse 2 escenarios: 558 | i. los cambios de U1 y U2 son compatibles. por ejemplo: U1 cambio la línea 1 y U2 la línea 2 del README.md. En este caso git aplica ambos cambios y U2 termina con una versión que incluye tanto sus cambios como los del repositorio remoto. En este caso puede subir la versión final haciendo `git add` y `git push` 559 | ii. los cambios de U1 y U2 son conflictivos. Por ejemplo: ambos U1 y U2 modificaron la misma línea de maneras diferentes. En este punto git no puede resolver automáticamente el conflicto y le pide a U2 que lo resuelva manualmente. Una vez que U2 decide que hacer (si dejar su cambio o tomar el de U1) confirma el cambio y hace push 560 | 561 | Es decir, git va a intentar aplicar todos los cambios posibles siempre que no sean conflictivos. Y si hay conflicto le va a pedir al usuario que lo resuelva. 562 | 563 | Probemos resolver un conflicto. Para esto vamos a simular que somos 2 usuarios diferentes clonando el mismo repositorio en 2 carpetas diferentes de la misma máquina: 564 | 565 | ``` 566 | cd Escritorio 567 | mkdir repo1 568 | cd repo1 569 | git clone https://github.com/miNombreDeUsuario/tallerDeGit 570 | cd .. 571 | mkdir repo2 572 | cd repo2 573 | git clone https://github.com/miNombreDeUsuario/tallerDeGit 574 | cd.. 575 | ``` 576 | 577 | En este momento tenemos 2 copias del mismo proyecto. Podemos ver que los contenidos de repo1 y repo2 tienen la misma estructura: 578 | 579 | ``` 580 | Estudiante@pc1:/tmp$ ls -lR repo* 581 | repo1: 582 | total 4 583 | drwxrwxr-x 3 Estudiante Estudiante 4096 may 3 22:00 tallerDeGit 584 | 585 | repo1/tallerDeGit: 586 | total 32 587 | -rw-rw-r-- 1 Estudiante Estudiante 34 may 3 22:00 README.md 588 | -rw-rw-r-- 1 Estudiante Estudiante 25272 may 3 21:59 taller_git.md 589 | 590 | repo2: 591 | total 4 592 | drwxrwxr-x 3 Estudiante Estudiante 4096 may 3 22:10 tallerDeGit 593 | 594 | repo2/tallerDeGit: 595 | total 32 596 | -rw-rw-r-- 1 Estudiante Estudiante 34 may 3 22:10 README.md 597 | -rw-rw-r-- 1 Estudiante Estudiante 25272 may 3 22:10 taller_git.md 598 | ``` 599 | 600 | Modificamos el README.md del repo1 usando el Editor de Textos y guardamos el archivo. Luego desde la terminal pusheamos el cambio: 601 | 602 | ``` 603 | cd repo1 604 | cd tallerDeGit 605 | git status 606 | git add README.md 607 | git commit -m "hice un cambio en la primer línea" 608 | git push 609 | ``` 610 | 611 | El push funciona correctamente. 612 | 613 | Hacemos ahora una modificación en el README.md del repo2 y guardamos el archivo teniendo en cuenta modificar la misma línea pero con diferente contenido. E intentamos pushear con los mismos comandos: 614 | 615 | 616 | ``` 617 | cd .. 618 | cd .. 619 | cd repo2 620 | cd tallerDeGit 621 | git status 622 | git add README.md 623 | git commit -m "hice otro cambio en la primer línea" 624 | git push 625 | ``` 626 | 627 | En este punto el push va a fallar y git nos va a decir que hay cambios en el repositorio remoto que no tenemos: 628 | 629 | ``` 630 | Estudiante@pc1:~/Escritorio/repo2/tallerDeGit$ git push 631 | To https://github.com/miNombreDeUsuario/tallerDeGit 632 | ! [rejected] main -> main (fetch first) 633 | error: failed to push some refs to 'https://github.com/miNombreDeUsuario/tallerDeGit' 634 | hint: Updates were rejected because the remote contains work that you do 635 | hint: not have locally. This is usually caused by another repository pushing 636 | hint: to the same ref. You may want to first integrate the remote changes 637 | hint: (e.g., 'git pull ...') before pushing again. 638 | hint: See the 'Note about fast-forwards' in 'git push --help' for details. 639 | ``` 640 | 641 | Hacemos `git pull`, pero nos vuelve a aparecer un mensaje donde git nos pide que configuremos una estrategia de merge: 642 | 643 | ``` 644 | Estudiante@pc1:~/Escritorio/repo2/tallerDeGit$ git pull 645 | remote: Enumerating objects: 5, done. 646 | remote: Counting objects: 100% (5/5), done. 647 | remote: Compressing objects: 100% (2/2), done. 648 | remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 649 | Unpacking objects: 100% (3/3), 307 bytes | 307.00 KiB/s, done. 650 | From https://github.com/miNombreDeUsuario/tallerDeGit 651 | 721f61f..1ec3bed main -> origin/main 652 | hint: You have divergent branches and need to specify how to reconcile them. 653 | hint: You can do so by running one of the following commands sometime before 654 | hint: your next pull: 655 | hint: 656 | hint: git config pull.rebase false # merge (the default strategy) 657 | hint: git config pull.rebase true # rebase 658 | hint: git config pull.ff only # fast-forward only 659 | hint: 660 | hint: You can replace "git config" with "git config --global" to set a default 661 | hint: preference for all repositories. You can also pass --rebase, --no-rebase, 662 | hint: or --ff-only on the command line to override the configured default per 663 | hint: invocation. 664 | fatal: Need to specify how to reconcile divergent branches. 665 | ``` 666 | 667 | Vamos a usar la estrategia default: 668 | 669 | ``` 670 | git config pull.rebase false 671 | ``` 672 | 673 | Y ahora volvemos a hacer pull: 674 | 675 | ``` 676 | Estudiante@pc1:~/Escritorio/repo2/tallerDeGit$ git pull 677 | Auto-merging README.md 678 | CONFLICT (content): Merge conflict in README.md 679 | Automatic merge failed; fix conflicts and then commit the result. 680 | ``` 681 | 682 | Si vemos el mensaje de error git nos dice que tenemos que editar el README.md de repo2 y solucionar el conflicto que se generó. 683 | 684 | Si abrimos el archivo en el Editor de Textos vamos a ver que hay bloques de texto que no estaban en el archivo original (fueron agregados por git): 685 | 686 | ``` 687 | # tallerDeGit 688 | Taller de Git 689 | Hola! 690 | <<<<<<< HEAD 691 | Manola! 692 | ======= 693 | Chau! 694 | >>>>>>> 1ec3bedd04acd9bfc842a8b2ee466f73f138d473 695 | ``` 696 | 697 | En este punto tenemos que decidir cuál de los dos cambios dejamos. No hay una regla general sobre cómo hacerlo y muchas veces probablemente tenga sentido comunicarnos con el usuario que hizo el otro cambio para ponernos de acuerdo en cuál es la mejor version. 698 | 699 | Y ahora sí podemos pushear 700 | 701 | ``` 702 | git add README.md 703 | git commit -m "hice otro cambio en la primer línea" 704 | git push 705 | ``` 706 | 707 | Si ahora volvemos a la carpeta repo1 y hacemos `git diff` no vamos a ver ninguna diferencia todavia. Esto es porque para tomar los nuevos cambios tenemos que hacer `git pull`: 708 | 709 | ``` 710 | cd .. 711 | cd repo1 712 | git diff README.md 713 | ``` 714 | 715 | Para sincronizar repo2 podemos hacer `git pull`: 716 | 717 | ``` 718 | git pull 719 | ``` 720 | 721 | y ahora sí ambas carpetas están sincronizadas con el repositorio remoto. 722 | 723 | ## antes de finalizar 724 | 725 | Dado que estamos usando computadoras compartidas, vamos a dejar el ambiente ordenado y listo para que otra persona pueda realizar las mismas pruebas que hicimos nosotros. Para esto vamos a: 726 | 727 | 1. eliminar los archivos `presentacion.txt` y `presentacion_v1.txt` que hayamos creado en el Escritorio del usuario `Estudiante` 728 | 1. eliminar la carpeta `.git` que quedo en el Escritorio: `rm -rf ~/Escritorio/.git` 729 | 1. eliminar las copias de nuestros repositorios locales: `rm -rf ~/Escritorio/repo1 && rm -rf ~/Escritorio/repo2` 730 | 1. eliminar el historial de la terminal: `history -c && history -w` 731 | 732 | En el caso en que nos interese seguir trabajando sólo tenemos que continuar usando nuestro repositorio remoto con el token correspondiente. 733 | 734 | Si bien en los ejemplos que vimos usamos la versión de línea de comando, existen aplicaciones con interfaz gráfica para simplificar la experiencia de uso. Ahora que tienen conocimientos básicos de cómo utilizar git, van a poder entender fácilmente cuáles son los comandos que se están ejecutando por detras. 735 | 736 | Recuerden que todos los comandos de git tienen una ayuda en línea a la que pueden acceder ejecutando el comando con el agregado de la opcion `-h` o usando el comando `help`. Por ejemplo: `git add -h` da la versión de ayuda corta y `git help add` la versión larga. 737 | 738 | Por ultimo, hay mucho material disponible en la red sobre git, sus comandos y las múltiples formas de usarlo. Estan más que invitados a seguir explorando git por su cuenta :) 739 | 740 | 741 | ## links 742 | 743 | - git (pagina oficial): https://git-scm.com/ 744 | - github + git: https://docs.github.com/es/get-started/using-git/about-git 745 | --------------------------------------------------------------------------------