Git

Sitio: Facultad de Ingeniería U.Na.M.
Curso: IC511 - Internet de las Cosas, Sensores y Redes
Libro: Git
Imprimido por: Invitado
Día: miércoles, 3 de julio de 2024, 07:19

1. Introduccion a git

¿Que es git?

Es un sistema de control de versiones.

Cada versión del proyecto se conoce como "commit". En cada commit git guarda los archivos que han sido modificados. Los archivos que no han sido modificados con respecto al commit anterior no se copian, git ofrece un enlace simbólico a ellos. Este mecanismo es transparente para el usuario y asegura que no se produzcan duplicaciones innecesarias.

¿Que es un commit?

Se ha dicho que cada commit representa un estado versionado del proyecto. Técnicamente, un commit es un objeto de git. Este objeto tiene varios campos, de los cuales los que mas nos interesan por ahora son:

  •     id: un identificador único asignado a cada commit. Propuesta: investigar como se genera este identificador.
  •     commit anterior
  •     autor
  •     fecha
  •     mensaje
  •     blob con el contenido del proyecto


Branches (Ramas)

Un branch (rama) representa una linea de desarrollo del proyecto. En cada proyecto existe al menos una. La rama por defecto se llama ‘master’.

Para cada rama del proyecto existe un puntero que apunta al último commit de esta linea. Cada vez que se agrega un commit, el puntero de la rama cambia para indicar el nuevo commit.

Puntero HEAD

HEAD es un puntero que apunta al commit donde se esta trabajando actualmente. Normalmente, HEAD apunta al puntero de alguna rama, por lo que apunta indirectamente al último commit de esta rama. Es posible hacer que HEAD apunte a un commit anterior, lo que hace que nuestro espacio de trabajo muestre el contenido que el proyecto tenia en esta versión. Cuando HEAD no apunta al puntero de una rama se dice que esta en modo detached.

Creando ramas

Crear una rama implica agregar un nuevo puntero que, en principio, apunta al commit actual. En la figura se ha creado la rama ‘dev’ mientras HEAD apuntaba a la rama ‘master’. Tanto ‘master’ como ‘dev’ apuntan al mismo commit ‘asd’.

Es posible hacer que HEAD apunte a la nueva rama 'dev' de la misma forma que se lo direcciona a cualquier otro commit.

Si en esta situación se crean nuevos commits, el puntero de la rama de trabajo actual ('dev') se actualizara para apuntar siempre al ultimo commit.

Si se vuelve a la rama 'master' y se agregan mas commits, el puntero 'master' también se actualiza. En esta situación se observa que ambas ramas de desarrollo divergen.

Combinando cambios

Si se desean combinar los cambios o actualizaciones hechos en varias ramas, es posible realizar una operación merge (mezcla, unión). Esta operación trae (o aplica los cambios de) los commits de la rama indicada en la rama actual. En la figura se ha realizado la operación merge de la rama 'dev' en la rama 'master'. Los commits 'zxc' y 'jkl' se copian en la rama 'master'.

2. Práctica de operaciones locales

Se asume que se tiene instalado git. Este se utiliza mediante comandos en la CLI.

En una instalación nueva de git el usuario no esta definido, por lo que es necesario identificarlo. Para establecer el nombre de autor:

$git config --global user.name 'minombre'

Para establecer el correo del autor:

$git config --global user.email 'mi@correo.com'

Una vez establecidos estos datos de usuario, se esta en condiciones para realizar operaciones locales.

Para crear un repositorio en el directorio actual:

$git init

Cree un archivo. Puede ser un archivo de texto. Para este ejemplo se utilizará el nombre file1.txt. Para indicarle al sistema git que se quiere archivar una versión del proyecto, primero deben copiarse todos los archivos que se desean versionar al area de staging. Para hacer esto:

$git add file1.txt

Alternativamente, se pueden agregar todos los archivos en el directorio actual de manera recursiva con:

$git add .

Ahora los archivos estan en el area de staging. Para crear el commit:

$git commit

El entorno abre un editor de texto en donde se pide introducir el mensaje que acompañará al commit. El editor por defecto es vi. Es posible especificar el mensaje en el mismo comando con la opcion -m:

$git commit -m "mensaje"

Se puede obtener información del estado del repositorio con

$git status

La salida del comando indica si hay modificaciones que no se han copiado al área de staging o cambios en el área de staging que no se han archivado. Si indica que el árbol de trabajo esta limpio, significa que el espacio de trabajo es igual que el ultimo commit realizado.

Importante: si no se agregan los archivos modificados al área de staging con $git add, estos no se archivan al hacer $git commit. Antes de hacer $git commit, siempre se deben agregar los archivos modificados al área de staging.

Propuesta:

Cree el archivo file2.txt, agréguelo al área de staging y cree un commit. Repita los pasos para un archivo file3.txt.

Si ha seguido los pasos hasta aquí, tendrá 3 archivos en su directorio. El comando:

$git log

lista los commits realizados hasta el momento. Se muestra el id, el autor y la fecha de cada commit. Deberían aparecer 3 commits distintos.

Copie el id del primer commit (no es necesario copiar los 40 caracteres, basta con los primeros 7) y úselo como argumento del comando:

$git checkout id-primer-commit

El sistema avisa que el puntero HEAD apunta ahora al primer commit y esta en modo detached. Si observa el directorio de trabajo, solo debería estar el archivo file1.txt.

El comando $git checkout sirve para direccionar el puntero HEAD.

Si se hace $git log, solo se muestra el primer commit.

Para volver al ultimo commit, hacemos que HEAD vuelva a apuntar a master. Recuerde que los punteros de las ramas siempre apuntan al commit mas reciente:

$git checkout master

El área de trabajo debería mostrar nuevamente 3 archivos, ya que estamos en la versión mas reciente.

El comando:

$git branch

lista las ramas existentes. En este caso, solo existe la rama 'master'. Un asterisco al lado de master indica que HEAD esta apuntando a esta rama.

Para crear una rama nueva: (en este ejemplo se le llamará 'dev'):

$git branch dev

Se puede comprobar que se ha creado utilizando el comando $git branch. Para trabajar en la rama recien creada se redirecciona el puntero head:

$git checkout dev

Los últimos 2 comandos ($git branch dev y $git checkout dev) pueden ser resumidos por:

$git checkout -b dev

Propuesta:

En la rama 'dev', cree el archivo file4.txt, agreguelo al area de staging y cree un commit. Repita para el archivo file5.txt.

Se deberían tener 5 archivos y 5 commits en el log.

Propuesta:

Regrese a la rama 'master'. ¿Cuantos archivos hay en el área de trabajo? Cree el archivo file6.txt, agreguelo al area de staging y cree un commit. Repita para el archivo file7.txt.

Se deberían tener 5 archivos y 5 commits en el log.

En master se tienen los archivos file1.txt, file2.txt, file3.txt, file6.txt y file7.txt. Para "traer" los archivos file4.txt y file5.txt que fueron creados en la rama 'dev' se puede hacer una operacion merge. Estando en 'master':

$git merge dev -m "mensaje de merge"

Al hacer $git log se comprueba que se han agregado los commits que se habían realizado en la rama 'dev' en la rama 'master'. El orden en que se agregan los commits es cronológico, según la fecha de creación. Ademas, la operación merge agrega un nuevo commit con el mensaje provisto. Los archivos que se habían creado en la rama 'dev' deberían aparecer en el area de trabajo.

3. Operaciones con remotos

Hasta ahora se han visto funcionalidades de Git que nos permiten versionar nuestros proyectos de forma local. Cuando mas de un usuario trabaja sobre un mismo proyecto, Git ofrece funcionalidades que facilitan el trabajo colaborativo.

Consideraciones

Locales y remotos

Cada usuario posee una copia del repositorio completo. Cada usuario se refiere a su copia particular como local” y las copias presentes en maquinas ajenas a la suya como “remotes” (remotos).

Git es no centralizado por naturaleza. Un usuario puede trabajar con su copia local, independientemente de lo que hagan los demás. Git permite que un usuario sincronice su repositorio local contra cualquier repositorio remoto. En este contexto, sincronizar se refiere a compartir cambios. Así, un usuario puede pasarle sus cambios a otro o descargar en su repositorio local las modificaciones que otro usuario ha hecho en su propio repositorio (que sería un repositorio remoto desde el punto de vista del usuario que descarga estas modificaciones).

Push y pull

Una operación de push implica que el usuario que la ejecuta aplica sus cambios a un repositorio remoto. Por otra parte, una operación de pull implica que el usuario que la ejecuta aplica en su repositorio los cambios que existen en un repositorio remoto.

Origin

Se ha mencionado anteriormente que Git no requiere centralización. No obstante, por cuestiones de logística, lo mas común es definir un repositorio particular como el central contra el que todos los colaboradores sincronizan sus cambios. A este repositorio central se le suele dar el alias “origin”.

Entonces, “origin” es un remoto contra el que “pusheamos” nuestros cambios o “pulleamos” los cambios que otros colaboradores han hecho.

¿Donde vive “origin”?

Origin puede existir en un servidor o computadora de la organización (self hosting), o en la nube. Existen varios servicios gratuitos de hosting de código en la nube que ofrecen funcionalidades montadas sobre Git. Algunos de los mas conocidos al momento de escribir este papiro son GitHub, GitLab, Codeberg y NotABug.

Como establecer una copia remota de un repositorio local

Supongamos que se ha trabajado en un proyecto de forma local utilizando versionado con Git. El comando

$git remote

revela los remotos asociados a este repositorio local. Siendo que este proyecto nació en forma local, via $git init, no existen remotos asociados a el. Supongamos ahora que queremos dar acceso a colaboradores mediante un repositorio central en algún servicio en la nube.

Primero, utilizando la interfaz provista por el servicio en cuestión, creamos un repositorio nuevo. El servidor le asigna una url, que sera la url del remoto “origin”. Para asociar nuestro repositorio local con el “origin” recién creado utilizamos el comando:

$git remote add origin https://url.de.repo.remoto

y seguidamente hacemos:

$git push origin branch_actual

para subir nuestros cambios (esto es, el estado actual del repositorio local) a origin, que hasta ese momento era un repositorio vacío. Git pedirá nuestras credenciales (usuario y contraseña) de la plataforma para completar el proceso.

Es necesario tener en cuenta que se debe dar acceso a los colaboradores utilizando la interfaz provista por el servidor.

Clonando un repositorio existente

Un usuario puede descargar un repositorio ya existente utilizando el comando:

$git clone https://url.de.repo.remoto

Si el repositorio en cuestión es de tipo publico, el comando se completara sin mas y se tendrá una copia del repositorio en el directorio actual. Por otra parte, si el repositorio es privado, la interfaz de Git consultará por las credenciales del usuario, quien deberá estar autorizado (esto es, debe ser colaborador) por el dueño del repositorio para completar la operación.

Sincronizando cambios de otros colaboradores

Si un colaborador sube cambios a origin, es posible descargar estos cambios a nuestro repositorio local mediante el comando:

$git pull origin branch_a_actualizar

Sincronizando nuestros cambios

Para aplicar los cambios que hemos hecho en el repositorio local al remoto origin, se utiliza el comando:

$git push origin branch_actual

Git pedirá nuestras credenciales de la plataforma donde se encuentra alojado origin. Si nuestro usuario se encuentra autorizado como colaborador del repositorio remoto, los commits que se hayan realizado en el repositorio local se aplicarén también al remoto origin.

4. Otros recursos

Nicolás Paez - Tutorial de Git: una serie de 8 videos breves donde se explican fundamentos de Git.

https://www.youtube.com/watch?v=1B-Tuohe18M&list=PLBD-V2suZup_a78x_d9eSBhv6Gu2UwbWr