Ejercicios
Esta guía de ejercicios se divide en dos secciones:
- Usuario único y
- Multi-usuario.
En “usuario único”, vamos a:
- crear un repositorio local,
- agregar archivos,
- crear commits, puntos de control en la historia del repositorio, y
- navegar por diferentes puntos de la historia.
En “Multi-usuario”, vamos a:
- sincronizar el repositorio con “otro” usuario, y
- publicar en GitHub.
1 Requisitos
Para los siguientes ejercicios, se requiere solamente tener instalado git.
Si se tiene instalado VS Code, se puede abrir en la carpeta donde se creará el repositorio de git. Con VS Code, vamos a poder:
- visualizar los cambios que hacen los comandos de git en la solapa “Control de Versiones”,
- correr los comandos de git en la terminal de VS Code.
2 Ayuda y documentación
Para ver la ayuda de git, correr git help.
Para ver la ayuda de un subcommando, correr git help [SUBCOMMAND].
3 Usuario único
git initgit addgit rmgit commitgit restoregit resetgit checkoutgit branchgit mergegit rebase
3.1 Crear repositorio
Objetivo: crear un repositorio local y configurar la identidad.
- Crear un directorio para el proyecto y entrar en ese directorio.
- Inicializar Git en ese directorio.
- Configurar nombre de usuario y correo.
mkdir <NAME> # MaKe DIRectory
cd <NAME> # Change Directory
git init
git config user.name <NOMBRE>
git config user.email <EMAIL>El nombre de usuario y mail no tienen porque ser reales. Simplemente se utilizan como parte de los mensajes de commit para identificar al autor.
3.2 Añadir un archivo
Objetivo: versionar un archivo nuevo con el primer commit.
git status: no hay nada para commitear.- Crear un archivo de texto
file.txtcon algún contenido. git status: hay un untracked file.git add file.txt: agrega el archivo al staging area.git status: hay cambios para commiteargit commit: crear un commit con mensaje descriptivo.git status: no hay nada para commitear.
3.3 Modificar el archivo y deshacer los cambios
Objetivo: descartar cambios desde el último commit.
- Editar el archivo creado, agregar una nueva línea y guardarlo.
git status: hay un archivo modificado.git diff: ver las modificaciones.git restore file.txt: descartar los cambios.git status: nada para commitear.
3.4 Modificar el archivo y guardar los cambios
Objetivo: registrar una nueva versión del archivo.
- Volver a editar el archivo y agregar contenido.
- Agregar los cambios al staging area.
- Crear un nuevo commit con mensaje descriptivo.
3.6 Trabajar en una rama
Objetivo: desarrollar un cambio aislado en una rama nueva.
git branch dev: crear una nueva rama llamadadev.git log: dos ramas apuntan al commit actualmainydev. Pero estamos parados enmain(HEADapunta amain).git checkout dev: cambiar a la nueva rama.git log: se invierte(HEAD -> rama, main)- Modificar el archivo y commitear el cambio en esa rama.
git log
3.7 Unir una rama: sin conflictos
Objetivo: integrar en la rama main los cambios de la rama dev.
git checkout main: cambiamos a la ramamain.git merge dev: unimos la ramadeva la ramamain. Si no hay conflictos, porque no hubo ningun commit enmaindesde que se separaron las ramas, la ramamainsimplemente “avanza” al commit dedev.
Si ya no la necesitaramos, podríamos borrar la rama dev.
3.8 Unir una rama: con conflictos
git reset --hard <HASH_ANTERIOR>: descartemos el último commit enmainvolviendo al commit anterior.Hacer un cambio en
mainy commitearlo.git merge dev: hay un conflicto al unir las ramas.git status: unmerged paths.git diff: para la(s) línea(s) donde hubo cambios en ambas ramas, vamos a ver las dos versiones:
<<<<<<< HEAD
archivo en mi rama
=======
archivo en la otra rama
>>>>>>> DEV- Resolver manualmente el estado final del archivo: puede ser el cambio que realizó una rama, la otra, o un nuevo cambio que unifica los dos.
- Marcar como resuelto con
git add file.txt. git status: cambios para commiteargit commit: realizar el commit de merge con el conflicto resuelto.git log --oneline --parents: notar que el commit de merge tiene dos padres.git log --oneline --parents --graph.
3.9 Reescribir la historia
Objetivo: practicar una reescritura simple del historial local.
- Crear dos commits pequeños seguidos.
- Usar
git rebase -i HEAD~2para combinarlos en uno solo (squash). git log --oneline: Verificar el nuevo historial.
4 Multi-usuario
git clonegit fetchgit pullgit remote
En dos repositorios locales, vamos a simular ser dos usuarios, Alice y Bob, que quieren compartir su trabajo.
En este ejercicio, vamos a asumir que crearon los repositorios uno al lado del otro:
ejercicio/
├── alice/
│ ├── .git/
│ └──file.txt
└── bob/
├── .git/
└── file.txt4.1 Alice: crear repositorio y primer commit
Objetivo: inicializar el repositorio que se compartirá.
- Crear un directorio
alicee inicializar Git. - Configurar usuario y mail de Alice.
- Crear un archivo inicial.
- Agregarlo al staging area.
- Crear el primer commit.
git init alice
cd alice
git config user.name "Alice"
git config user.email "alice@example.com"
echo "Soy Alice." > file.txt
git add file.txt
git commit -m "Commit inicial de Alice"4.2 Bob: clonar el repositorio
Objetivo: clonar el repositorio para empezar a colaborar.
- Clonar el repositorio remoto.
- Entrar en el repositorio clonado y revisar el estado.
git clone alice bob
cd bobEl comando git clone configura dos cosas que vamos a tener que configurar manualmente para Alice.
Si abren el archivo de texto bob/.git/config, van a ver que tiene:
[remote "origin"]
url = .../alice
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main4.3 De Alice a Bob: sincronizar cambios
Objetivo: que Bob obtenga nuevos commits de Alice
Modificar los archivos de Alice y realizar un commit.
¿Están estos cambios reflejados en el repositorio de Bob?
En esta forma que estamos trabajando, Alice no puede enviarle los cambios a Bob, sino que Bob tiene que pedir los cambios:
git fetch: descarga los objetos nuevos.git merge: hace un merge de la ramaorigin/mainamain.
Se puede hacer en un paso con git pull.
4.4 De Bob a Alice: sincronizar cambios
Objetivo: que Alice obtenga nuevos commits de Bob.
Primero, hagan un cambio y commit en el repositorio de Bob.
Si revisan la configuración de Git de Alice, alice/.git/config, este no tiene conocimiento de ningún repositorio remoto El de Bob se configuró automáticamente al realizar un clonado. Configuremoslo:
git remote add robert ../bobAhora, el repositorio de Alice conoce un repositorio remoto llamado “robert” que está ubicado en el directorio ../bob.
Si corremos git fetch, git le va a pedir al repositorio de Bob todos los objetos nuevos que no conozca. Si queremos mergear los cambios, no podemos hacer simplemente git merge:
> git merge
fatal: No remote for the current branch.La rama en la que estamos parados en el repositorio de Alice no está asociada a ninguna rama remota. Hay dos opciones:
- Especificamos explicitamente la rama:
git merge robert/main- Asociamos la rama
mainde Alice con la ramamainde Bob:
git branch -u robert/mainLuego de lo cual ya podemos usar git merge sin especificar la rama.
5 Multi-usuario con GitHub
git push
La versión multi-usuario de la sección anterior tiene una limitación: necesitamos acceso a la computadora de la otra persona para sincronizar. Generalmente, nuestras computadoras no están conectadas continuamente a internet ni permiten el acceso desde afuera (sino que se inicia la comunicación hacia afuera).
Para resolver este problema, podemos usar un repositorio intermedio de intercambio que permita el accesso a través de internet. Hay que crear un repositorio bare, con git init --bare, que permite que le enviemos nuestros cambios con el comando git push. Si no, estaríamos en el mismo problema de antes: ese repositorio necesitaría acceso a nuestra computadora para pedir (fetch) los cambios. Hay varios sitios que proveen este servicio: GitHub, GitLab, Codeberg, entre otros.
5.1 Publicar en GitHub
Objetivo: publicar el repositorio local en GitHub.
- Crear un repositorio local y realizar un commit.
- Crear un repositorio público vacío en https://github.com/new. Para sincronizar nuestro repositorio local, GitHub nos dice de correr los siguientes comandos:
git remote add origin <URL>
git push -u origin mainque agregan el remoto origin en la dirección provista por GitHub, y envian la rama main a dicho remoto, configurandola como upstream para que los siguientes fetch o push sean automáticos.
5.2 Compartir con otro usuario
Si el repositorio es público, otra persona puede verlo y/o clonarlo a través de su dirección:
https://github.com/<USER>/<REPO>Pero no puede pushear a este.
Si el repositorio es privado, tenemos que darle acceso (de sólo lectura) con su nombre de usuario de GitHub a nuestro repositorio en
https://github.com/<USER>/<REPO>/settings/access5.3 Recibir cambios de otro usuario
Si queremos recibir cambios de otro usuario, tenemos dos opciones:
5.3.1 Opción 1: dar acceso al repositorio
Podemos darle acceso de escritura a nuestro repositorio:
https://github.com/<USER>/<REPO>/settings/access5.3.2 Opción 2: hacer un fork y pull request
En GitHub, un fork es un clon que hace otro usuario de nuestro repositorio en su cuenta de GitHub:
https://github.com/<USUARIO>/<REPO>/forkLuego, la otra persona puede pushear cambios a esta copía, ya que es su repositorio.
Para sincronizar a nuestro repositorio, el otro usuario puede generar un pull request con el botón “Contribute”: 
En nuestro repositorio de GitHub, va a aparecer este pedido y darnos la opción de hacer un merge de esos cambios.