Taller Git

59
TALLER DE INTRODUCCIÓN A GIT SERGIO GÓMEZ BACHILLER

description

Taller Githun

Transcript of Taller Git

Page 1: Taller Git

TALLER DE INTRODUCCIÓN A GITSERGIO GÓMEZ BACHILLER

Page 2: Taller Git

Esta página se ha dejado vacía a propósito

Page 3: Taller Git

Índice de contenidosCapítulo 1 Sistemas de control de versiones . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.1 Definición, clasificación y funcionamiento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Introducción a git. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

Capítulo 2 Aspectos básicos de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.1 Instalación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2 Configuración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Capítulo 3 Uso básico de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3.1 Crear un proyecto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.2 Trabajando con el historial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Capítulo 4 Uso avanzado de Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

4.1 Deshacer cambios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.2 Moviendo y borrando archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Capítulo 5 Ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5.1 Administración de ramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315.2 Fusión de ramas y resolución de conflictos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335.3 Mezclando con la rama master . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Capítulo 6 Administración de repositorios. . . . . . . . . . . . . . . . . . . . . . . . . 41

6.1 Trabajando con otros repositorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.2 Repositorios básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Capítulo 7 Github . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

7.1 Configuración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497.2 Clientes gráficos para GitHub. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507.3 Trabajando con un proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507.4 Trabajando con Github . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507.5 Último paso, documentación. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Page 4: Taller Git

Esta página se ha dejado vacía a propósito

4

Page 5: Taller Git

Capítulo 1

Sistemas de control de versiones1.1 Definición, clasificación y funcionamientoSe llama control de versiones a la gestión de los diversos cambios que se realizan sobre loselementos de algún producto o una configuración del mismo. Una versión, revisión o edi-ción de un producto, es el estado en el que se encuentra dicho producto en un momentodado de su desarrollo o modificación. Aunque un sistema de control de versiones puederealizarse de forma manual, es muy aconsejable disponer de herramientas que facilitenesta gestión dando lugar a los llamados sistemas de control de versiones o SVC (del inglésSystem Version Control).

Estos sistemas facilitan la administración de las distintas versiones de cada productodesarrollado, así como las posibles especializaciones realizadas (por ejemplo, para algúncliente específico). Ejemplos de este tipo de herramientas son entre otros: CVS, Subver-sion, SourceSafe, ClearCase, Darcs, Bazaar , Plastic SCM, Git, Mercurial, Perforce.

1.1.1 TerminologíaRepositorio ("repository")

El repositorio es el lugar en el que se almacenan los datos actualizados e históricos decambios.

Revisión ("revision")Una revisión es una versión determinada de la información que se gestiona. Haysistemas que identifican las revisiones con un contador (Ej. subversion). Hay otrossistemas que identifican las revisiones mediante un código de detección demodificaciones (Ej. git usa SHA1).

5

Page 6: Taller Git

Etiqueta ("tag")Los tags permiten identificar de forma fácil revisiones importantes en el proyecto. Porejemplo se suelen usar tags para identificar el contenido de las versiones publicadasdel proyecto.

Rama ("branch")Un conjunto de archivos puede ser ramificado o bifurcado en un punto en el tiempode manera que, a partir de ese momento, dos copias de esos archivos se puedendesarrollar a velocidades diferentes o en formas diferentes de forma independiente eluno del otro.

Cambio ("change")Un cambio (o diff, o delta) representa una modificación específica de un documentobajo el control de versiones. La granularidad de la modificación que es consideradacomo un cambio varía entre los sistemas de control de versiones.

Desplegar ("checkout")Es crear una copia de trabajo local desde el repositorio. Un usuario puede especificaruna revisión en concreto u obtener la última. El término 'checkout' también se puedeutilizar como un sustantivo para describir la copia de trabajo.

Confirmar ("commit")Confirmar es escribir o mezclar los cambios realizados en la copia de trabajo delrepositorio. Los términos 'commit' y 'checkin' también se pueden utilizar comosustantivos para describir la nueva revisión que se crea como resultado de confirmar.

Conflicto ("conflict")Un conflicto se produce cuando diferentes partes realizan cambios en el mismodocumento, y el sistema es incapaz de conciliar los cambios. Un usuario debe resolverel conflicto mediante la integración de los cambios, o mediante la selección de uncambio en favor del otro.

Cabeza ("head")También a veces se llama tip (punta) y se refiere a la última confirmación, ya sea en eltronco ('trunk') o en una rama ('branch'). El tronco y cada rama tienen su propiacabeza, aunque HEAD se utiliza a veces libremente para referirse al tronco.

Tronco ("trunk")La única línea de desarrollo que no es una rama (a veces también llamada línea base,línea principal o máster).

Capítulo 1 Sistemas de control de versiones Taller de introducción a Git

6

Page 7: Taller Git

Fusionar, integrar, mezclar ("merge")

Una fusión o integración es una operación en la que se aplican dos tipos de cambios enun archivo o conjunto de archivos. Algunos escenarios de ejemplo son los siguientes:

• Un usuario, trabajando en un conjunto de archivos, actualiza o sincroniza sucopia de trabajo con los cambios realizados y confirmados, por otros usuarios, enel repositorio.

• Un usuario intenta confirmar archivos que han sido actualizado por otrosusuarios desde el último despliegue ('checkout'), y el software de control deversiones integra automáticamente los archivos (por lo general, después depreguntarle al usuario si se debe proceder con la integración automática, y enalgunos casos sólo se hace si la fusión puede ser clara y razonablemente resuelta).

• Un conjunto de archivos se bifurca, un problema que existía antes de laramificación se trabaja en una nueva rama, y la solución se combina luego en laotra rama.

• Se crea una rama, el código de los archivos es independiente editado, y la ramaactualizada se incorpora más tarde en un único tronco unificado.

1.1.2 ClasificaciónPodemos clasificar los sistemas de control de versiones atendiendo a la arquitectura utili-zada para el almacenamiento del código:

LocalesLos cambios son guardados localmente y no se comparten con nadie. Esta arquitecturaes la antecesora de las dos siguientes.

Taller de introducción a Git Capítulo 1 Sistemas de control de versiones

7

Page 8: Taller Git

Figura 1.1 Sistema de control de versiones local

Figura 1.2 Sistema de control de versiones centralizado

CentralizadosExiste un repositorio centralizado de todo el código, del cual es responsable un únicousuario (o conjunto de ellos). Se facilitan las tareas administrativas a cambio de

Capítulo 1 Sistemas de control de versiones Taller de introducción a Git

8

Page 9: Taller Git

reducir flexibilidad, pues todas las decisiones fuertes (como crear una nueva rama)necesitan la aprobación del responsable. Algunos ejemplos son CVS y Subversion.

DistribuidosCada usuario tiene su propio repositorio. Los distintos repositorios puedenintercambiar y mezclar revisiones entre ellos. Es frecuente el uso de un repositorio,que está normalmente disponible, que sirve de punto de sincronización de losdistintos repositorios locales. Ejemplos: Git y Mercurial.

Figura 1.3 Sistema de control de versiones distribuido

Ventajas de sistemas distribuidos

• No es necesario estar conectado para guardar cambios.• Posibilidad de continuar trabajando si el repositorio remoto no está accesible.

Taller de introducción a Git Capítulo 1 Sistemas de control de versiones

9

Page 10: Taller Git

• El repositorio central está más libre de ramas de pruebas.• Se necesitan menos recursos para el repositorio remoto.• Más flexibles al permitir gestionar cada repositorio personal como se quiera.

1.2 Introducción a gitGit es un sistema de control de versiones distribuido que se diferencia del resto en el modoen que modela sus datos. La mayoría de los demás sistemas almacenan la información co-mo una lista de cambios en los archivos, mientras que Git modela sus datos más como unconjunto de instantáneas de un mini sistema de archivos.

Figura 1.4 Modelo de datos de los sistemas distribuidos tradicionales

Figura 1.5 Modelo de datos de Git

1.2.1 Los tres estadosGit tiene tres estados principales en los que se pueden encontrar tus archivos: confirmado(committed), modificado (modified), y preparado (staged). Confirmado significa que losdatos están almacenados de manera segura en tu base de datos local. Modificado significaque has modificado el archivo pero todavía no lo has confirmado a tu base de datos. Prepa-

Capítulo 1 Sistemas de control de versiones Taller de introducción a Git

10

Page 11: Taller Git

rado significa que has marcado un archivo modificado en su versión actual para que vayaen tu próxima confirmación.

Esto nos lleva a las tres secciones principales de un proyecto de Git: el directorio de Git (Gitdirectory), el directorio de trabajo (working directory), y el área de preparación (stagingarea).

Figura 1.6 Directorio de trabajo, área de preparación, y directorio de Git

1.2.2 Flujos de trabajo distribuidos con gitHemos visto en qué consiste un entorno de control de versiones distribuido, pero más alláde la simple definición, existe más de una manera de gestionar los repositorios. Estos sonlos flujos de trabajo más comunes en Git.

Flujo de trabajo centralizadoExiste un único repositorio o punto central que guarda el código y todo el mundosincroniza su trabajo con él. Si dos desarrolladores clonan desde el punto central, yambos hacen cambios; tan solo el primero de ellos en enviar sus cambios de vuelta lopodrá hacer limpiamente. El segundo desarrollador deberá fusionar previamente sutrabajo con el del primero, antes de enviarlo, para evitar el sobreescribir los cambiosdel primero

Taller de introducción a Git Capítulo 1 Sistemas de control de versiones

11

Page 12: Taller Git

Figura 1.7 Flujo de trabajo centralizado

Flujo de trabajo del Gestor-de-IntegracionesAl permitir multiples repositorios remotos, en Git es posible tener un flujo de trabajodonde cada desarrollador tenga acceso de escritura a su propio repositorio público yacceso de lectura a los repositorios de todos los demás. Habitualmente, este escenariosuele incluir un repositorio canónico, representante "oficial" del proyecto. Este modelose puso muy de moda a raíz de la forja GitHub.

Figura 1.8 Flujo de trabajo del Gestor-de-Integraciones

Flujo de trabajo con Dictador y TenientesEs una variante del flujo de trabajo con multiples repositorios. Se utiliza generalmenteen proyectos muy grandes, con cientos de colaboradores. Un ejemplo muy conocido esel del kernel de Linux. Unos gestores de integración se encargan de partes concretasdel repositorio; y se denominan tenientes. Todos los tenientes rinden cuentas a ungestor de integración; conocido como el dictador benevolente. El repositorio deldictador benevolente es el repositorio de referencia, del que recuperan (pull) todos loscolaboradores.

Capítulo 1 Sistemas de control de versiones Taller de introducción a Git

12

Page 13: Taller Git

Figura 1.9 Flujo de trabajo con Dictador y Tenientes

Taller de introducción a Git Capítulo 1 Sistemas de control de versiones

13

Page 14: Taller Git

Esta página se ha dejado vacía a propósito

14

Page 15: Taller Git

Capítulo 2

Aspectos básicos de Git2.1 Instalación

2.1.1 Instalando en LinuxSi quieres instalar Git en Linux a través de un instalador binario, en general puedes ha-cerlo a través de la herramienta básica de gestión de paquetes que trae tu distribución. Siestás en Fedora, puedes usar yum:

$ yum install git-core

O si estás en una distribución basada en Debian como Ubuntu, prueba con apt-get:

$ apt-get install git

2.1.2 Instalando en WindowsInstalar Git en Windows es muy fácil. El proyecto msysGit tiene uno de los procesos deinstalación más sencillos. Simplemente descarga el archivo exe del instalador desde la pá-gina de GitHub, y ejecútalo:

http://msysgit.github.com/

Una vez instalado, tendrás tanto la versión de línea de comandos (incluido un cliente SSHque nos será útil más adelante) como la interfaz gráfica de usuario estándar. Se recomien-da no modificar las opciones que trae por defecto el instalador.

15

Page 16: Taller Git

2.2 Configuración

2.2.1 Tu identidadLo primero que deberías hacer cuando instalas Git es establecer tu nombre de usuario ydirección de correo electrónico. Esto es importante porque las confirmaciones de cambios(commits) en Git usan esta información, y es introducida de manera inmutable en loscommits que envías:

$ git config --global user.name "John Doe"

$ git config --global user.email [email protected]

También se recomienda configurar el siguiente parámetro:

$ git config --global push.default simple

2.2.2 Bash CompletionBash completion es una utilidad que permite a bash completar órdenes y parámetros. Pordefecto suele venir desactivada en Ubuntu y es necesario modificar el archivo $HO-

ME/.bashrc para poder activarla. Simplemente hay que descomentar las líneas que lo ac-tivan,

2.2.3 Tu clave pública/privadaMuchos servidores Git utilizan la autentificación a través de claves públicas SSH. Y, paraello, cada usuario del sistema ha de generarse una, si es que no la tiene ya. El proceso parahacerlo es similar en casi cualquier sistema operativo. Ante todo, asegurarte que no ten-gas ya una clave. (comprueba que el directorio $HOME/usuario/.sshno tiene un archivoid_dsa.pub o id_rsa.pub).

Para crear una nueva clave usamos la siguiente orden:

$ ssh-keygen -t rsa -C "Cuenta Thinstation"

Capítulo 2 Aspectos básicos de Git Taller de introducción a Git

16

Page 17: Taller Git

Capítulo 3

Uso básico de Git3.1 Crear un proyecto

3.1.1 Crear un programa "Hola Mundo"Creamos un directorio donde colocar el código

$ mkdir curso-de-git

$ cd curso-de-git

Creamos un fichero hola.php que muestre Hola Mundo.

<?php

echo "Hola Mundo\n";

3.1.2 Crear el repositorioPara crear un nuevo repositorio se usa la orden git init

$ git init

Initialized empty Git repository in /home/cc0gobas/git/curso-de-git/.git/

3.1.3 Añadir la aplicaciónVamos a almacenar el archivo que hemos creado en el repositorio para poder trabajar, des-pués explicaremos para qué sirve cada orden.

$ git add hola.php

$ git commit -m "Creación del proyecto"

[master (root-commit) e19f2c1] Creación del proyecto

17

Page 18: Taller Git

1 file changed, 2 insertions(+)

create mode 100644 hola.php

3.1.4 Comprobar el estado del repositorioCon la orden git status podemos ver en qué estado se encuentran los archivos de nues-tro repositorio.

$ git status

# On branch master

nothing to commit (working directory clean)

Si modificamos el archivo hola.php:

<?php

@print "Hola {$argv[1]}\n";

Y volvemos a comprobar el estado del repositorio:

$ git status

# On branch master

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working

directory)

#

# modified: hola.php

#

no changes added to commit (use "git add" and/or "git commit -a")

3.1.5 Añadir cambiosCon la ordengit add indicamos a git que prepare los cambios para que sean almacenados.

$ git add hola.php

$ git status

# On branch master

# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# modified: hola.php

#

3.1.6 Confirmar los cambiosCon la orden git commit confirmamos los cambios definitivamente, lo que hace que seguarden permanentemente en nuestro repositorio.

Capítulo 3 Uso básico de Git Taller de introducción a Git

18

Page 19: Taller Git

$ git commit -m "Parametrización del programa"

[master efc252e] Parametrización del programa

1 file changed, 1 insertion(+), 1 deletion(-)

$ git status

# On branch master

nothing to commit (working directory clean)

3.1.7 Funcionamiento de git: se guardan cambios, no ficheros.Modificamos nuestra aplicación para que soporte un parámetro por defecto y añadimoslos cambios.

<?php

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

git add hola.php

Volvemos a modificar el programa para indicar con un comentario lo que hemos hecho.

<?php

// El nombre por defecto es Mundo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

Y vemos el estado en el que está el repositorio

$ git status

# On branch master

# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# modified: hola.php

#

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working

directory)

#

# modified: hola.php

#

Almacenamos los cambios por separado:

$ git commit -m "Se añade un parámetro por defecto"

[master 3283e0d] Se añade un parámetro por defecto

Taller de introducción a Git Capítulo 3 Uso básico de Git

19

Page 20: Taller Git

1 file changed, 2 insertions(+), 1 deletion(-)

$ git status

# On branch master

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working

directory)

#

# modified: hola.php

#

no changes added to commit (use "git add" and/or "git commit -a")

$ git add .

$ git status

# On branch master

# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# modified: hola.php

#

$ git commit -m "Se añade un comentario al cambio del valor por defecto"

[master fd4da94] Se añade un comentario al cambio del valor por defecto

1 file changed, 1 insertion(+)

El valor "." despues de git add indica que se añadan todos los archivos que hayan cambia-do.

3.2 Trabajando con el historial

3.2.1 Observando los cambiosCon la orden git log podemos ver todos los cambios que hemos hecho:

$ git log

commit fd4da946326fbe8b24e89282ad25a71721bf40f6

Author: Sergio Gómez <[email protected]>

Date: Sun Jun 16 12:51:01 2013 +0200

Se añade un comentario al cambio del valor por defecto

commit 3283e0d306c8d42d55ffcb64e456f10510df8177

Author: Sergio Gómez <[email protected]>

Date: Sun Jun 16 12:50:00 2013 +0200

Se añade un parámetro por defecto

Capítulo 3 Uso básico de Git Taller de introducción a Git

20

Page 21: Taller Git

commit efc252e11939351505a426a6e1aa5bb7dc1dd7c0

Author: Sergio Gómez <[email protected]>

Date: Sun Jun 16 12:13:26 2013 +0200

Parametrización del programa

commit e19f2c1701069d9d1159e9ee21acaa1bbc47d264

Author: Sergio Gómez <[email protected]>

Date: Sun Jun 16 11:55:23 2013 +0200

Creación del proyecto

También es posible ver versiones abreviadas o limitadas, dependiendo de los parámetros:

$ git log --oneline

fd4da94 Se añade un comentario al cambio del valor por defecto

3283e0d Se añade un parámetro por defecto

efc252e Parametrización del programa

e19f2c1 Creación del proyecto

git log --oneline --max-count=2

git log --oneline --since='5 minutes ago'

git log --oneline --until='5 minutes ago'

git log --oneline --author=sergio

git log --oneline --all

Una versión muy útil de git log es la siguiente, pues nos permite ver en que lugares estámaster y HEAD, entre otras cosas:

$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (HEAD, master) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto [Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

3.2.2 Crear aliasComo estas órdenes son demasiado largas, Git nos permite crear alias para crear nuevas ór-denes parametrizadas. Para ello editaremos un archivo llamado .gitconfig que está ennuestro $HOME y le añadiremos estas líneas al final:

[alias]

hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short

Taller de introducción a Git Capítulo 3 Uso básico de Git

21

Page 22: Taller Git

3.2.3 Recuperando versiones anterioresCada cambio es etiquetado por un hash, para poder regresar a ese momento del estado delproyecto se usa la orden git checkout.

$ git checkout e19f2c1

Note: checking out 'e19f2c1'.

You are in 'detached HEAD' state. You can look around, make experimental

changes and commit them, and you can discard any commits you make in this

state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may

do so (now or later) by using -b with the checkout command again.

Example:

git checkout -b new_branch_name

HEAD is now at e19f2c1... Creación del proyecto

$ cat hola.php

<?php

echo "Hello, World\n";

El aviso que nos sale nos indica que estamos en un estado donde no trabajamos en ningunarama concreta. Eso significa que los cambios que hagamos podrían "perderse" porque si noson guardados en una nueva rama, en principio no podríamos volver a recuperarlos. Hayque pensar que Git es como un árbol donde un nodo tiene información de su nodo padre,no de sus nodos hijos, con lo que siempre necesitaríamos información de dónde se encuen-tran los nodos finales o de otra manera no podríamos acceder a ellos.

3.2.4 Volver a la última versión de la rama master.Usamos git checkout indicando el nombre de la rama:

$ git checkout master

Previous HEAD position was e19f2c1... Creación del proyecto

3.2.5 Etiquetando versionesPara poder recuperar versiones concretas en la historia del repositorio, podemos etique-tarlas, lo cual es más facil que usar un hash. Para eso usaremos la orden git tag.

$ git tag v1

Capítulo 3 Uso básico de Git Taller de introducción a Git

22

Page 23: Taller Git

Ahora vamos a etiquetar la versión inmediatamente anterior como v1-beta. Para ello po-demos usar los modificadores ^ o ~ que nos llevarán a un ancestro determinado. Las si-guientes dos órdenes son equivalentes:

$ git checkout v1^

$ git checkout v1~1

$ git tag v1-beta

Si ejecutamos la orden sin parámetros nos mostrará todas las etiquetas existentes.

$ git tag

v1

v1-beta

Y para verlas en el historial:

$ git hist master --all

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1, master) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (HEAD, tag:

v1-beta) [Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

3.2.6 Borrar etiquetasPara borrar etiquetas:

git tag -d nombre_etiqueta

3.2.7 Visualizar cambiosPara ver los cambios que se han realizado en el código usamos la ordengit diff. La ordensin especificar nada más, mostrará los cambios que no han sido añadidos aún, es decir, to-dos los cambios que se han hecho antes de usar la orden git add. Después se puede indicarun parámetro y dará los cambios entre la versión indicada y el estado actual. O para com-parar dos versiones entre sí, se indica la más antigua y la más nueva. Ejemplo:

$ git diff v1-beta v1

diff --git a/hola.php b/hola.php

index a31e01f..25a35c0 100644

--- a/hola.php

+++ b/hola.php

@@ -1,3 +1,4 @@

<?php

+// El nombre por defecto es Mundo

Taller de introducción a Git Capítulo 3 Uso básico de Git

23

Page 24: Taller Git

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

Capítulo 3 Uso básico de Git Taller de introducción a Git

24

Page 25: Taller Git

Capítulo 4

Uso avanzado de Git4.1 Deshacer cambios

4.1.1 Deshaciendo cambios antes de la fase de staging.Volvemos a la rama máster y vamos a modificar el comentario que pusimos:

$ git checkout master

Previous HEAD position was 3283e0d... Se añade un parámetro por defecto

Switched to branch 'master'

$ # Modificamos hola.php

$ cat hola.php

<?php

// Este comentario está mal y hay que borrarlo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

$ git status

# On branch master

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working

directory)

#

# modified: hola.php

#

no changes added to commit (use "git add" and/or "git commit -a")

El mismo Git nos indica que debemos hacer para añadir los cambios o para deshacerlos:

25

Page 26: Taller Git

$ git checkout hola.php

$ git status

# On branch master

nothing to commit, working directory clean

$ cat hola.php

<?php

// El nombre por defecto es Mundo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

4.1.2 Deshaciendo cambios antes del commitVamos a hacer lo mismo que la vez anterior, pero esta vez sí añadiremos el cambio al stag(sin hacer commit).

$ # Modificamos hola.php

$ cat hola.php

<?php

// Este comentario está mal y hay que borrarlo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

$ git add hola.php

$ git status

# On branch master

# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# modified: hola.php

#

De nuevo, Git nos indica qué debemos hacer para deshacer el cambio almacenado en elstag:

$ git reset HEAD hola.php

Unstaged changes after reset:

M hola.php

$ git status

# On branch master

# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working

directory)

#

# modified: hola.php

#

Capítulo 4 Uso avanzado de Git Taller de introducción a Git

26

Page 27: Taller Git

no changes added to commit (use "git add" and/or "git commit -a")

$ git checkout hola.php

Y ya tenemos nuestro repositorio limpio otra vez.

4.1.3 Deshaciendo commits no deseados.Si a pesar de todo hemos hecho un commit y nos hemos equivocado, podemos deshacerlocon la orden git revert. Modificamos otra vez el archivo como antes pero ahora sí hace-mos commit:

$ # Modificamos hola.php

$ cat hola.php

<?php

// Este comentario está mal y hay que borrarlo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

$ git add hola.php

$ git commit -m "Ups... este commit está mal."

master 5a5d067] Ups... este commit está mal

1 file changed, 1 insertion(+), 1 deletion(-)

4.1.4 Crear un "reverting commit"$ git revert HEAD --no-edit

[master 817407b] Revert "Ups... este commit está mal"

1 file changed, 1 insertion(+), 1 deletion(-)

$ git hist

* 817407b 2013-06-16 | Revert "Ups... este commit está mal" (HEAD,

master) [Sergio Gómez]

* 5a5d067 2013-06-16 | Ups... este commit está mal [Sergio Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

4.1.5 Borrar commits de una ramaEl anterior apartado revierte un commit, pero deja huella en el historial de cambios. Parahacer que no aparezca hay que usar la orden git reset.

$ git reset --hard v1

HEAD is now at fd4da94 Se añade un comentario al cambio del valor por

defecto

$ git hist

Taller de introducción a Git Capítulo 4 Uso avanzado de Git

27

Page 28: Taller Git

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (HEAD, tag: v1, master) [Sergio Góme

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

El resto de cambios no se han borrado (aún), simplemente no están accesibles porque gitno sabe como referenciarlos. Si sabemos su hash podemos acceder aún a ellos. Pasado untiempo, eventualmente Git tiene un recolector de basura que los borrará. Se puede evitaretiquetando el estado final.

De todas maneras, reset es una operación delicada, que debe evitarse, sobre todo cuando setrabaja en repositorios compartidos.

4.1.6 Modificar un commitEsto se usa cuando hemos olvidado añadir un cambio a un commit que acabamos de rea-lizar.

$ cat hola.php

<?php

// Autor: Sergio Gómez

// El nombre por defecto es Mundo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

$ git commit -a -m "Añadido el autor del programa"

[master cf405c1] Añadido el autor del programa

1 file changed, 1 insertion(+)

El parámetro -a hace un git add antes de hacer commit de todos los archivos modifica-dos o borrados (de los nuevos no), con lo que nos ahorramos un paso. Ahora nos percata-mos que se nos ha olvidado poner el correo electrónico.

$ cat hola.php

<?php

// Autor: Sergio Gómez <[email protected]>

// El nombre por defecto es Mundo

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

@print "Hola, {$nombre}\n";

$ git add hola.php

$ git commit --amend -m "Añadido el autor del programa y su email"

[master 96a39df] Añadido el autor del programa y su email

1 file changed, 1 insertion(+)

$ git hist

Capítulo 4 Uso avanzado de Git Taller de introducción a Git

28

Page 29: Taller Git

* 96a39df 2013-06-16 | Añadido el autor del programa y su email (HEAD,

master) [Sergio Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

4.2 Moviendo y borrando archivos

4.2.1 Mover un archivo a otro directorio con gitPara mover archivos usaremos la orden git mv:

$ mkdir lib

$ git mv hola.php lib

$ git status

# On branch master

# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# renamed: hola.php -> lib/hola.php

#

4.2.2 Mover y borrar archivos.Otra forma de hacer lo mismo:

$ mkdir lib

$ mv hola.php lib

$ git add lib/hola.php

$ git rm hola.php

Y ya podemos guardar los cambios:

$ git commit -m "Movido hola.php a lib."

[master 8c2a509] Movido hola.php a lib.

1 file changed, 0 insertions(+), 0 deletions(-)

rename hola.php => lib/hola.php (100%)

Taller de introducción a Git Capítulo 4 Uso avanzado de Git

29

Page 30: Taller Git

Esta página se ha dejado vacía a propósito

30

Page 31: Taller Git

Capítulo 5

Ramas5.1 Administración de ramas

5.1.1 Crear una nueva ramaCuando vamos a trabajar en una nueva funcionalidad, es conveniente hacerlo en una nue-va rama, para no modificar la rama principal y dejarla inestable. Aunque la orden paramanejar ramas es git branch podemos usar también git checkout.

$ git branch hola

$ git checkout hola

Switched to branch 'hola'

O de forma más rápida:

$ git checkout -b hola

Switched to a new branch 'hola'

5.1.2 Modificaciones en la rama secundariaAñadimos un nuevo archivo en el directorio lib llamado HolaMundo.php:

<?php

class HolaMundo

{

private $nombre;

function __construct($nombre)

{

31

Page 32: Taller Git

$this->nombre = $nombre;

}

function __toString()

{

return sprintf ("Hola, %s.\n", $this->nombre);

}

}

Y modificamos hola.php:

<?php

// Autor: Sergio Gómez <[email protected]>

// El nombre por defecto es Mundo

require('HolaMundo.php');

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

print new HolaMundo($nombre);

Podríamos confirmar los cambios todos de golpe, pero lo haremos de uno en uno, con sucomentario.

$ git add lib/HolaMundo.php

$ git commit -m "Añadida la clase HolaMundo"

[hola 6932156] Añadida la clase HolaMundo

1 file changed, 16 insertions(+)

create mode 100644 lib/HolaMundo.php

$ git add lib/hola.php

$ git commit -m "hola usa la clase HolaMundo"

[hola 9862f33] hola usa la clase HolaMundo

1 file changed, 3 insertions(+), 1 deletion(-)

Y ahora con la orden git checkout podemos movernos entre ramas:

$ git checkout master

Switched to branch 'master'

$ git checkout hola

Switched to branch 'hola'

5.1.3 Modificaciones en la rama masterPodemos volver y añadir un nuevo archivo a la rama principal:

$ git checkout master

Switched to branch 'master'

$ cat README.md

Capítulo 5 Ramas Taller de introducción a Git

32

Page 33: Taller Git

# Curso de GIT

Este proyecto contiene el curso de introducción a GIT

$ git add README.md

$ git commit -m "Añadido README.md"

[master c3e65d0] Añadido README.md

1 file changed, 3 insertions(+)

create mode 100644 README.md

$ git hist --all

* c3e65d0 2013-06-16 | Añadido README.md (HEAD, master) [Sergio Gómez]

| * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio

Gómez]

| * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

|/

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

Y vemos como git histmuestra la bifurcación en nuestro código.

5.2 Fusión de ramas y resolución de conflictos

5.2.1 Mezclar ramasPodemos incorporar los cambios de una rama a otra con la orden git merge

$ git checkout hola

Switched to branch 'hola'

$ git merge master

Merge made by the 'recursive' strategy.

README.md | 3 +++

1 file changed, 3 insertions(+)

create mode 100644 README.md

$ git hist --all

* 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola (HEAD, hola)

[Sergio Gómez]

|\

* | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez]

* | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

Taller de introducción a Git Capítulo 5 Ramas

33

Page 34: Taller Git

| |

| * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

|/

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

De esa forma se puede trabajar en una rama secundaria incorporando los cambios de la ra-ma principal o de otra rama.

5.2.2 Resolver conflictosUn conflicto es cuando se produce una fusión que Git no es capaz de resolver. Vamos a mo-dificar la rama master para crear uno con la rama hola.

$ git checkout master

M lib/hola.php

Already on 'master'

$ cat lib/hola.php

<?php

// Autor: Sergio Gómez <[email protected]>

print "Introduce tu nombre:";

$nombre = trim(fgets(STDIN));

@print "Hola, {$nombre}\n";

$ git add lib/hola.php

$ git commit -m "Programa interactivo"

[master 9c85275] Programa interactivo

1 file changed, 2 insertions(+), 2 deletions(-)

$ git hist --all

* 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola (hola) [Sergio

Gómez]

|\

* | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez]

* | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

| | * 9c85275 2013-06-16 | Programa interactivo (HEAD, master) [Sergio

Gómez]

| |/

| * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

|/

Capítulo 5 Ramas Taller de introducción a Git

34

Page 35: Taller Git

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

Volvemos a la rama hola y fusionamos:

$ git checkout hola

Switched to branch 'hola'

$ git merge master

Auto-merging lib/hola.php

CONFLICT (content): Merge conflict in lib/hola.php

Automatic merge failed; fix conflicts and then commit the result.

$ cat lib/hola.php

<?php

// Autor: Sergio Gómez <[email protected]>

<<<<<<< HEAD

// El nombre por defecto es Mundo

require('HolaMundo.php');

$nombre = isset($argv[1]) ? $argv[1] : "Mundo";

print new HolaMundo($nombre);

=======

print "Introduce tu nombre:";

$nombre = trim(fgets(STDIN));

@print "Hola, {$nombre}\n";

>>>>>>> master

La primera parte marca el código que estaba en la rama donde trabajábamos (HEAD) y laparte final el código de donde fusionábamos. Resolvemos el conflicto:

$ cat lib/hola.php

<?php

// Autor: Sergio Gómez <[email protected]>

require('HolaMundo.php');

print "Introduce tu nombre:";

$nombre = trim(fgets(STDIN));

print new HolaMundo($nombre);

$ git add lib/hola.php

Taller de introducción a Git Capítulo 5 Ramas

35

Page 36: Taller Git

$ git commit -m "Solucionado el conflicto al fusionar con la rama master"

[hola a36af04] Solucionado el conflicto al fusionar con la rama master

5.2.3 Rebasing vs MergingRebasing es otra técnica para fusionar distinta a merge y usa la ordengit rebase. Vamosa dejar nuestro proyecto como estaba antes del fusionado:

$ git checkout hola

Switched to branch 'hola'

$ git hist

* a36af04 2013-06-16 | Solucionado el conflicto al fusionar con la

rama master (HEAD, hola) [Sergio Gómez]

|\

| * 9c85275 2013-06-16 | Programa interactivo (master) [Sergio Gómez]

* | 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola [Sergio

Gómez]

|\ \

| |/

| * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

* | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez]

* | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

|/

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

$ git reset --hard 9862f33

HEAD is now at 9862f33 hola usa la clase HolaMundo

$ git checkout master

Switched to branch 'master'

$ git hist

* 9c85275 2013-06-16 | Programa interactivo (HEAD, master) [Sergio Gómez]

* c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

Capítulo 5 Ramas Taller de introducción a Git

36

Page 37: Taller Git

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

$ git reset --hard c3e65d0

HEAD is now at c3e65d0 Añadido README.md

Y nuestro estado será:

$ git hist --all

* 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez]

* 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

| * c3e65d0 2013-06-16 | Añadido README.md (HEAD, master) [Sergio Gómez]

|/

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

$ git checkout hola

Switched to branch 'hola'

$ git rebase master

First, rewinding head to replay your work on top of it...

Applying: Añadida la clase HolaMundo

Applying: hola usa la clase HolaMundo

$ git hist --all

* 491f1d2 2013-06-16 | hola usa la clase HolaMundo (HEAD, hola) [Sergio

Gómez]

* c13d75c 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

* c3e65d0 2013-06-16 | Añadido README.md (master) [Sergio Gómez]

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (tag: v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

Taller de introducción a Git Capítulo 5 Ramas

37

Page 38: Taller Git

Lo que hace rebase es volver a aplicar todos los cambios a la rama máster, desde su nodomás reciente. Eso significa que se modifica el orden o la historia de creación de los cam-bios. Por eso rebase no debe usarse si el orden es importante o si la rama es compartida.

5.3 Mezclando con la rama masterYa hemos terminado de implementar los cambios en nuestra rama secundaria y es horade llevar los cambios a la rama principal. Usamos git merge para hacer una fusión nor-mal:

$ git checkout master

Switched to branch 'master'

$ git merge hola

Updating c3e65d0..491f1d2

Fast-forward

lib/HolaMundo.php | 16 ++++++++++++++++

lib/hola.php | 4 +++-

2 files changed, 19 insertions(+), 1 deletion(-)

create mode 100644 lib/HolaMundo.php

Vemos que indica que el tipo de fusión es fast-forward. Este tipo de fusión tiene el proble-ma que no deja rastro de la fusión, por eso suele ser recomendable usar el parámetro --no-ffpara que quede constancia siempre de que se ha fusionado una rama con otra.

Capítulo 5 Ramas Taller de introducción a Git

38

Page 39: Taller Git

Figura 5.1 Diferencias entre tipos de fusión

Taller de introducción a Git Capítulo 5 Ramas

39

Page 40: Taller Git

Esta página se ha dejado vacía a propósito

40

Page 41: Taller Git

Capítulo 6

Administración de repositorios6.1 Trabajando con otros repositorios

6.1.1 Clonar un repositorioClonar es la acción de copiar el contenido de un repositorio para generar otra copia de tra-bajo. Se usa la orden git clone. Vamos a clonar nuestro respositorio de ejemplo en otrodirectorio:

$ cd ..

$ git clone curso-git curso-git-clonado

Cloning into 'curso-git-clonado'...

done.

Y comprobamos que el nuevo repositorio es igual que el que teníamos:

$ cd curso-git-clonado/

$ ls

README.md lib

$ git hist --all

* 491f1d2 2013-06-16 | hola usa la clase HolaMundo (HEAD, origin/master,

origin/hola, origin/HEAD, master) [Sergio Gómez]

* c13d75c 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

* c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (v1) [Sergio Gómez]

41

Page 42: Taller Git

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

Bueno, no exactamente igual. Hay unas nuevas ramas llamadas origin/* que indican queestán vinculadas con un repositorio externo. Podemos verlas con la orden git remote:

$ git remote show origin

* remote origin

Fetch URL: /home/cc0gobas/git/curso-git

Push URL: /home/cc0gobas/git/curso-git

HEAD branch (remote HEAD is ambiguous, may be one of the following):

hola

master

Remote branches:

hola tracked

master tracked

Local branch configured for 'git pull':

master merges with remote master

Local ref configured for 'git push':

master pushes to master (up to date)

6.1.2 Ramas remotasPara poder ver las ramas remotas debemos usar el parámetro -a en la orden git branch:

$ git branch -a

* master

remotes/origin/HEAD -> origin/master

remotes/origin/hola

remotes/origin/master

6.1.3 Cómo actualizar el repositorio copiaCuando se trabaja en grupo, es normal que el repositorio remoto cambie. Vamos a modifi-carlo y ver como podemos actualizar el repositorio copia:

$ cd ..

$ cd curso-git

$ cat README.md

# Curso de GIT

Este proyecto contiene el curso de introducción a GIT.

Ahora es un repositorio compartido.

$ git add README.md

Capítulo 6 Administración de repositorios Taller de introducción a Git

42

Page 43: Taller Git

$ git commit -m "Cambiado el README.md"

[master 3d2db03] Cambiado el README.md

1 file changed, 2 insertions(+), 1 deletion(-)

Al proceso de traer una actualización se le llama pull y de hecho hay una orden llamadagit pull que realiza ese cometido. Vamos a ver, de todas maneras, el camino largo usan-do git fetch. Esta última órden lo que hace es actualizar la rama origin/master y origin/HEAD de nuestro repositorio copia, pero no actualiza las ramas locales. Es decir, no fusio-na las ramas remotas con las locales:

$ cd ../curso-git-clonado/

$ git fetch

remote: Counting objects: 5, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 0), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

De /home/cc0gobas/git/curso-git

491f1d2..3d2db03 master -> origin/master

$ git hist --all

* 3d2db03 2013-06-17 | Cambiado el README.md (origin/master,

origin/HEAD) [Sergio Gómez]

* 491f1d2 2013-06-16 | hola usa la clase HolaMundo (HEAD, origin/hola,

master) [Sergio Gómez]

* c13d75c 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez]

* c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez]

* 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez]

* 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio

Gómez]

* fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por

defecto (v1) [Sergio Gómez]

* 3283e0d 2013-06-16 | Se añade un parámetro por defecto (v1-beta)

[Sergio Gómez]

* efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez]

* e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez]

Podemos comprobar que el archivore README.mdno ha cambiado. Para hacer los cambiostendremos que fusionar las ramas como hemos visto:

$ git merge origin/master

Updating 491f1d2..3d2db03

Fast-forward

README.md | 3 ++-

1 file changed, 2 insertions(+), 1 deletion(-)

Taller de introducción a Git Capítulo 6 Administración de repositorios

43

Page 44: Taller Git

Los dos pasos anteriores se suelen reducir en uno solo:

$ git pull

Updating 491f1d2..3d2db03

Fast-forward

README.md | 3 ++-

1 file changed, 2 insertions(+), 1 deletion(-)

¿Por qué existe entonces git fetch? Pues porque normalmente los integradores prefie-ren ver los cambios que se van a realizar antes de hacerlos. Se puede hacer un checkout a larama remota para ver lo que ha cambiado.

6.1.4 Añadir una rama de seguimientoCuando se clona un repositorio, en el repositorio local solo se crea una rama máster, perolas ramas secundarias que ya existían en el repositorio remoto no se crean. Solo aparecena través de las ramas remotas origin/*. Para crear ramas locales que hagan seguimiento deesas ramas remotas usaremos git branch:

$ git branch --track hola origin/hola

Branch hola set up to track remote branch hola from origin.

$ git branch -a

hola

* master

remotes/origin/HEAD -> origin/master

remotes/origin/hola

remotes/origin/master

$ git hist --max-count=2

* 3d2db03 2013-06-17 | Cambiado el README.md (HEAD, origin/master,

origin/HEAD, master) [Sergio Gómez]

* 491f1d2 2013-06-16 | hola usa la clase HolaMundo (origin/hola, hola)

[Sergio Gomez]

6.1.5 Borrar ramas remotasPara borrar una rama local se usaba git branch:

$ git branch -d nombre-rama

Pero para borrar una rama que esté en el repositorio remoto hay que usar git push colo-cando el símbolo : antes del nombre de la rama:

$ git push origin :nombre-rama

Capítulo 6 Administración de repositorios Taller de introducción a Git

44

Page 45: Taller Git

6.2 Repositorios básicos

6.2.1 CreaciónLos repositorio básicos (en inglés conocidos como bare repositories) no contienen la partellamada "directorio de trabajo" y son usados específicamente para ser compartidos, se usa in-dicando el parámetro --bare a las órdenes git clone y git init:

$ cd ..

$ git clone --bare curso-git curso-git.git

Cloning into bare repository 'curso-git.git'...

hecho.

$ ls curso-git.git/

branches config description HEAD hooks info objects packed-refs

refs

6.2.2 Añadir un repositorio remotoEs posible indicar, para un proyecto ya existente, que utilice un repositorio remoto. En es-te caso, al proyecto original vamos a indicarle que use el nuevo repositorio básico:

$ cd curso-git

$ git remote add origin ../curso-git.git

6.2.3 Subir cambiosEl escenario que tenemos ahora es el siguiente:

• Un repositorio básico llamado curso-git.git donde se almacenará centralmente elproyecto.

• Un repositorio llamado curso-git donde trabajaremos.

Este es el escenario normal, un directorio centralizado y compartido y uno donde traba-jamos localmente. En este escenario, iremos realizando cambios en nuestro directorio y,posteriormente, los subiremos al repositorio compartido. Para eso usaremos la orden git

push.

Vamos a modificar nuestro archivo README.md de nuevo y a subir los cambios:

$ cat README.md

# Curso de GIT

Este proyecto contiene el curso de introducción a GIT.

Ahora es un repositorio compartido.

Con esto ya estamos terminando el curso.

$ git add README.md

Taller de introducción a Git Capítulo 6 Administración de repositorios

45

Page 46: Taller Git

$ git commit -m "Añadido un comentario compartido en README.md"

[master 243d834] Añadido un comentario compartido en README.md

1 file changed, 1 insertion(+)

$ git push -u origin master

Counting objects: 5, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (3/3), done.

Writing objects: 100% (3/3), 372 bytes, done.

Total 3 (delta 1), reused 0 (delta 0)

To ../curso-git.git/

3d2db03..243d834 master -> master

Branch master set up to track remote branch master from origin.

6.2.4 Actualizar cambios desde repositorios compartidosEl repositorio curso-git-clonado era un clon del repositorio original. Git permite modificarlas ramas remotas de un proyecto o añadir más, de tal manera que podríamos hacer ahorados cosas con ese repositorio:

• Eliminar las referencias de origin/* y crear nuevas al repositorio básico curso-

git.git.• Añadir más ramas remotas asociadas al repositorio básico.

Esto último sería:

$ cd ../curso-git-clonado/

$ git remote add shared ../curso-git.git

$ git pull -u shared master

remote: Counting objects: 5, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 1), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

De ../curso-git

* branch master -> FETCH_HEAD

Updating 3d2db03..243d834

Fast-forward

README.md | 1 +

1 file changed, 1 insertion(+)

$ cat README.md

# Curso de GIT

Este proyecto contiene el curso de introducción a GIT.

Ahora es un repositorio compartido.

Con esto ya estamos terminando el curso.

Capítulo 6 Administración de repositorios Taller de introducción a Git

46

Page 47: Taller Git

El parámetro -u es equivalente a hacer esto:

git branch --track shared master

Taller de introducción a Git Capítulo 6 Administración de repositorios

47

Page 48: Taller Git

Esta página se ha dejado vacía a propósito

48

Page 49: Taller Git

Capítulo 7

GithubGithub es lo que se denomina una forja, un repositorio de proyectos que usan Git comosistema de control de versiones. Es la forja más popular, ya que alberga más de 10 millonesde repositorios. Debe su popularidad a sus funcionalidades sociales, principalmente dos: laposibilidad de hacer forks de otros proyectos y la posibilidad de cooperar aportando códi-go para arreglar errores o mejorar el código. Si bien, no es que fuera una novedad, sí lo es lofácil que resulta hacerlo. A raíz de este proyecto han surgido otros como Gitorius o Gitlab,pero Github sigue siendo el más popular y el que tiene mejores y mayores características.algunas de estas son:

• Un wiki para documentar el proyecto, que usa MarkDown como lenguaje de marca.• Un portal web para cada proyecto.• Funcionalidades de redes sociales como followers.• Gráficos estadísticos.• Revisión de código y comentarios.• Sistemas de seguimiento de incidencias.

Lo primero es entrar en el portal (https://github.com/) para crearnos una cuenta si no latenemos aún.

7.1 ConfiguraciónVamos a aprovechar para añadir la clave RSA que generamos antes, para poder accederdesde git a los repositorios. Para ellos nos vamos al menú de configuración de usuario, queen la barra superior se identifica con un icono con un par de herramientas.

49

Page 50: Taller Git

Figura 7.1 Barra principal de menú

Nos vamos al menú 'SSH Keys' y añadimos una nueva clave. En Title indicamos una des-cripción que nos ayude a saber de dónde procede la clave y en key volcamos el contenidodel archivo ~/.ssh/id_rsa.pub. Y guardamos la clave.

Con esto ya tendriamos todo nuestro entorno para poder empezar a trabajar desde nuestroequipo.

7.2 Clientes gráficos para GitHubAdemás, para Github existe un cliente propio tanto para Windows como para MacOSX:

• Cliente Windows: http://windows.github.com/

• Cliente MacOSX: http://mac.github.com/

Para Linux no hay cliente propio, pero sí hay plugin para Eclipse:

• Cliente Eclipe: http://eclipse.github.com/

De todas maneras, estos clientes solo tienen el fin de facilitar el uso de Github, pero noson necesarios para usarlo. Es perfectamente válido usar el cliente de Git o cualquier otrocliente genérico para Git. Uno de los más famosos es Smartgit(http://www.syntevo.com/smartgithg/).

7.3 Trabajando con un proyectoAntes de nada, este tutorial tiene los siguiente pre-requisitos:

• Git• PHP versión 5.4.0 o superior• Composer (Disponible en https://getcomposer.org/download/).

Todo el software se encuentra disponible en Thinstation.

7.4 Trabajando con Github

7.4.1 Clonado de un repositorio.Nos vamos a la web del proyecto en el que queremos colaborar. En este caso el proyectose encuentra en https://github.com/sgomez/miniblog. Pulsamos en el botón de fork y esocreará una copia en nuestro perfil.

Capítulo 7 Github Taller de introducción a Git

50

Page 51: Taller Git

Figura 7.2 Barra de información de proyecto

Una vez se termine de clonar el repositorio, nos encontraremos con el espacio de trabajodel mismo:

• En la parte superior información sobre los commits, ramas, etiquetas, etc.• Justo debajo un explorador de archivos.• En la parte derecha un selector para cambiar de contexto entre: explorador de

código, peticiones de colaboración (pull request), wiki, configuración, etc.• Justo abajo a la derecha información sobre como clonar localmente o descargar un

proyecto.

Figura 7.3 Espacio de trabajo

Github nos permite clonar localmente un proyecto por tres vías: HTTPS, SSH y Subver-sion. Seleccionamos SSH y copiamos el texto que después añadiremos a la orden git clo-

ne como en la primera línea del siguiente grupo de órdenes:

$ git clone [email protected]:miusuario/miniblog.git

$ cd miniblog

$ composer.phar install

$ php console create-schema

Lo que hace el código anterior es:

Taller de introducción a Git Capítulo 7 Github

51

Page 52: Taller Git

1. Clona el repositorio localmente2. Entramos en la copia3. Instalamos las dependencias que la aplicación tiene4. Arrancamos un servidor web para pruebas

Y probamos que nuestra aplicación funciona:

$ php -S localhost:9999 -t web/

Podemos usar dos direcciones para probarla:

• Frontend: http://localhost:9999/index_dev.php• Backend: http://localhost:9999/index_dev.php/admin/ con usuario admin

y contraseña 1234.

7.4.2 Sincronizar con el repositorio originalCuando clonamos un repositorio de otro usuario hacemos una copia del original. Pero esacopia es igual al momento en el que hicimos la copia. Cuando el repositorio original cam-bie, que lo hará, nuestro repositorio no se actualizará solo. ¡Son dos repositorios diferentes!Necesitamos una manera de poder incorporar los cambios que vaya teniendo el reposito-rio original en el nuestro. Para eso crearemos una nueva rama remota. Por convenio, y co-mo vimos anteriormente, ya existe una rama remota llamada origin que apunta al reposi-torio de donde clonamos el proyecto, en este caso apunta a nuestro fork en github:

$ git remote show origin

* remote origin

Fetch URL: [email protected]:miusuario/miniblog.git

Push URL: [email protected]:miusuario/miniblog.git

HEAD branch (remote HEAD is ambiguous, may be one of the following):

develop

master

Remote branches:

develop tracked

master tracked

Local branch configured for 'git pull':

master merges with remote master

Local ref configured for 'git push':

master pushes to master (up to date)

También por convenio, la rama remota que hace referencia al repositorio original se lla-ma upstream y se crea de la siguiente manera:

Capítulo 7 Github Taller de introducción a Git

52

Page 53: Taller Git

$ git remote add upstream [email protected]:sgomez/miniblog.git

$ git remote show upstream

* remote upstream

Fetch URL: [email protected]:sgomez/miniblog.git

Push URL: [email protected]:sgomez/miniblog.git

HEAD branch: master

Remote branches:

develop new (next fetch will store in remotes/upstream)

master new (next fetch will store in remotes/upstream)

Local ref configured for 'git push':

master pushes to master (local out of date)

En este caso, la URI debe ser siempre la del proyecto original. Y ahora para incorporar ac-tualizaciones, usaremos el merge en dos pasos:

$ git fetch upstream

$ git merge upstream/master

Recordemos que fetch solo trae los cambios que existan en el repositorio remoto sin hacerningún cambio en nuestro repositorio. Es la orden merge la que se encarga de que todo estésincronizado. En este caso decimos que queremos fusionar con la rama master que está enel repositorio upstream.

7.4.3 Creando nuevas funcionalidadesVamos a crear una nueva funcionalidad: vamos a añadir una licencia de uso. Para ello pre-ferentemente crearemos una nueva rama.

$ git checkout -b add-license

$ echo "LICENCIA MIT" > LICESE

# el error es intencionado

$ git add LICESE

$ git commit -m "Archivo de licencia de uso"

En principio habría que probar que todo funciona bien y entonces integraremos en la ra-ma master de nuestro repositorio y enviamos los cambios a Github:

$ git checkout master

$ git merge add-license --no-ff

$ git branch -d add-license

# Borramos la rama que ya no nos sirve para nada

$ git push --set-upstream origin add-license

# Enviamos la rama a nuestro repositorio origin

Taller de introducción a Git Capítulo 7 Github

53

Page 54: Taller Git

Si volvemos a Github, veremos que nos avisa de que hemos subido una nueva rama y siqueremos crear un pull request.

Figura 7.4 Aviso de nueva rama

Pulsamos y entramos en la petición de Pull Request. Este es el momento para revisar cual-quier error antes de enviar al dueño del repositorio. Como vemos hemos cometido uno,nombrando el fichero, si lo correguimos debemos hacer otro push para ir actualizando larama. Cuando esté lista volvemos aquí y continuamos. Hay que dejar una descripción delcambio que vamos a hacer.

Figura 7.5 Creando un Pull Request

Una vez hemos terminado y nos aseguramos que todo está correcto, pulsamos Send pull re-quest y le llegará nuestra petición al dueño del proyecto.

Figura 7.6 Gestión de un _Pull Request_

Capítulo 7 Github Taller de introducción a Git

54

Page 55: Taller Git

Sin embargo, para esta prueba, no vamos a cambiar el nombre del archivo y dejaremos elerror como está. Así de esta manera al administrador del proyecto le llegará el Pull Requesty la lista de cambios. Ahora en principio, cabría esperar que el administrador aprobara loscambios, pero podría pasar que nos indicara que cambiemos algo. En ese caso solo habríaque modificar la rama y volverla a enviar.

$ git mv LICESE LICENSE

$ git commit -m "Fix: Nombre de archivo LICENSE"

$ git push

Ahora sí, el administrador puede aprobar la fusión y borrar la rama del repositorio. El pa-nel de Github permite aceptar los cambios directamente o informa de como hacer una co-pia de la rama ofrecida por el usuario para hacer cambios, como puede verse en la siguien-te imagen.

Figura 7.7 Conversación en un _Pull Request_

Una vez que se han aceptado los cambios, podemos borrar la rama y actualizar nuestro re-positorio con los datos del remoto como hicimos antes. ¿Por qué actualizar desde el remotoy no desde nuetra rama add-license? Pues porque usualmente el administrador puede ha-

Taller de introducción a Git Capítulo 7 Github

55

Page 56: Taller Git

ber modificado los cambios que le hemos propuesto, o incluso una tercera persona. Recor-demos el cariz colaborativo que tiene Github.

$ git checkout master

$ git branch -d add-license

# Esto borra la rama local

$ git push origin --delete add-license

# Esto borra la rama remota. También puede hacerse desde la web.

7.4.4 Todo esto es algo complicado...Sí, lo es, al menos al principio. Git tiene una parte muy sencilla que es el uso del repositoriolocal (órdenes tales como add, rm, mv y commit). El siguiente nivel de complejidad locomponen las órdenes para trabajar con ramas y fusionarlas (checkout, branch, merge, re-base) y por último, las que trabajan con repositorios remotos (pull, push, fetch, remote).Además hay otra serie de órdenes para tener información (diff, log, status) o hacer opera-ciones de mantenimiento (fsck, gc). Lo importante para no perderse en Git, es seguir la si-guiente máxima:

Muy poco sentido tiene ponernos a crear ramas en github si aún no entendemos cómo secrean localmente y para que deben usarse. En la parte de referencias hay varios manualesen línea, incluso tutoriales interactivos. También hay mucha documentación disponibleen Github que suele venir muy bien explicada. En caso de que tengamos un problema queno sepamos resolver, una web muy buena es StackOverflow (http://stackoverflow.com/). Es una web de preguntas y respuestas para profesionales; es muy difícil que se os planteeuna duda que no haya sido ya preguntada y respondida en esa web. Eso sí, el inglés es im-prescindible.

7.5 Último paso, documentación.Github permite crear documentación. En primer lugar, generando un archivo llamadoREADME. También permite crear una web propia para el proyecto y, además, una wiki.Para marcar el texto, se utiliza un lenguaje de marcado de texto denominado Markdown.En la siguiente web hay un tutorial interactivo: http://www.markdowntutorial.com/. Co-mo en principio, no es necesario saber Markdown para poder trabajar con Git o con Git-hub, no vamos a incidir más en este asunto.

Sin embargo, para los curiosos dejamos como referencia la web de Easybook(http://easybook-project.org/) . Este proyecto, que se encuentra también en Github, per-

No avanzar al siguiente nivel de complejidad, hasta no haber entendido comple-

tamente el anterior.“

Capítulo 7 Github Taller de introducción a Git

56

Page 57: Taller Git

mite crear documentos en PDF, HTML o ePub a partir de documentos escritos en Mark-down. Este manual, por ejemplo, ha sido escrito en Markdown y pasado a PDF con Easy-book.

Taller de introducción a Git Capítulo 7 Github

57

Page 58: Taller Git

Esta página se ha dejado vacía a propósito

Page 59: Taller Git

Referencias• Documentación oficial en inglés (http://git-scm.com/documentation) .• Documentación oficial en español (quizás incompleta) (http://git-scm.com/book/

es) .• Curso de Git (inglés) (http://gitimmersion.com/lab_01.html) . La mayoría de la

documentación de este manual está basada en este curso.• Curso interactivo de Git (inglés) (http://try.github.io/levels/1/challenges/1) .• Página de referencia de todas las órdenes de Git (inglés) (http://gitref.org/) .• Chuleta con las órdenes más usuales de Git (http://byte.kde.org/~zrusin/git/git-

cheat-sheet-large.png) .• Gitmagic (ingles y español). Otro manual de Git (http://www-cs-

students.stanford.edu/~blynn/gitmagic/intl/es/)• Artículo técnico: Un modelo exitoso de ramificación en Git (http://nvie.com/posts/

a-successful-git-branching-model/) .