Git
Instrucciones para configurar Git y a su vez GitHub
Configuración global
Para forzar a que se guarde de forma local la configuración
git config credential.helper store
Asignar email y nombre para los commits
git config --global user.name "Manuel Muñoz"
git config --global user.email "my_email@gmail.com"
Asignar firma GPG y firmar los commits por defecto con dicha firma (Nota: primero es necesario generar la firma GPG para poder asociarlo de forma global)
git config --global user.signingKey UUID_DE_LA_FIRMA
git config --global commit.gpgsign true
Si se desea eliminar la firma de la configuración global, se utiliza el parametro --unset
git config --global --unset commit.gpgsign
Si tenemos establecido un correo de forma global, pero dentro de una carpeta que contiene otros repositorios, podemos establecerlo dentro de ese directorio. Primero es necesario modificar el fichero ~/.gitconfig y añadirle
[user]
name = Manuel Muñoz
email = my_custom_email@gmail.com
[includeIf "gitdir:~/GitHubPersonal/"]
path = ~/GitHubPersonal/.gitconfig
Y a continuación creamos el fichero .gitconfig dentro de ese directorio con la configuración especifica
[user]
email = my_other_email@gmail.com
Git Cheat Sheet
Para clonar un repo
git clone <URL-REPOSITORIO>
Para iniciar uno nuevo (en local)
git init
Para visualizar la configuración global de git
git config --global --list
Para visualizar la configuración asociada a un repo
git config --list
Para cambiar de rama
git checkout <newbranch>
git checkout develop
Variante con
switchgit switch <newbranch> git switch develop
Para cambiar de rama pero sin guardar previamente los cambios realizados en la anterior rama
git switch --discard-changes <newbranch>
git switch --discard-changes develop
Para crear una rama a partir del commit actual
git checkout -b <newbranch>
git checkout -b feature-M001
Variante con
switchgit switch -c <newbranch> git switch -c feature-M001
Para crear una rama vacía
git checkout --orphan <branch>
git checkout --orphan new-docs
Variante con
switchgit switch --orphan <branch> git switch --orphan new-docs
Para borrar una rama en local
git branch -d <branch>
git branch -d test01
Para borrar una rama en remoto
git push origin -d <branch>
git push origin -d test01
Para crear un commit, añadir todos los ficheros modificados o borrados, firmarlos y añadirle un mensaje.
git commit -a -S -m "My message"
Si por algún motivo nos hemos olvidado de añadir un archivo al último commit podemos añadirlo con el parámetro --amend. Nota: no hacerlo bajo ningún concepto
git commit <file> --amend
Para el ejemplo anterior, la opción recomendada es resetear HEAD a un commit anterior, de esta forma eliminamos el último commit con el comando reset. Además, podemos especificar los niveles a retrasar indicando el número de commits a resetear para HEAD
git reset HEAD~<integer_value>
git reset HEAD~1
Para borrar todos los archivos de una rama
git rm -rf .
Para descargar los cambios de remoto en local
git pull origin
Para sincronizar los cambios de remoto en local (no descarga nada)
git fetch
Para sincronizar los cambios en remoto en local pero previamente eliminar cualquier referencia de ramas que no existen en remoto
git fetch -p
Para subir los cambios de local a remoto
git push origin
Si una rama local no se encuentra en remoto, utilizamos el parámetro -u o --set-upstream para añadirla en el remoto
git push -u origin <branch-name>
Si queremos subir todas las ramas de local a remoto
git push --all -u
Para forzar a subir una rama en local, podemos utilizar el parametro --force, pero solo si utiliza una sola persona el repo
git push --force origin master
Si tenemos una rama en remoto y forzamos a que se actualice con el --force, es posible que los cambios que realice otra persona en la misma rama se pierdan, para ello utilizamos el parametro --force-with-lease, de esta forma comprueba que los cambios que subamos no se ven afectados por los cambios realizados por otra persona en la misma rama.
git push --force-with-lease origin master
--force-with-lease alone, without specifying the details, will protect all remote refs that are going to be updated by requiring their current value to be the same as the remote-tracking branch we have for them.
Para mostrar los mensajes de los commits confirmados
git log -n5
Para crear un tag, añadirle una versión y un mensaje
git tag -a v1.1.1 -m "My message"
Comprobar los Tags del proyecto
git tag -n5
Eliminar un tag en local y en remoto
git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag -d v1.1.8
git push origin :refs/tags/v1.1.8
Para enviar un tag a remoto, se especifica el tag a origen, también podemos enviar todos los tags de una sola vez a origen
git push origin --tags
git push origin v1.1.1
git push origin <branch> --tags
Si deseamos cambiar de rama pero actualmente tenemos cambios, tenemos que guardar dichos cambios, pero sino queremos guardarlos en ese momento podemos descartarlos
git stash
Si deseamos recuperar los cambios de los archivos modificados en la rama
git stash pop
Para añadir ramas de forma local a un repo
git checkout <branch> && git push origin <branch>
git checkout mmunoz && git push origin mmunoz
Cuando tenemos 2 ramas que parten del mismo punto, la segunda rama añade nuevos cambios y deseamos guardar dichos cambios en la primera rama, es necesario cambiar a la primera rama y después hacer un merge de la segunda rama
git checkout <primera-rama> && git merge <segunda-rama>
git checkout mmunoz && git merge mmunoz-tests
Cuando tenemos 2 ramas que parten del mismo punto, la segunda rama añade nuevos cambios y deseamos guardar dichos cambios en la primera rama pero en un sólo commit, es necesario cambiar a la primera rama, después hacer un merge de la segunda rama con el modificador --squash y por último es realizar un commit
git checkout <primera-rama> && git merge --squash <segunda-rama> && git commit -m "My Message"
git checkout mmunoz && git merge --squash mmunoz-tests && git commit -m "Squashed merge"
Cuando tenemos una rama con un archivo más actualizado en origen y en local se ha modificado el mismo archivo, pero no queremos conservar los cambios del archivo en local
git checkout <filename>
git checkout FLUTTER.md
Para comparar un commit con un Tag con otra rama, se especifica el TAG con la rama a comparar
git diff --stat <tag> <branch>
git diff --stat v1.1.8 mmunoz
Para visualizar la configuración del origin
git remote -v
origin https://git-codecommit.eu-west-2.amazonaws.com/v1/repos/sobwayFlutter (fetch)
origin https://git-codecommit.eu-west-2.amazonaws.com/v1/repos/sobwayFlutter (push)
Para añadir un nuevo origin a un proyecto
git remote add origin <url-repo>
git remote add origin https://github.com/DaswareTech/DEBOS.App.Sobway.git
Para renombrar un origin
git remote rename <origin> <new_origin>
git remote rename origin origin-aws
Para eliminar un origin
git remote remove <origin>
git remote remove origin-aws
Para contar el total de commits de una rama
git rev-list --count HEAD
Para contar el total de commits de una rama hasta el commit actual
git rev-list --count develop..HEAD
Muestra el total de commits por cada usuario
git shortlog -s -n
Git Flow
Git Flow se basa en la creación y uso de ramas específicas para cada etapa del desarrollo de un proyecto
Para iniciar un repositorio local y establecer la estructura de ramas de Git Flow, creando las ramas develop, main y una serie de ramas auxiliares para el manejo de releases, hotfixes y features
git flow init
Mostrar
Initialized empty Git repository in ~/project/.git/
No branches exist yet. Base branches must be created now.
Branch name for production releases: [main]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Para crear una nueva rama para el desarrollo de una nueva característica, basándose en la rama develop
git flow feature start feature_branch
Para finalizar el desarrollo de una característica, fusionando los cambios en la rama develop y eliminando la rama
git flow feature finish feature_branch
Git LFS
La extensión LFS permite gestionar mejor los archivos grandes de un repositorio, guardando punteros a dichos archivos. Esta extensión esta soportada en sitios como Github
El primer paso es instalar dicha extensión, disponible en la web https://git-lfs.github.com/, en ubuntu se puede instalar mediante apt
apt install git-lfs -y
Es necesario activar por cada repositorio dicha extensión
git lfs install
Acto seguido indicamos las extensiones de archivos que deseamos que se gestione con LFS
git lfs track "*.psd"
Acto seguido nos creará un archivo .gitattributes en caso de no estar disponible previamente
*.psd filter=lfs diff=lfs merge=lfs -text
Nota: El servicio de Github limitada los archivos que superen los 100 MB y se recibe una advertencia cuando los archivos superen los 50 MB sino está añadido al listado de LFS
GitHub blocks pushes that exceed 100 MB
Git Submodule
El comando submodule permite clonar un repositorio dentro de otro repositorio, de esta forma podemos tener un repo de forma privada que contenga información que no sea relevante para todo el público pero que esté disponible para consultar desde otro repo
A groso modo, con submodule podemos tener un link a otro repo dentro de nuestro repo principal
Para mostrar los submódulos dentro de un repo
git submodule
Clonar repo en carpeta
git submodule add <repo-origin> <folder>
git submodule add https://github.com/jaidis/repo docs/repo
A continuación se guardan los cambios en el repo principal
git add . && git commit -m "Añadido submodulo X"
Cuando se clona un repo que contiene un submodule es necesario iniciar el/los submódulo/s con el comando init
git submodule init
Para descargar la información relacionada de esos subḿodulos
git submodule update
Para eliminar un submódulo dentro de un repo
git rm --cached <mysubmodule>
Formas de actualizar los submodule
Opción A
De forma individual, se realiza un git pull origin
Cuando esté toda la información actualizada se realiza un commit con los cambios traidos por el resto de submódulos
Opción B
De forma individual, se realiza un git fetch (para ver los nuevos cambios) junto con un git merge origin/main
Cuando esté toda la información actualizada se realiza un commit con los cambios traidos por el resto de submódulos
Opción C (recomendada)
Para actualizar todos los submódulos de golpe (y confiar en los cambios que contengan) podemos utilizar el comando git submodule update --remote --recursive
Cuando esté toda la información actualizada se realiza un commit con los cambios traidos por el resto de submódulos
Opción de los cobardes --recurse-submodules
Con el parámetro --recurse-submodules nos permite clonar y sincronizar los repos que contengan submodule sin tener que utilizar comandos extras
git clone --recurse-submodules
git pull --recurse-submodules
Scripts
Para clonar todas las ramas del remoto, partiendo desde master
#!/bin/bash
for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do
git branch --track "${branch##*/}" "$branch"
done
Otra variante
#!/bin/bash
git branch -a | grep -v HEAD | perl -ne 'chomp($_); s|^\*?\s*||; if (m|(.+)/(.+)| && not $d{$2}) {print qq(git branch --track $2 $1/$2\n)} else {$d{$_}=1}'
Enlaces
- Git and Git Flow Cheat Sheet
- Gitflow Workflow
- GitHub - Actions virtual environments
- GitHub - Beautify GitHub Profile
- GitHub - custom domain for your GitHub Pages site
- GitHub - supported grammars
- GitHub - supported grammars - list
- Youtube - Tutorial de Git (Makigas)
