~~stoggle_buttons~~
====== Links ======
* [[https://git-scm.com/doc|Documentación]] (incluye el manual) y [[https://git-scm.com/book/en/v2|manual]]
* [[https://ohshitgit.com/|Oh Shit, Git!?!]]
* [[https://github.com/k88hudson/git-flight-rules|Flight rules for Git]]
* [[https://github.com/larsbrinkhoff/fearless-git|fearless-git: Rewrite Git History Like There's No Tomorrow]]
* [[https://dhwthompson.com/2019/my-favourite-git-commit|My favourite git commit]]
* [[https://github.com/src-d/hercules|hercules]] Estadísticas avanzadas de git (hay hacer ''%%alias labours="python3 -m labours"%%'' porque por defecto pilla el python2, y luego también se les olvida el pipe:. Funciona con versiones antiguas de python (3.6, 3.7), si no te tienes que compilar tú tus paquetes con dependencias binarias
* ''%%hercules --burndown --burndown-people file://$PWD | labours -m overwrites-matrix%%''
* [[https://github.com/augmentable-dev/askgit]] Queries sql contra git
* [[https://www.linuxuprising.com/2019/11/forgit-interactive-git-commands-with.html|forgit]] git + fzf
* [[https://github.com/git-learning-game/git-hydra|game about learning git]]
====== Guía rápida ======
===== Ciclo básico de desarrollo =====
git clone # Descargar el repositorio (sólo una vez, al principio)
git pull # Pillar lo que ha cambiado desde la última vez
git add
git add * # añadir todo lo que se ha modificado
git commit -m "He cambiado esto y esto otro"
git push # Sube los cambios al servidor
''git log'' sirve para ver los commits pasados. Se puede filtrar por usuario, no mostrar los merges, filtrar por fecha, grepear, ...
''%%git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"%%'' para que se vea bonito, ''git lg -p'' para ver el diff de cada commit
* Configurar ''user.name, user.email, core.editor''
* Configurar [[https://help.github.com/articles/dealing-with-line-endings|.gitattributes]] para los saltos de línea
* ''git ls-files %%--%%deleted | xargs git add'' añadir sólo archivos borrados
* ''git diff %%--%%no-index A B'' para diff con estilos de git
===== Deshaciendo cosas =====
* ''git reset HEAD '' deshace ''git add ''
* ''git reset HEAD'' deshace todos los ''git add'' que hayamos hecho
* ''git commit %%--%%amend'' antes de ''git push'' enmienda el commit que hemos hecho
* ''git checkout %%--%% '' BORRA los cambios (locales) del archivo sin commitear y lo reemplaza con la versión que hay en el repositorio
* ''git stash'' Descarta los cambios locales, pero los guarda para más tarde con ''git stash pop''
* ''git reset %%--%%hard'' Resetea el repositorio local, BORRA y reemplaza para que el repositorio local se quede igual que el remoto
* ''git checkout '' Cambia a un commit anterior para ver cambios.
* ''git revert '' DESHACE y BORRA todos los cambios a partir del commit indicado. ''git reset %%--%%hard'' esencialmente revierte al último commit
* ''git reset %%--%%hard '' resetea todo a ese commit, por si tienes algunos commits que no quieres subir
* ''git revert %%--%%no-commit master~9..master'' revierte los últimos 9 commits de master
===== He subido archivos binarios al git y tarda 15min en clonarse =====
[[https://medium.com/@buzaa/why-you-should-not-push-binary-files-to-git-and-what-to-do-if-you-do-29f34692cef0]]
* ''%%git filter-branch --tree-filter "rm -r -f " HEAD%%''
* Forzar el push
===== reset vs checkout =====
Situación inicial
object master
object HEAD
e138c7e -> 72625a3
72625a3 -> 13b2cbe
13b2cbe -> 75cdf49
master --|> 75cdf49
HEAD --|> master
''git reset 13b2cbe''
object master
object HEAD
e138c7e -> 72625a3
72625a3 -> 13b2cbe
13b2cbe -> 75cdf49
master --|> 13b2cbe
HEAD --|> master
''git checkout 13b2cbe'' (Produce detached HEAD)
object master
object HEAD
e138c7e -> 72625a3
72625a3 -> 13b2cbe
13b2cbe -> 75cdf49
master --|> 75cdf49
HEAD --|> 13b2cbe
DETACHED HEAD se soluciona simplemente con:
''git checkout ''
===== Borrando cosas =====
* ''git push origin %%--%%delete branch'' elimina ''origin/branch'' (remoto)
* ''git push %%--%%delete origin mytag'' lo elimina en remoto, y ''git tag rm mytag'' en local
===== Arreglando desastres =====
* ''git push origin HEAD:'' cuando estamos en detached HEAD y queremos hacer un commit. Me ha pasado cuando hago ''git checkout ; git merge origin ; git push # FALLA'', en vez de hacer ''git revert'' porque había muchos commits en medio. **Después habrá que hacer ''git pull; git checkout ''** porque seguimos trabajando en detached HEAD
===== Evitando desastres =====
* Antes de hacer un rebase de new_feature contra una rama old_feature, que partió de una rama estable como master, hay que hacer primero un rebase de old_feature contra master, por que si divergen las historias, hay conflictos
* Una alternativa sería mergear de new_feature con old_feature, pero si la rama está desactualizada, git sabe qué commits tiene que coger? (Creo que sí)
====== Git en profundidad ======
===== git add =====
===== git commit =====
* Commit con el mismo mensaje que el anterior: ''%%git commit -C HEAD%%''
* ''%%--amend%%'' para enmendar un commit anterior
===== git log =====
* ''%%git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"%%''
* ''git log %%--%%abbrev-commit %%--%%name-only'' muestra hash abreviado y nombre de archivos cambiados
''%%git log --pretty=format%%''
^ Opción ^ Descripción ^
| ''%H/%h'' | Commit largo/abreviado |
| ''%an/%ae'' | Author name/email |
| ''%ad/ar'' | Author date/relative date |
| ''%s'' | Subject (commit message) |
| ''%n'' | Salto de línea |
Las ''a'' se pueden cambiar por ''c'' para mostrar el commiter name y demás. Commiter es el que hace el commit y author el que escribe el código. Normalmente coincide, pero al hacer una Pull Request difiere (ya que sólo los que trabajan en el proyecto pueden hacer commits al repositorio principal)
* Soporta fechas con ''%%--date=[local|short]%%''
* strftime con ''%%--date=format[-local]:"%Y-%m-%d %H:%M:%S"%%''
* ''--graph'' para que se vean las ramas separarse y juntarse
==== filtros ====
* ''%%--[since|after], --[until|before]%%''
* ''%% --author, --committer%%''
* ''%% --grep -> el mensaje matchea. Acepta argumentos de grep como -E, pero van antes de --grep%%''
* ''%% -S -> los commits han eliminado o añadido código que matchea%%''
* ''%% -G -> lo mismo con regex%%''
* ''%% -L :func:script.py -> Dentro de script.py, cambios hechos a la función/clase func%%''
* ''%% -L ,:script.py -> Dentro de script.py, cambios hechos a as líneas entre y %%''
==== Buscar archivos en el histórico ====
=== Por nombre de archivo ===
git log --all --full-history -- "**/thefile.*"
git lg -S"#+transclude" -p -- . ":\!path/to/file"
=== Por línea ===
[[https://stackoverflow.com/questions/1337320/how-to-grep-git-commit-diffs-or-contents-for-a-certain-word/1340245#1340245]]
git grep $(git rev-list --all)
git grep $(git rev-list --all -- lib/util) -- lib/util # Buscar en un subárbol
git log -S
git log -G
===== git merge =====
* [[https://howchoo.com/git/git-merge-conflicts-rebase-ours-theirs|Estrategias de merge]]
===== git grep =====
git grep -n # Saca el número de línea y es clickable en vscode
git grep buscar -- "*.py" # los "" son necesarios, si no falla
git grep -i task -- './*' ':(exclude)*.md # Buscar excluyendo los .md
===== cherry picking y diff apply =====
* git cherry-pick **no aplica sólo un commit**, sino que mueve el HEAD hacia ese commit (lo que puede provocar conflicto de merge aunque en el commit específico que coges no haya dichos conflictos)
* La alternativa es [[https://stackoverflow.com/questions/12320863/how-do-you-take-a-git-diff-file-and-apply-it-to-a-local-branch-that-is-a-copy-o|diff-apply]] ''%%git diff d892531 815a3b5 | git apply%%''
===== Información =====
* ''git show-branch (|-r|-a)'' Muestra todas las ramas locales|remotas|todas
* ''git blame '' Muestra quién ha escrito cada línea de
===== Configuración =====
- ''/etc/gitconfig %%-> --%%system %%--%%system-wide''
- ''~/.gitconfig or ~/.config/git/config %%-> --%%global''
- ''repo/.git/config %%-> --%%local''
==== .gitignore ====
* Es un archivo para hacer una lista de los archivos que **no** se tienen que seguir (track), es decir, git ignorará esos archivos y no se añadiran incluso tras hacer ''git add *''
* ''git add -f '' fuerza añadir el archivo incluso si está ignorado en ''.gitignore''
* ''%%git config --local core.excludesfile hidden/.gitignore_local%%''
===== remotes =====
''git branch %%--%%set-upstream-to=origin/master master'' enlaza origin/master con tu master local, de manera que no hay que hacer ''git push origin master'' o ''git pull origin master''
==== Crear un repositorio ====
server:$ git init --bare --shared
local:$ git clone
==== Submódulos de git ====
* ''%%git submodule update --init%%''
* ''cd'' al repo y ''git pull'' para coger el último cambio
* ''git submodule update'' para quedarte up to date con el repo original
===== Herramientas =====
==== diff ====
''git diff ''
Si sólo ponemos un commit y no tenemos ningún unstaged changes/untracked files, entonces
''git diff '' es lo mismo que ''git diff HEAD''
[[https://stackoverflow.com/questions/31454603/order-of-commit-arguments-in-git-diff]]
==== stash ====
git stash
git stash list; git stash apply @stash{2}; git stash pop # aplica el primero
git stash --keep-index (stash sin checkout a la rama) --include-untracked (-u)
git stash branch # Nueva rama para el stash
git stash push -m "mensaje de stash" --
==== patchs, interactivo ====
git add -i # abre modo interactivo
# patch -> ciertas partes del código, añadir ciertas líneas
git add --patch
git checkout --patch
git stash push --patch
==== grep ====
git grep -n (número de línea) -c (contar ocurrencias) -p (en qué parte del código) --
==== rev-list ====
git rev-list .. # Saca todos la lista de commits de inicio a final
====== Git Standards ======
* [[https://nvie.com/posts/a-successful-git-branching-model/|A successful Git branching model]]
* [[https://www.conventionalcommits.org/|Conventional Commits]]
* [[https://commitizen-tools.github.io/commitizen/|Commitizen]] -> Generar [[https://keepachangelog.com|Changelogs]] en base a Conventional Commits
* [[https://semver.org/]]