Git avanzado

Licencia de Creative Commons mario@mariogl.com

Git avanzado

Índice

Conceptos iniciales

Git avanzado

Git avanzado

Conceptos iniciales

  • Qué es el control de versiones

Git avanzado

Conceptos iniciales

  • Qué es el control de versiones

Git avanzado

develop

experimento

develop

Conceptos iniciales

  • Qué es el control de versiones

Git avanzado

proyecto

Conceptos iniciales

  • Qué es el control de versiones

  • VCS centralizados / distribuidos

  • Línea de comandos vs. interfaces gráficas

  • Branching

Git avanzado

Conceptos iniciales

Git avanzado

master

develop

feature

feature2

Configuración

Git avanzado

Configuración

  • Variables de configuración
    • Sistema (S.O.): git config --system
    • Global (usuario): git config --global
    • Local (proyecto): git config [--local]
  • Guardar una variable de configuración:
    • git config [ámbito] nombre_variable valor
    • Por ejemplo: git config --system user.name "Mario González"
  • Leer una variable de configuración:
    • git config [ámbito] nombre_variable
    • Por ejemplo: git config --global user.name
  • Listar todas las variables de configuración
    • git config [ámbito] --list
  • Archivos de configuración
    • git config [ámbito] --list --show-origin

Git avanzado

Configuración inicial

  • Configuración proxy:
    git config --global http.proxy http://username:password@host:port
    git config --global https.proxy http://username:password@host:port
  • Configuración usuario:
    git config --global user.name "Mario González"
    git config --global user.email mario@mariogl.com

Git avanzado

  • Configuración saltos de línea:
    git config --global core.autocrlf true    (Windows)
    git config --global core.autocrlf input   (UNIX)

Fundamentos y arquitectura interna de Git

Git avanzado

Fundamentos de Git

  • Working directory

  • Repositorio

Git avanzado

Working directory

Repositorio

(.git)

Fundamentos de Git

  • Working directory

  • Repositorio

  • Commits (snapshots)

Git avanzado

Working directory

Repositorio local

Fundamentos de Git

  • Working directory

  • Repositorio

  • Commits (snapshots)

  • Stage

Git avanzado

Working directory

Repositorio local

Stage

archivo1.java

archivo1.java

archivo1.java

archivo1.java

archivo2.java

archivo2.java

archivo1.java

archivo2.java

archivo2.java

Fundamentos de Git

  • Referencias

    • HEAD

    • Ramas

    • Tags

Git avanzado

Fundamentos de Git

  • Tipos de tags:
    • Ligera

    • Anotada

  • Añadir tag ligera:
    git tag nombre_tag [commit]
  • Añadir tag anotada:
    git tag -a nombre_tag -m "Mensaje tag" [commit]

Git avanzado

Fundamentos de Git

Git avanzado

Commits

Git avanzado

Preparando el commit

  • Añadir nuevos archivos al índice (empezar a versionar):
    git add <path>

  • Añadir modificaciones al stage:
    git add <path>

  • Información sobre el estado de las tres zonas:
    git status

  • Borrar archivos:
    git rm path

  • Sacar un archivo del repositorio sin borrarlo en el Working Directory (desversionar):
    git rm --cached path

  • Añadir modificaciones concretas dentro de un mismo archivo:
    git add --patch

Git avanzado

Preparando el commit

  • Quitar modificaciones del stage:
    git reset HEAD <path>
    git restore --staged <path>  (experimental)

  • Deshacer cambios del Working Directory:
    (operación irreversible)
    git checkout -- <path>  
    git restore <path>  (experimental)

Git avanzado

Preparando el commit

  • Hacer el commit:
    git commit [-m "Mensaje"]

  • Cambiar el editor por defecto:
    git config [ámbito] core.editor <nombre-editor>

  • Evitar mensajes genéricos como "Cambios", "Nuevo archivo", "Correcciones", "CSS", "Merge"...

Git avanzado

😑

😒

👽

💩

😔

🤓

👵

🤯

Preparando el commit

Git avanzado

Preparando el commit

  • Hacer el commit:
    git commit [-m "Mensaje"]

  • Cambiar el editor por defecto:
    git config [ámbito] core.editor <nombre-editor>

  • Evitar mensajes genéricos como "Cambios", "Nuevo archivo", "Correcciones", "CSS", "Merge"...

  • Aislar pocos cambios en cada commit
    (ejemplo)

Git avanzado

Preparando el commit

  • Modificar el último commit:
    git commit --amend

  • No hacer --amend si el commit ya se había subido al remoto

Git avanzado

El commit

  • Autor / commiteador

  • Fecha

  • Mensaje

  • Padre/s

  • Hash SHA-1

Git avanzado

- Ejercicio 1 -

El log

  • Cómo referenciar a un commit

    • Por su identificador: hash SHA-1

    • Por el nombre de una rama

    • Por el nombre de una tag

    • Por su posición relativa:
      HEAD^, develop^2, e873Xc9^^...
      HEAD~, develop~2, e873Xc9~~...

    • Por su posición en el listado de reflog: HEAD@{n}

  • Ver el contenido de un commit:
    git show <commit>

Git avanzado

El log

Git avanzado

  • Ver el histórico de commits:
    git log [referencia]

  • Ver el log compacto:
    git log --oneline

  • Ver el log de todas las referencias:
    git log --all

  • Ver ramificaciones en el log:
    git log --graph

El log

Git avanzado

  • oneline + fecha + autor

  •  

  • Crear un alias:
    git config --global alias.milog "log --oneline --graph --all"

  • Mostrar los cambios en los commits:
    git log --patch

git log --date=short --pretty=format:"%C(yellow)%h%Creset%C(red)%C(bold)%d%Creset%C(white)(%cd %an)%Creset %s"

El log

Git avanzado

  • Filtrar el log por fechas:
    git log --since=<fecha> --until=<fecha>

  • Filtrar el log por autor/commiteador:
    git log --author=<nombre> | --committer=<nombre>

  • Ver el log de un archivo:
    git log <archivo>

  • Ver el log de unas líneas:
    git log -L <inicio>,<fin>:<archivo>
  • Ver un rango de commits:
    git log <commit1>..<commit2>
  • Ver un archivo en otro commit (o rama):
    git show <referencia>:<archivo>
  • Ver las diferencias en un archivo:
    git show <referencia> <archivo>

El log

Git avanzado

  • Buscar en qué commit se introdujo un bug:
    git bisect

    • Comenzamos:
      git bisect start

    • Marcamos el commit actual como versión con bug:
      git bisect bad

    • Marcamos un commit antiguo como versión sin bug:
      git bisect good <commit>

    • A partir de aquí, vamos diciendo si está bien o mal:
      git bisect bad
                 o
      git bisect good

El log

  • Saltar a otro commit o rama:
    git checkout <commit o rama>

  • Borrar commits:
    git reset <commit> [--soft|--mixed|--hard]

  • Ver todos los movimientos de las referencias:
    git reflog

  • Culpar:
    git blame <path>

  • Revertir:
    git revert <commit>

Git avanzado

😈

El stash

  • Apartar cambios provisionalmente

    • git stash [push -m "Mensaje"]

    • git stash list

    • git stash show [stash@{n}] [-p]

    • git stash apply [stash@{n}]

    • git stash pop [stash@{n}]

    • git stash drop [stash@{n}]

Git avanzado

Cómo deshacer

Git avanzado

  • Deshacer cambios en el Working Directory

  • Deshacer subidas al stage

  • Deshacer commits

  • Deshacer un commit --amend

  • Deshacer un reset

  • Resolver problemas derivados del Detached HEAD

  • Ignorar archivos que ya están siendo versionados

Reescritura del histórico

Git avanzado

  • Modificar el último commit:
    git commit --amend

  • Borrar commits:
    git reset

  • Comprimir varios commits en uno:
    git reset --soft + git commit

  • Varios cambios de golpe:
    git rebase -i

- Ejercicio 2 -

Conflictos

Git avanzado

Conflictos

  • Cuando hay dos versiones de código y Git no puede decidir cuál es la definitiva

  • Diferencias en formato del archivo (tabulaciones, codificación, saltos de línea...)

  • Pueden aparecer en cualquier operación que implique fusión de código: merge, rebase, cherry-pick, pull

  • Siempre que aparezcan conflictos, primero lanzar git status

  • Git espera a que resolvamos los conflictos y le demos la orden de cerrar la operación

  • Los conflictos se delimitan por marcas en los archivos

Git avanzado

<<<<<<< HEAD
    ↑    
    // Código del commit o rama
    // adonde apunta el HEAD
    ↓
=======
    ↑
    // Código del commit o rama 
    // que estoy intentando fusionar con HEAD
    ↓
>>>>>>> develop

Conflictos

Git avanzado

Conflictos

  • Si queremos resolverlos a mano, editamos el texto, borramos las marcas y dejamos el código definitivo.

  • Para usar una interfaz gráfica específica para resolver conflictos:
    git mergetool

  • Ejemplo: configurar KDiff3
    git config --global merge.tool kdiff3
    git config --global mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"

Git avanzado

Conflictos

  • Una vez resueltos los conflictos, se lo comunicamos a git mediante git add path

  • Para terminar la fusión en un merge o en un pull:
    git commit

  • Para terminar la fusión en un rebase:
    git rebase --continue

  • Para terminar la fusión en un cherry-pick:
    git cherry-pick --continue

Git avanzado

Branching

Git avanzado

Ramas

Git avanzado

Ramas

  • Referencia

  • La rama master

  • Múltiples ramas

Git avanzado

Ramas

  • Listar ramas:
    git branch

  • Crear una rama:
    git branch nombre_rama [commit]

  • Borrar una rama:
    git branch -d/-D nombre_rama

  • Renombrar una rama:
    git branch -m nombre_antiguo nombre_nuevo

Git avanzado

Ramas

  • Ir a una rama:
    git checkout nombre_rama
    git switch nombre_rama

  • Crear rama e ir a ella:
    git checkout -b nombre_rama
    git switch -c nombre_rama

Git avanzado

Ramas - merge

Git avanzado

HEAD

develop

C1

C2

C5

C6

C7

C3

C4

Ramas - merge

  • Fusionar ramas

  • Volcar el trabajo de una rama en otra

  • Objetivo: que una rama tenga los commits de otra

  • Tipos de merge:

    • Fast forward: no crea un nuevo commit, sin conflictos

    • Merge a tres bandas: crea un nuevo commit, posibilidad de conflictos

  • Conflictos: lanzar siempre git status

Git avanzado

Ramas - rebase

Git avanzado

HEAD

develop

C1

C2

C5

C6

C7

C3

C4

Ramas - rebase

  • Aplicar una rama al final de otra

  • Volcar el trabajo de una rama en otra

  • Objetivo: que una rama tenga los commits de otra

  • No crea un nuevo commit

  • Conflictos por pasos: lanzar siempre git status

  • No hacer rebase si ya se ha subido la rama al remoto

Git avanzado

Ramas - cherry-pick

  • Aplicar un commit aislado a una rama

  • No se aplican los commits anteriores

  • Modificador -x para que añada al mensaje "Cherry-picked from XXXX"

  • Conflictos: lanzar siempre git status

Git avanzado

Ramas - mover referencias

  • Mover una rama en la que no estoy
    git branch -f nombre_rama [<commit>]
    git switch -C nombre_rama [<commit>]

  • Mover la rama en la que estoy
    git reset <commit> --hard

  • Si sólo queremos avanzar la referencia de una rama hasta un commit más avanzado:
    git merge <commit>

Git avanzado

El modelo git flow

  • master branch

  • develop branch

  • feature branch

  • bugfix branch

  • hotfix branch

  • release branch

Git avanzado

El programa git flow

  • Instalación (en Windows ya viene instalado con Git)

  • Empezar a usar git flow en un repositorio:
    git flow init

  • Iniciar rama:
    git flow tipo_rama start nombre_rama

  • Cerrar rama:
    git flow finish

Git avanzado

Repositorios remotos

Git avanzado

Repositorios remotos

Git avanzado

  • Los remotes: el remote origin

  • Añadir un remote:
    git remote add nombre_remote URL_remote

  • Renombrar un remote:
    git remote rename nombre_actual nuevo_nombre

  • Cambiar la URL de un remote:
    git remote set-url nombre_remote URL_remote

  • Borrar un remote:
    git remote remove nombre_remote

Repositorios remotos

Git avanzado

  • Clonar un repositorio remoto:
    git clone URL [directorio]

  • Ver ramas remotas:
    git branch -r

  • Ver todas las ramas (locales y remotas):
    git branch -a

  • Trackear rama:
    git branch --set-upstream-to nombre_remote/nombre_rama

  • Ver ramas trackeadas:
    git branch -vv

Repositorios remotos

  • Enviar cambios al repositorio remoto:
    git push nombre_remote nombre_rama

  • Trackear la rama al hacer el push:
    git push -u nombre_remote nombre_rama

  • Sincronizar mi copia local del remoto:
    git fetch -v

  • Traer cambios del remoto:
    git fetch + git merge = git pull
    git fetch + git rebase = git pull --rebase

  • Si siempre queremos pull --rebase:
    git config --global pull.rebase true

Git avanzado

Repositorios remotos

  • Borrar ramas del remoto:
    git push --delete <remoto> <rama>

  • Marcar ramas remotas borradas:
     git fetch --prune

  • Configurar prune por defecto:
    git config [--global|--system] fetch.prune true

  • Ver lo que voy a enviar en el push:
    git diff origin/master master

Git avanzado

Repositorios remotos

  • Subir una tag al remoto:
    git push <remote> <nombre_tag>

  • Subir todas las tags al remoto (desaconsejado):
    git push <remote> --tags

  • Subir las tags anotadas de la rama que vamos a pushear:
    git push <remote> <rama> --follow-tags

  • Configuración para que siempre se comporte como en el punto anterior:
    git config [ámbito] push.followTags true

     

Git avanzado

Pull Requests

Git avanzado

Pull Requests

  • En equipos grandes

  • El repositorio remoto tiene permisos de sólo lectura en la rama develop

  • Los miembros no pueden mergear sus ramas a develop

  • Se sube la rama propia de feature y se solicita el merge a través de la interfaz del servidor

  • Hay un encargado (o varios) de revisar las peticiones de PR, y de realizar el merge de las ramas a develop

Git avanzado

Git avanzado

Git avanzado

By mariogl

Git avanzado

Curso Git avanzado Barcelona 7-14 febrero 2020

  • 725