You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
7.1 KiB

---
weight: 4
title: "Apuntes de Git"
date: 2022-07-28T20:30:52+0200
draft: false
summary: "Pues eso, apuntes sueltos de git"
categories:
- notes
tags:
- git
---
## Detached-HEAD
Lo normal es que te enteres después de hacer uno o varios *commits* en *Detached*
### Con rama temporal
```bash
git branch tmp
git checkout main
git merge tmp
git branch -d tmp
```
### Directamente
```bash
git checkout main
git merge HEAD@{1}
```
## Dejar de seguir un fichero
### Sin borrarlo del directorio de trabajo
1. Primero añadimos el fichero o directorio que quieres ignorar al .gitignore.
2. Ejecutamos:
```bash
git rm -r --cached <file>
git add .
```
Vale para ficheros o directorios, la opción `-r` es para hacerlo recursivo, la opción `--cached` esta para que no borre nada en el _working tree_ solo borra en _index_
__OJO__: Este método borra los ficheros para el resto del equipo cuando hagan un `git pull`
### Queremos hacer modificaciones del fichero en local sin propagarlas al resto del equipo
```bash
git --update-index --skip-worktree <file>
```
## Hacer un merge
1. Asegúrate de completar todas las tareas para dejar lista la rama que vas a fusionar
2. Asegúrate de cambiár a la rama receptora (`git checkout`) y de que estás en ella (`git status`)
3. Actualiza la rama receptora con el _remote_ (puedes usar `git fetch` y `git pull`)
4. Ejecuta el _merge_ con `git merge`
## Borrar submódulo
La forma correcta de hacerlo, conservando el contenido del módulo si es necesario.
```bash
mv a/submodule a/submodule_tmp # keeps a backup of module contents
# do this only if keeping the contents
git submodule deinit -f a/submodule # removes submodule from repo
rm -rf .git/modules/a/submodule # removes submodule reference
git rm -f a/submodule # Note: a/submodule (no trailing slash)
# or, if you want to leave it in your working tree and have done step 0
git rm --cached a/submodule
mv a/submodule_tmp a/submodule
```
## Clonar cuando hay submódulos
La opción `-jn` asigna n recursos para las tareas de clonado.
```bash
git clone --recursive -j8 git://github.com/foo/bar.git
```
## Deshacer un _amend_
Siempre y cuando no la hayas pifiado ya en la historia compartida.
```bash
git reset --soft HEAD@{1}
git commit -C HEAD@{1}
```
La primera orden mueve el _HEAD_ a donde estaba apuntando el _commit_ antiguo. Además dejamos el _index_ intacto para poder hacer otra vez un _commit_ con los cambios pendientes.
`HEAD@{1}` nos da el _commit_ al que _HEAD_ estaba apuntando antes de apuntar al que está apuntando (léelo un par de veces más). No es lo mismo que `HEAD~1` que devuelve el _commit_ padre del _commit_ al que está apuntando _HEAD_.
La segunda sentencia es más retorcida. Significa: _haz un commit del tree actual, usando los detalles del commit erroneo_. Fíjate que `HEAD@{1}` ahora apunta al _commit_ erróneo, puesto que apunta al _commit_ al que apuntaba _HEAD_ antes de apuntar a donde apunta ahora mismo.
## _Revert_ a un _commit_ previo
### _Detached Head_
```bash
git checkout <old-commit-hash>
```
__¡Ojo!__ ahora mismo estás en un _detached head_ es decir no estás en ningún _branch_. Si haces cambios en el _commit_ `<old-commit-hash>` vas a tener muchos problemas. Antes de hacer cambios puedes crear una nueva rama:
```bash
git switch -c <new-branch-name>
```
O volver a donde estabas con `git checkout`
### Con una rama
Si quieres hacer cambios es lo más recomendable:
```bash
git checkout -b old-state <old-commit-hash>
```
### A fuego (quemando las naves)
__Si no tienes nada en la historia compartida__ puedes hacer reset:
```bash
# Perderás todos los cambios locales!
git reset --hard <old-commit-hash>
# Si quieres guardar cambios pendientes
git stash
git reset --hard <old-commit-hash>
git stash pop
# Salvar modificaciones y reaplicar
```
__Si ya has compartido la historia__ tendrás que trabajar con _revert_.
Esta también es la forma más segura y recomendable si quieres conservar la historia completa:
```bash
git revert --no-commit <old-commit-hash>..HEAD
git commit
```
El _flag_ `--no-commit` permite hacer un _revert_ de todos los _commits_ de un golpe, si no lo pasas hará un nuevo _commit_ por cada _commit_ "revertido" y la historia va a quedar un poco enrevesada.
## Cambiar el nombre a una rama
En _Gitlab_ hay que usar _main_ en lugar de _master_.
```bash
git branch -m <New_Branch_Name>
git push origin :<Old_Branch_Name> <New_Branch_Name>
git push --set-upstream origin <New_Branch_Name>
```
## Cambiar de master a main (otro método)
En local:
```bash
git branch -m master main
git status
git push -u origin main
git push origin --delete master
```
Resto del equipo:
```bash
git checkout master
git branch -m master main
git fetch
git branch --unset-upstream
git branch -u origin/main
```
## Crear una nueva rama
```bash
git branch <newbranch_name> # Crea una nueva rama
git checkout <newbranch_name> # Cambia a la nueva rama
git switch <newbranch_name> # También cambia a la nueva rama
git push -u origin <newbranch_name> # Sube la nueva rama al repo remoto
```
Hay otras alternativas:
```bash
git branch <new_branch> ffeeddaa # Crea una rama a partir de un commit
git branch <new_branch> v1.2 # Crea una rama a partir de un tag
git branch --track <new_branch> origin/<base_branch> # Crea una rama a partir de una rama remota
```
## Borrar un fichero con información sensible de la historia del repo
### Usando solo git
```bash
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" \
--prune-empty --tag-name-filter cat -- --all
git push --force --verbose --dry-run
git push --force
```
### Usando git-filter-repo
Es una herramienta escrita en Python (ver [github](https://github.com/newren/git-filter-repo))
## rebase interactive
- <https://jordanelver.co.uk/blog/2020/06/04/fixing-commits-with-git-commit-fixup-and-git-rebase-autosquash/>
## Escribir mensajes de commit significativos
- <https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/>
**Mis tipos de _commit_**
Para usar con este formato:
```bash
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
| Type | Tipo | Descripción |
|:--|:--|:--|
| dev | desarrollo | Es un _commit_ de desarrollo en las fases iniciales del proyecto |
| fix | fix | Se arregla un _bug_ |
| chore | mantenimiento | El _commit_ no implica ni cambios de código ni de test |
| refactor | | refactorización de código que no arregla un _bug_ ni añade features |
| docs | | Añade o retoca documentación del proyecto |
| style | | Cambios que no afectan el significado del código, probablemente relacionados con el formateado del código, y similares |
| test | | Crea nuevos test o corrige test existentes |
| perf | | mejoras de _performance_ |
| ci | | Relacionados con integración contínua (_continuous integration_) |
| build | | cambios que afecta al _build_ del proyecto, p.ej. cambios de dependencias |
| revert | | Vuelta a un _commit_ previo |