summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--es/1.md610
1 files changed, 610 insertions, 0 deletions
diff --git a/es/1.md b/es/1.md
index e69de29..3939d27 100644
--- a/es/1.md
+++ b/es/1.md
@@ -0,0 +1,610 @@
+---
+title: GIT
+subtitle: Introducción y uso básico
+license: CC-BY-NC-SA 4.0
+author: Ekaitz Zarraga - ElenQ Technology
+links-as-notes: true
+lang: spanish
+polyglossia-lang:
+ name: spanish
+how-to: pandoc -f markdown+smart -t beamer % -o pdf/1.pdf --pdf-engine=xelatex --template=./template.tex
+...
+
+## Licencia
+
+- CC-BY-SA 4.0
+- El contenido del documento ha sido adaptado de [**Pro Git (Scott Chacon, Ben
+ Straub)**](https://git-scm.com/book/en/v2).
+
+# Introducción: sistemas de control de versiones
+
+## Sistemas de control de versiones
+
+`Document_v3_FINAL.pdf`
+
+---
+
+![Centralizados](img/zentralizatuak.png){ height=180px }
+
+---
+
+![Descentralizados](img/banatuak.png){ height=300px }
+
+# Git: Introducción
+
+## Contexto
+
+- 2005
+- Para el desarrollo de Linux
+ - Miles de desarrolladores
+ - Código fuente muy extenso
+- Es distribuído (*distributed*)
+- Se basa en *snapshots*
+- La mayoría de las operaciones ocurren en local y no son destructivas
+- Control de integridad mediante SHA-1 (o SHA-256)
+- Tres estados:\
+ `ARCHIVO — STAGING AREA — REPOSITORIO`
+
+## Instalación
+
+Debian:
+
+```
+apt-get install git
+```
+
+En el resto de distros es similar.
+
+## Sistema de configuración
+
+- Sistema: `/etc/gitconfig`
+- Configuración general: `~/.config/git/config` o `~/.gitconfig`
+- Local por repositorio: `$REPOSITORIO/.git/config`
+
+Funciona en modo cascada, de local a sistema. Para ver de dónde se toman los
+valores:
+
+```
+git config --list --show-origin
+```
+
+## Gestión de configuración
+
+Los comandos leen y escriben los archivos de configuración de forma ordenada,
+aunque se puede hacer a mano:
+
+```
+git config [--global] <SECTION>.<KEY> [<VALUE>]
+```
+
+- El `<VALUE>` es opcional. Si se usa, se escribe la configuración con ese
+ valor. Si no se usa, se devuelve el valor en esa línea de la configuración.
+
+Realmente es más complejo que esto: ver documentación.
+
+## Configuración inicial
+
+Definir la identidad para que se registre el autor de los commits:
+
+```
+git config --global user.name "John Doe"
+git config --global user.email johndoe@example.com
+```
+
+Seleccionar editor de texto por defecto:
+
+```
+git config --global core.editor vim
+```
+
+## Ayuda
+
+- `git help`
+- `man`
+
+
+
+
+# Git basico
+
+## Obtener un repositorio
+
+Dos alternativas:
+
+- Crear un repositorio nuevo: `git init`. Esta opción crea un directorio `.git`
+ en el directorio actual, donde se almacenará la información interna de Git.
+
+- Clonar un repositorio existente: `git clone <URL>`. Esta opción copia el
+ repositorio en el directorio actual, incluyendo su `.git`. Puede usar varios
+ protocolos diferentes
+
+
+## Estados de un archivo
+
+![Ciclo de vida de los archivos](img/lifecycle.png){ height=180px }
+
+
+## Visualizar estado de un repositorio
+
+- `git status`
+- Para ignorar archivos, añadirlos a un archivo `.gitignore`.
+ Utiliza *glob pattern*s.
+
+## Para cambiar de estado
+
+- Añadir archivos con: `git add`
+- Para enviar los cambios al *staging area*: `git add`
+
+## Para ver cambios
+
+- `git diff`
+- `git diff --cached|--staged`
+- `git difftool` (si está configurada)
+
+La salida de `git diff` puede guardarse a archivo y después aplicarse sobre el
+repositorio mediante `git apply`.
+
+
+## Para escribir los cambios
+
+- `git commit`
+
+Pide rellenar un mensaje mediante el `$EDITOR` o el `git config --global
+core.editor`
+
+
+## Borrar archivos
+
+- `git rm`
+- `git rm --cached`
+
+## Renombrar
+
+- `git mv`
+
+Equivalente a `git rm` + `git add`.
+
+
+## Para ver la historia
+
+- `git log`
+
+Es un comando muy complejo.
+
+- `-<N>` Muestra los últimos N commits.
+- `-p/--patch` muestra el *patch*.
+- `--stat` muestra estadísticas.
+- `--pretty` cambia el formato de salida, tiene muchas opciones.
+- `--graph` modo gráfico.
+
+Se pueden combinar:
+
+`git log --graph --pretty=oneline --decorate --all`
+
+
+## Filtrar la historia
+
+La salida de `git log` puede filtrarse:
+
+- `--since` desde cuando, por ejemplo: `--since=2weeks`
+- `--author` filtrar por autor
+- `--grep` búsqueda por palabras clave
+- `-S/-G/...` *pickaxe function*s, buscan palabras en los cambios aplicados en
+ el commit.
+- `git log -- archivo` mostrar commits que afectaron a ese archivo.
+- `--no-merges` descartar commits de tipo *merge*
+
+Ver la ayuda: `git help log`
+
+
+## Deshacer cambios
+
+- `git commit --amend` reescribe el último commit
+ - Cambiar el mensaje
+ - Añadir o quitar archivos
+ - ...
+
+- `git reset` quita cambios de la *staging area*. CUIDADO con `--hard`.
+- `git checkout` para deshacer los cambios. CUIDADO
+- `git restore` comando nuevo (>2.23.0), parecido a los anteriores.
+
+Los comandos `reset` y `checkout` son parte integral de Git y realizan más
+acciones que las que se acaban de mencionar. Se estudian más adelante en
+detalle.
+
+## Remotos (*remote*)
+
+Son copias de un repositorio. Se pueden actualizar enviándoles cambios locales
+mediante *push* o se pueden descargar cambios desde ellos para actualizar el
+repositorio local mediante *fetch* y *pull*.
+
+Pueden ubicarse en otras máquinas y accederse mediante la red, en otras partes
+del mismo disco duro, etc.
+
+## Gestión de remotos
+
+- `git remote`
+
+Están escritos en `.git/config`. También pueden editarse a mano. No se
+recomienda hacerlo.
+
+
+- `git clone` añade el remoto llamado `origin` automáticamente, apuntando al
+ repositorio del que se clonó.
+- `git remote -v`
+- `git remote add <nombre> <URL>`
+- `git remote show <nombre>`
+- `git remote rename <nombre> <nuevo nombre>`
+- `git remote remove <nombre>`
+
+## Intercambiar información con el remoto
+
+
+- `git fetch [<remote>]` descarga la información del remoto sin alterar el
+ repositorio local.
+
+- `git pull` aplica un `fetch` seguido de un `merge` si las ramas están
+ configuradas correctamente:\
+ ```
+ git pull = git fetch + git merge
+ ```
+
+- `git push [<remote> <branch>]` sube los cambios al remoto de forma segura. En
+ caso de conflicto los rechaza.
+
+
+## Etiquetas (*tag*)
+
+Nombres que se les pueden asignar a los commits. Sirven para identificar los
+commits con nombres fáciles de recordar, son útiles para señalar *releases*.
+
+- `git tag -l` muestra las etiquetas
+
+Hay dos tipos de etiquetas:
+
+- **Lightweight**: son referencias, como una rama fija. Sólo son un
+ identificador.
+- **Annotated**: son un objeto más en Git, como un commit, y pueden tener
+ autor, firma, mensaje, etc.
+
+## Annotated tags
+
+- `git tag -a <nombre> [<commit>]`
+
+Se muestran en `git show`.
+
+## Lightweight tags
+
+- `git tag <nombre> [<commit>]`
+
+`git show` no las muestra, sino que muestra el commit al que hacen referencia.
+
+## Compartir tags
+
+- `git push [<remote>] <tag>`
+- `git push [<remote>] --tags` para enviar todos
+
+## Eliminar tags
+
+- `git tag -d <tag>`
+- `git push [<remote>] --delete <tag>`
+
+
+## Aliases
+
+Permiten escribir nuevos comandos usando los que ya están disponibles en Git
+como base. Son valores de la configuración:
+
+- `git config --global alias.co checkout`
+- `git co` => `git checkout`
+
+Yo uso mucho:
+
+```
+git config --global alias.lg log --graph \
+ --decorate --all --oneline
+```
+
+
+
+# Git básico: Ramas
+
+## Rama (*branch*)
+
+Las ramas permiten al desarrollo del repositorio tomar diferentes caminos sin
+alterar el desarrollo principal.
+
+En Git las ramas son fundamentales, ya que está diseñado alrededor de éstas.
+
+En otros sistemas de control de versiones el uso de ramas es pesado, pero en
+Git es muy ligero y no es raro ver repositorios con cientos de ramas distintas.
+
+## Git por dentro
+
+- Cuando los archivos se mandan al *staging area* Git guarda sus contenidos en
+ un *blob* y calcula su *checksum* (SHA-1)
+- Cuando se aplica un commit, calcula los checksums de todos los directorios y
+ construye un objeto *tree* por cada uno de ellos. Los objetos *tree* apuntan
+ a los objetos *blob* indicando su nombre, y formando la estructura de
+ archivos. El *tree* principal se añade al commit, junto con el autor, fecha,
+ mensaje y otros datos. Se almacena el objeto *commit* resultante.
+- Los *commit* hacen referencia a sus *commit* padre. Los commits "normales"
+ tienen un único padre, los commits de tipo *merge* tienen varios padres y el
+ commit inicial no tiene padre.
+
+Las ramas son referencias móviles que apuntan a los *commits*.
+
+## Git por dentro
+
+![Datos internos](img/commit-and-tree.png)
+
+## Git por dentro
+
+![Estructura de commits](img/commits-and-parents.png)
+
+## Crear ramas
+
+- `git branch <branchname>`
+
+Por defecto hay una rama llamada `master` (puede configurarse), y siempre debe
+haber al menos una rama, donde se irán añadiendo los commits nuevos.
+
+Git guarda una referencia que apunta a la rama actual: `HEAD`
+
+## Cambiar de rama
+
+- `git checkout <branchname>`
+- `git checkout -b <branchname>` crear rama y saltar a ella
+
+Como `checkout` es un comando complejo se ha añadido el comando `switch` que
+cumple esta tarea de forma más clara:
+
+- `git switch <branchname>`
+- `git switch -c <branchname>` crear rama y saltar a ella
+- `git switch -` saltar a la rama anterior
+
+
+## Ramas y cambios — I
+
+![`git branch testing`](img/head-to-master.png)
+
+## Ramas y cambios — II
+
+![`git checkout testing`](img/head-to-testing.png)
+
+## Ramas y cambios — III
+
+![`git commit ...`](img/advance-testing.png)
+
+## Ramas y cambios — IV
+
+![`git checkout master`](img/checkout-master.png)
+
+## Ramas y cambios — V
+
+![`git commit ...`](img/advance-master.png)
+
+## Ramas y cambios — VI
+
+Visto desde la interfaz de Git:
+
+```
+$ git log --oneline --decorate --graph --all
+* c2b9e (HEAD, master) Made other changes
+| * 87ab2 (testing) Made a change
+|/
+* f30ab Add feature #32
+* 34ac2 Fix bug #1328
+* 98ca9 initial commit
+```
+
+> CUIDADO: Si no se añade `--all` no se muestran todas las ramas al hacer `git
+> log`, sino que sólo se muestra la rama actual.
+
+
+## Ramas y merges — I
+
+![](img/basic-branching-4.png){ height=180px }
+
+## Ramas y merges — II
+
+Caso **fast forward**, una rama contiene la otra
+
+![`git checkout master`\
+`git merge hotfix`](img/basic-branching-5.png){ height=200px }
+
+## Ramas y merges — III
+
+Siempre no es así de fácil:
+
+![](img/basic-branching-6.png){ height=180px }
+
+## Ramas y merges — IV
+
+Se busca el ancestro común (*common ancestor*) y se aplica un *three-way
+merge*.
+
+![`git checkout master`\
+`git merge iss53`](img/basic-merging-1.png){ height=180px }
+
+## Ramas y merges — V
+
+Crea un commit nuevo que combina ambas ramas.
+
+Es un *Merge*: tiene al menos dos padres.
+
+![`git checkout master`\
+`git merge iss53`](img/basic-merging-2.png){ height=180px }
+
+
+## Conflictos — I
+
+El caso de antes no siempre sale bien. Es posible que haya un conflicto si se
+han editado los mismos archivos en las dos ramas.
+
+```
+$ git merge iss53
+Auto-merging index.html
+CONFLICT (content): Merge conflict in index.html
+Automatic merge failed; fix conflicts and then
+commit the result.
+```
+
+## Conflictos — II
+
+```
+$ git status
+On branch master
+You have unmerged paths.
+ (fix conflicts and run "git commit")
+
+Unmerged paths:
+ (use "git add <file>..." to mark resolution)
+
+ both modified: index.html
+
+no changes added to commit (use "git add" and/or
+"git commit -a")
+```
+
+## Conflictos — III
+
+El archivo se ve así:
+
+```
+<<<<<<< HEAD:index.html
+<div id="footer">contact :
+ email.support@github.com</div>
+=======
+<div id="footer">
+ please contact us at support@github.com
+</div>
+>>>>>>> iss53:index.html
+```
+
+Aparecen unos separadores: `<<<<<<<`, `=======` y `>>>>>>>`.
+
+En el primer trozo aparece el contenido del `HEAD` y en el segundo `iss53`.
+
+Si está configurada una herramienta, puede usarse `git mergetool`
+
+
+## Gestión de ramas
+
+- `git branch` muestra las ramas
+- `git branch --merged | --no-merged` muestra las ramas mergeadas o las no
+ mergeadas con la actual.
+- `git branch -d <adarra>` borra ramas. Las no-mergeadas no las borra, hay que
+ hacer `-D` para eso (diferencia mayúsculas y minúsculas).
+- `git branch --move <adarra> <rama_nueva>` cambiar nombre de rama
+- `git push -u|--set-upstream <remote> <adarra>` asigna una rama a un remoto
+- `git push <remote> --delete <adarra>` borra una rama en un remoto
+
+## Workflows habituales
+
+- *Long-running branches*: `master`, `testing` y `development`
+- *Topic branches*: por cada issue o feature se trabaja en una rama
+ independiente.
+
+## Ramas en los remotos
+
+Git guarda referencias a los remotos para poder ver su estado (`git ls-remote
+<remote>` o `git remote show` para verlo).
+
+Las ramas en los remotos pueden verse con el nombre `<remoto>/<rama>`. No son
+ramas normales, sino que se muestran como tal. La diferencia es que estas ramas
+no se pueden alterar de forma directa. La forma de manipularlas es hacer
+cambios en el remoto, para que éstos se reflejen en la rama.
+
+![Ejemplo: el repositorio local tiene dos commits nuevos](img/remote-branches.png)
+
+## Hacer push
+
+- `git push <remote> <branch>` envía la rama al remoto. Hay que hacerlo
+ manualmente para no subir más que la rama que se quería. Facilitando el uso
+ de ramas locales.
+
+- `<rama-local>:<rama-remota>` para usar diferente nombre en local que en el
+ remoto.
+
+## Tracking branches
+
+Es una forma de relacionar una rama remota (*upstream*) y una local
+(*tracking*):
+
+- `git checkout -b <rama> <remote>/<rama>` relaciona `<remote>/<rama>` con
+ `<rama>`
+- `git checkout --track <remote>/<rama>` relaciona la rama actual con la
+ remota.
+- `git checkout <rama>` si la rama local `<rama>` no existe, se crea
+ relacionada con `<remoto>/<rama>` automáticamente.
+- `git clone` crea una rama local relacionada con la remota automáticamente.
+- `git branch -u|--set-upstream-to <remote>/<adarra>` también relaciona las
+ ramas. Ver `git push`
+
+> Una vez relacionadas, para referirse a la rama remota puede usarse
+> `@{upstream}` o `@{u}`
+
+## Hacer pull
+
+Si hay una rama de tracking configurada, hacer `git pull` es equivalente a
+hacer `git fetch` seguido de un `git merge`.
+
+Cuidado: a veces es difícil ver qué ocurre con el `merge`. Para evitar
+problemas, hacer `fetch`, ver el estado del repositorio y hacer el `merge`
+manualmente.
+
+
+## Ramas y rebases — I
+
+![](img/basic-rebase-1.png)
+
+## Ramas y rebases — II
+
+![Al hacer `git merge` pasa esto](img/basic-rebase-2.png)
+
+## Ramas y rebases — II
+
+![`git checkout experiment`\
+`git rebase master`](img/basic-rebase-3.png)
+
+Ahora el merge es *fast-forward* y no añade commit de merge.
+
+
+## Un rebase más complejo — I
+
+![](img/interesting-rebase-1.png)
+
+## Un rebase más complejo — II
+
+![`git rebase --onto master server client`](img/interesting-rebase-2.png)
+
+Pasa los cambios de `client` a `master` sin incluir los de `server`.
+
+Ahora se puede hacer un rebase de `server` en `master` y después hacer un
+`merge` *fast-forward*.
+
+## Cuidado con los rebase
+
+Al hacer rebase, se crean commits nuevos con contenidos similares a los que
+había anteriormente, pero con diferente valor. Al enviarlos a un remoto
+(`push`) se fuerza al resto de nuestro equipo a hacer rebases:
+
+- `git push --force` reescribe la historia en el remoto. Es peligroso.
+- `git pull --rebase` puede ayudar a la hora de hacer pull de un repositorio en
+ el que hayan ocurrido rebases. Se puede configurar Git para que siempre se
+ comporte así en el pull.
+
+## Rebase vs Merge
+
+En función de la filosofía con la que se trabaje es interesante usar uno u
+otro.
+
+- Si se entiende el repositorio como un histórico de cambios el *rebase* no
+ tiene sentido, porque puede manipular el pasado. (*El sistema de control de
+ versiones fossil usa esta filosofía, y no tiene forma de hacer rebases*)
+- Si se entiende el repositorio como un *making-of*, tiene sentido aplicar
+ rebases, porque limpian la historia haciéndola más fácil de leer.
+
+Consejo: En local todo vale. En el servidor compartido cambiar la historia es
+peligroso porque afecta al equipo de desarrollo, usuarios, etc.