Cheatsheet Git
===
## Afficher la config du CLI
```bash=
git config --global -l
```
## Ajouter des alias utiles
```bash=
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st 'status -sb'
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.ll 'log --oneline'
```
## Stash
```bash=
git stash # pour remiser tout ce qui est en stage
git stash --include-untracked
git stash push -m "my_stash" # pour donner un nom parlant à son stash
git stash list
git stash pop # applique la dernière remise et supprime de la liste
git stash pop stash{n} # applique la nème remise et supprime de la liste
```
## Switch
```bash=
git switch -c new-branch # déplace les changements unstaged sur une nouvelle branche.
```
## Éviter le git pull qui peut avorter pour cause de conflit
Si l'on veut récupérer une version pure de la remote (exemple, sur un serveur de recette qui ne doit jamais commit):
```bash=
git fetch origin
git reset --hard origin/master
```
Cela supprimera toutes les modifications faites en local.
## Rechercher une chaîne dans un tag
```bash=
git grep "hello" v2.5
```
## Créer une branche à partir d'un tag
```bash=
# start a new branch named "stable" based at v2.5
git branch stable v2.5
```
## Log & history
```bash=
git log # See Git history
git log stable..master
git log branch..origin/master # see the delta with a remote branch
git log v2.5..v2.6 # commits between v2.5 and v2.6
git log v2.5.. # commits since v2.5
git log --after=2.weeks # filter for period (after=since)
git log --before=2020-01-22 # filter for periode (before=until)
git log --since="2 weeks ago" # commits from the last 2 weeks
git log v2.5.. Makefile # commits since v2.5 which modify Makefile
git log -p # See Git history with diff
git log -p -3 # to see only the 3 more recent commits
git log -S MY_CONSTANT -p # filter commits w/ update on `MY_CONSTANT`
git show --name-only <commit> # meta informations + files modified
git show --name-status <commit> # same with files status
git show --s <commit> # only the meta informations
git show <commit> # meta informations + files modified + diff
git log -1 -U <commit> # the same, handy to use log filter
```
Pretty log
```bash=
git log --pretty=oneline
```
Log with custom format
```bash=
git log --pretty=format:"%h - %an, %ar : %s"
```
Log with Graph
```bash=
git log --pretty=format:"%h %s" --graph
```
## Supprimer une branche
```bash=
# delete branch locally
git branch -d localBranchName
// delete branch remotely
git push origin --delete remoteBranchName
```
## Voir toutes les branches
```bash=
git branch -a # voir les branches locales et remote
git branch -r # voir uniquement les branches remote
git branch -a -v # voir en plus le SHA1 du dernier commit pour la branche
git branch -a -vv # voir en plus le lien entre la branche locale et la branche remote (+ "disparue" si n'existe plus sur la remote)
```
## Undoing things
Modify the last commit
```bash=
git commit --amend
```
Unstage a staged file
```bash=
git reset HEAD README.md
```
Unmodify a modified file
```bash=
git checkout -- README.md
```
## Supprimer le dernier commit
_À ne faire qu'en local bien sûr._
```bash=
git reset --soft HEAD^
```
Les modificationts vont se retrouver en mode staged.
Pour dé stage un répertoire :
```bash=
git reset my-dir
```
## Remote
See the remote
```bash=
git remote -v
git remote show origin
```
Add a remote
```bash=
git remote add john https://github.com/johndoe/azegit
```
Fetch the remote
```bash=
git fetch john
```
> This way, remote branches are locally accessible BUT no merge in your local work is done. For automatically merge, use `git pull`
## Récupérer une branche distante en faire une locale
```bash=
git checkout -b new-local-branch origin/new-branch
# ou s'il y a une seule remote
git checkout new-branch
```
## Fetch & Rebase
Attention :
Ne pas faire
master -> feat 1 -> feat 2
Puis, PR mergée sur master.
Puis feat 2 rebase à partir de master.
Car il va alors devoir rejouer plein de commits intermédiaires compliquées, car il y aura beaucoup de petits changements sur les mêmes zones et de manière incrémentale. C'est inutile car cela se résoudra au final mais impose de multiples gestion de phase de conflit.
Ce qu'il faut faire :
```bash=
git pull master
git checkout feat2
git merge master
````
Cas normal :
```bash=
# récupère les meta data (mais ne merge pas)
git fetch origin master
# rebase l'historique de sa branche courante avec origin/master
git rebase origin/master
# gérer les conflits éventuels et finir le rebase
git rebase --continue
# si branche perso et temporaire (utilisé dans sa propre PR), on peut se permettre d'écraser l'historique
git push origin ma-branche -f
# ou
git push --force origin ma-branche
```
Un rebase doit respecter la [règle d'or du rebase](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing). "Est-ce que quelqu'un d'autre que moi regarde/utilise cette branche?". Si oui, ne pas faire de rebase. Si c'est une branche “privée”, pas de problème.
## Miscealenous
Add execute permission on a file
```bash=
git update-index --add --chmod=+x backup.sh
```