Skip to content

Instantly share code, notes, and snippets.

@bessonm
Last active March 29, 2022 16:28
Show Gist options
  • Save bessonm/396d1dd39e927c90a61695cbbcb9cc8e to your computer and use it in GitHub Desktop.
Save bessonm/396d1dd39e927c90a61695cbbcb9cc8e to your computer and use it in GitHub Desktop.
Git Cheatsheet

Configure Git

See the system configuration (usually empty)

git config --list --system

See the global config

git config --list --global

See the local config of the project (you have to be in the directory)

git config --list --local

See all config (global and local)

git config --list

Find in which file is the configuration for each option

git config --list --show-origin

Open and modify the configuration file

git config --edit --global OR git config --edit --local # you must be in the directory

Then, you can modify it as you want and save it.

Moreover, you can set the program you want to open with git. This is core.editor option. Default is set to vi.

You can choose any editor providing its name or the full path to the executable.

Your best bet is to choose a program that opens quickly and you feel comfortable with.

Quickly add a single global option without opening the editor

git config --global user.name "James Bond"

git config --global user.email "jamesmisix.bond@misix.co.uk"

Or just locally in the project

git config --local user.name "Mario Bros"

git config --local user.email "mario.bros@nintendont.co.jp"

Start a project and use branches

Create a project from scratch

git init

Clone an existing project

git clone protocol://project.address/project-name.git

List all branches you have on our pc

git branch -a

List only "local" branches

git branch

List only local branches and find which remote branches they are tracking

git branch -vv

Create a branch and switch to it

git switch -c branch_name

Note:

  • Naming its branches correctly Even if there are conventions according to communities and programming languages (camelCase, spinal-case, PascalCase etc.) it is proven that the snake_case is the easiest to read. So that's what is often encountered to name branches.

  • Use a prefix A prefix, separated by a /, is often used to give a better idea of ​​the content. Example:

    • feat/do_something_new
    • wip/nothing_to_see_yet
    • fix/that_broken_code

FYI, you should be aware that git imposes some technical rules: https://git-scm.com/docs/git-check-ref-format

Navigate between branches

git switch branch_name

Quickly switch to the last branch you were on

git switch -

Delete a local branch

git branch -D branch_name other_branch

TIP: It is a good practice to list your local branches regularly and delete those which are no longer present on the remote repository.

Rename a branch

git branch -m old_name new_name

Working with yourself (Stage, Unstage, Stash)

Find where you are

git status

condensed version: git status -sb

TIP: Before making a commit, displaying the status is very useful to check that you are not forgeting anything or adding a file by mistake.

Add changes to validate (Stage)

git add OR git stage

Add changes to validate but only files already followed

git add -u

Remove all changes (Unstage)

git restore --staged .

or file by file:

  • git restore --staged file_name other_file

Delete all the changes you made

git restore .

or file by file:

  • git restore file_name other_file

Stash changes

git stash save "comment"

List the stash

git stash list

Reapply changes and remove from stash

git stash pop stash@{0}

NOTE: it is sometimes necessary to "escape" special characters for some terminals or shell, Ex: stash@\{0\}

Reapply changes without removing them from the stash

git stash apply stash@{0}

Remove from stash

git stash drop stash@{0}

Remove everything from the stash

git stash clear

Validate your modifications (Commit)

git commit

Directly Add a short message

git commit -m "doc(git101): Short message"

Modify the last commit to add new changes

git commit --amend --no-edit

Modify the last commit to add changes and/or change the message

git commit --amend

Modify the author of the last commit

git commit --amend --author="Mario Bros <mario.bros@nintendont.co.jp>" --no-edit

Send your changes to the remote (Push)

git push origin

Force sending changes to the remote

git push origin --force-with-lease

In order to understand why: https://blog.developer.atlassian.com/force-with-lease/

Update your code with changes from a remote server (Fetch + Merge / Rebase)

Recover all branches and clean up those that no longer exist on the remote server.

git fetch --all --prune

Update your local master branch

  1. Get changes from the remote: git fetch --all --prune
  2. If necessary, switch to your local master branch: git switch master
  3. Update your local branch with the changes from the remote origin: git merge --ff-only origin/master

NOTE: the --ff-only option is very important.

This is to ensure that the master branch of the server is clean and consistent with your local branch.

Using this option,

If the update does not pass, that means that someone (or yourself) did something they probably shouldn't have done on the master branch...

Update a working branch with changes from the master branch

  1. Get changes from the remote: git fetch --all --prune
  2. If necessary, switch to your working branch: git switch working_branch_name
  3. Update your working branch with changes from the remote origin: git rebase --no-ff origin/master

NOTE: the -- no-ff option is very important.

This is to guarantee that git won't fast forward and it's up to you to resolve any conflicts.

NOTE: Updating your local master branch or a working branch with changes from the remote master branch (the most important source of truth) is therefore symmetrical:

  • On one side: merge --ff-only -> fast forward only
  • On the other side: rebase --no-ff -> without any fast forward

This workflow ensures that all conflicts are properly settled on the working branch BEFORE merging changes into master

(Shared working branch) Update your working branch with changes made by someone else

  1. Get changes from the remote: git fetch --all --prune
  2. If necessary, switch to your working branch: git switch working_branch_name
  3. If necessary, stash any non commited changes: git stash save "before update"
  4. Update your local branch with changes from the remote server: git merge --ff-only origin/working_branch_name

Get only changes from commit (Cherry-pick)

  1. Find the commit hash you want to pick (using git log or other means): git log
  2. If necessary, switch to the branch to modify: git switch branch_name
  3. Get the changes: git cherry-pick COMMIT_HASH

Cherry pick all commits between 2 commits

git cherry-pick FIRST_COMMIT..LAST_COMMIT

Show git history (Log)

git log --online -n 10 # Last 10 commmits

Clean / Modify history

We saw previously that the --amend option allows you to modify or rename the last commit.

Interactive rebase is very useful to clean up your history into comprhensive commit before doing a PR. For each commit, you can:

  • reorder,
  • merge,
  • remove,
  • rename,
  • modify (add changes),
  • split into several commits
  • etc.

git rebase -i FIRST_COMMIT^1

TIP: If you just want to add changes to a past commit without going through an interactive rebase, you can use the --fixup option

History before:

  • 6e9f6fc4f7 feat: Forgot password
  • 82c6f15175 feat: User authentication
  • a86858b228 feat: Adding a user
  • 9192a998a9 feat: Added movie to library

You want to modify the commit 9192a998a9 feat: Adding a movie to the library

git commit --fixup 9192a998a9

History after:

  • eadf86710e fixup! feat: Adding a movie to the library
  • 6e9f6fc4f7 feat: Forgot password
  • 82c6f15175 feat: User authentication
  • a86858b228 feat: Adding a user
  • 9192a998a9 feat: Added movie to library

Then, all you have to do is an interactive rebase using the --autosquash option and save:

git rebase -i --autosquash FIRST_COMMIT^1

This will automatically order fixup commits and flag them accordingly.

Configurer Git

Voir la config système (généralement vide)

git config --list --system

Voir la config globale

git config --list --global

Voir la config locale du projet (il faut être dans le répertoire)

git config --list --local

Tout voir (global et local)

git config --list

Trouver dans quels fichiers se trouve la config de chaque option

git config --list --show-origin

Ouvrir et modifier le fichier de config

git config --edit --global OU git config --edit --local (il faut être dans le répertoire)

On peut alors le modifier comme on veut et le sauvegarder.

On peut aussi définir le programme qui s'ouvre pour interragir avec git. C'est avec l'option core.editor.

Par défaut c'est vi.

On peut choisir n'importe quel éditeur si on donne le nom (ou le chemin complet vers l'executable).

J'utilise nano, mais ça peut être sublime, notepad ou vscode etc. Le mieux est de choisir un programme qui s'ouvre rapidement et facile à manipuler.

Ajouter rapidement une seule option sans ouvrir l'éditeur

git config --global user.name "James Bond" git config --global user.email "james-externe.bond@enedis.fr"

ou localement au projet

git config --local user.name "Mario Bros" git config --local user.email "mario-externe.bros@enedis.fr"

Démarrer un projet et utiliser les branches

Créer un projet from scratch

git init

Récupérer un projet existant

git clone protocol://adresse.du.projet/nom-du-projet.git

Exemple d'alias: cl

git config --global alias.cl clone

Lister toutes les branches qu'on a sur son pc

git branch -a

Exemple d'alias: br git config --global alias.br branch

Lister que les branches "locales"

git br

Lister que les branches locales et voir quelle branches distantes est suivie

git br -vv

Supprimer une branche

git br -D nom_de_branche autre_branche

Basculer rapidement sur la branche où on était précédemment

git co -

TIP: c'est une bonne pratique de lister régulièrement ses branches locales et supprimer celles qui ne sont plus présentes sur le dépot distant.

Renommer une branche

git branch -m ancien_nom nouveau_nom

Naviguer entre les branches

git checkout nom_de_la_branche

Exemple d'alias: co git config --global alias.co checkout

Créer une branche et basculer directement dessus

git co -b nom_de_branche

Note:

  • Bien nommer ses branches Même s'il existe des conventions selon les communautés et les languages de programmation (camelCase, spinal-case, PascalCase etc.) il est prouvé que le snake_case est le plus facile à lire. C'est donc ce qui est souvent rencontré pour nommer les branches.

  • utiliser un prefix Un prefix, séparé par un /, est souvent utiliser pour donner une idée du contenu. Exemple:

    • feat/
    • wip/
    • bugfix/

Pour info, il faut aussi savoir que git impose aussi certaines règles techniques: https://git-scm.com/docs/git-check-ref-format

Travailler avec ses modifications (Stage, Unstage, Stash)

Savoir où j'en suis

git status

version condensée: git status -sb

Exemple d'alias: st

git config --global alias.st "status -sb"

TIP: Avant de faire un commit, afficher le status est très utile pour vérifier qu'on n'oublie rien ou qu'on n'ajoute pas un fichier sans le vouloir.

Ajouter des modifications à valider (Stage)

git add

ou

git stage

Ajouter des modifications à valider mais que des fichiers déjà suivis

git add -u

Enlever toutes les modifications à valider (Unstage)

git reset HEAD --

ou fichier par fichier:

  • git reset HEAD -- fichier autre_fichier

Exemple d'alias: unstage

git config --global alias.unstage "reset HEAD --"

Supprimer toutes les modifications qu'on a fait

git co -- .

ou fichier par fichier:

  • git co -- fichier autre_fichier

Mettre de coté des modifications (Stash) (planquer/mettre de coté)

git stash save "commentaire"

Lister le stash

git stash list

Réappliquer les modifications et enlever du stash

git stash pop stash@{0}

NOTE: il faut parfois "echapper" les caratères spéciaux pour certains terminaux ou shell, ex: stash@\{0\}

Réappliquer les modifications sans les enlever du stash

git stash apply stash@{0}

Supprimer du stash

git stash drop stash@{0}

Tout supprimer du stash

git stash clear

Valider ses modifications (Commit)

git commit

Exemple d'alias: ci

git config --global alias.ci commit

Ajouter directement un message court

git ci -m "git101(commit): Message court"

Message de commit semantic

Comme pour les branches, les messages de commit sont importants. L'idéal, notamment pour les fonctionnalités, est d'essayer d'écrire des messages qui exprime ce que l'application peut faire de plus. En parcourants l'historique on peut alors voir l'évolution du logiciel (se lit de bas en haut).

Exemple :

  • feat: Paiement refusé - Mise ne attente de la commande
  • feat: Paiement de la commande
  • feat: Ajout d'un film au panier
  • feat: Recherche de films par catégorie
  • feat: Mot de passe oublié
  • feat: Authentification d'un utilisateur
  • feat: Ajout d'un utilisateur
  • feat: Ajout d'un film à la bibliothèque

Il faut éviter les commits qui n'apportent pas d'information pertinente, tels que :

  • update init_db.sql
  • Add class
  • [...]

Semantic Commit, comme pour les branches, c'est une bonne pratique répandue qui utilise des préfix :

  • feat: (new feature for the user, not a new feature for build script)
  • fix: (bug fix for the user, not a fix to a build script)
  • docs: (changes to the documentation)
  • style: (formatting, missing semi colons, etc; no production code change)
  • refactor: (refactoring production code, eg. renaming a variable)
  • test: (adding missing tests, refactoring tests; no production code change)
  • chore: (updating grunt tasks etc; no production code change)

On peut ajouter un élément technique entre paranthèse () si on plus de précision

Exemple :

  • fix(ui): Message
  • chore(ws): Message
  • [...]

Modifier le dernier commit pour ajouter des modifications

git commit --amend --no-edit

Modifier le dernier commit pour ajouter des modifications et changer le message

git commit --amend

Modifier l'auteur du dernier commit

git commit --amend --author="Yue Gao yue-externe.gao@enedis.fr" --no-edit

Envoyer ses modifications sur le distant (Push)

git push origin

Forcer l'envoi des modifications sur le distant

git push origin --force-with-lease

Pour comprendre : https://blog.developer.atlassian.com/force-with-lease/

Se mettre à jour avec le serveur distant (Fetch + Merge / Rebase)

Récupérer toutes les branches et nettoyer celles qui n'existent plus sur le serveur distant.

git fetch --all --prune

Exemple d'alias: fap

git config --global alias.fap "fetch --all --prune"

Mettre à jour sa branche locale master

  1. Récupérer les modifications présentes sur le serveur : git fap
  2. Si besoin, basculer sur sa branche master locale : git co master
  3. Mettre à jour sa branche locale avec celle du serveur : git merge --ff-only origin/master

NOTE: l'option --ff-only est très importante.

Elle garantie que la branche master du serveur est "propre" et cohérente avec votre branche locale.

Avec cette option, Quand la mise à jour ne passe pas, Alors cela signifie que quelqu'un a fait quelque chose qu'il n'aurait surement pas dû sur la branche master...

Mettre à jour une branche de travail avec la branche master

  1. Récupérer les modifications présentes sur le serveur : git fap
  2. Si besoin, basculer sur sa branche de travail : git co nom_de_la_branche
  3. Mettre à jour la branche avec celle du serveur : git rebase --no-ff origin/master

NOTE: l'option --no-ff est très importante.

Elle garantie que git ne fera pas d'avance rapide et c'est à vous de régler les conflits s'il y en a.

NOTE: La mise à jour de la branche master et celle d'une branche avec master se fait donc de manière symètrique :

  • Merge --ff-only : uniquement fast forward
  • Rebase --no-ff : sans aucun fast forward

Cela garantie que que tous les conflits soient régler proprement sur la branche de travail AVANT de merger les modifications dans master

(Branche de travail partagée) Mettre à jour sa branche de travail avec les modifications apportées par une autre personne

Ici, on peut procéder de plusieurs façon,

A - Soit, comme pour une mise à jour avec master: pénible mais efficace, pas besoin de nettoyage de l'historique avant merge sur master

B - Soit avec des commits de merge: plus souple et plus facile, mais obligera un nettoyage de l'historique avant merge sur master

Solution A:

  1. Récupérer les modifications présentes sur le serveur : git fap
  2. Si besoin, basculer sur sa branche de travail : git co nom_de_la_branche
  3. Mettre à jour la branche avec celle du serveur : git rebase --no-ff origin/nom_de_la_branche

NOTE: ce mécanisme récupère les modifications du serveur et "réapplique" par dessus nos modifications

Solution B:

  1. Récupérer les modifications présentes sur le serveur : git fap
  2. Si besoin, basculer sur sa branche de travail : git co nom_de_la_branche
  3. Mettre à jour la branche avec celle du serveur : git merge origin/nom_de_la_branche

NOTE: ce mécanisme récupère les modifications du serveur et les applique par dessus nos modifications avec un commit de merge.

/!\ L'historique devient rapidement illisible et les mêmes modifications peuvent apparaitre plusieurs fois.

Récupérer seulement les modifications d'un commit provenant d'une autre branche (cherry-pick)

  1. Trouver le hash du commit que l'on veut récupérer (avec git log ou autre moyen) : git log
  2. Si besoin, basculer sur la branche à modifier: git co ma_branche
  3. Récupérer les modifications : git cherry-pick HASH_DU_COMMIT

Exemple d'alias: cp

git config --global alias.cp cherry-pick

Récupérer tous les commits entre 2 commits

git cp PREMIER_COMMIT..DERNIER_COMMIT

Consultuer l'historique (Log)

git log --online -n 10

Exemple d'alias: l

git config --global alias.l "log --online -n 10"

Exemple d'alias: lg

git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %Cblue<%an>%Creset' --abbrev-commit --date=relative --all"

toutes les branches locales

Global log , Exemple d'alias: glog

git config --global alias.glog "log --graph --oneline --decorate --branches --tags --date-order --full-history"

toutes les branches (locales et origin)

Log All , Exemple d'alias: lga

git config --global alias.lga "log --graph --decorate --date-order --full-history --pretty=format:'%C(yellow)%h%Creset <%C(red)%an%Creset> (%C(green)%ai%Creset)%C(auto)%d%Creset %s' --all"

uniquement la branche courante

Log Branch , Exemple d'alias: lgb

git config --global alias.lgb "log --graph --decorate --date-order --full-history --pretty=format:'%C(yellow)%h%Creset <%C(red)%an%Creset> (%C(green)%ai%Creset)%C(auto)%d%Creset %s'"

Nettoyer / Modifier l'historique

On a vu précédemment que l'option --amend permet de modifier ou renommer le derneir commit.

Le rebase interractif est très utile et on peut faire des choses très avancées. Pour chaque commit, on peut :

  • réordonner,
  • fusionner,
  • supprimer,
  • renommer,
  • modifier (ajouter des modifications),
  • redécouper en plusieurs commits
  • etc.

git rebase -i PREMIER_COMMIT^1

TIP: Si on souhaite simplement ajouter des modifications à un commit dans le passé, sans passer directement par un rebase interractif,

on peut utiliser l'option --fixup

Historique avant :

  • 6e9f6fc4f7 feat: Mot de passe oublié
  • 82c6f15175 feat: Authentification d'un utilisateur
  • a86858b228 feat: Ajout d'un utilisateur
  • 9192a998a9 feat: Ajout d'un film à la bibliothèque

On souhaite modifier le commit 9192a998a9 feat: Ajout d'un film à la bibliothèque

git commit --fixup 9192a998a9

Historique après :

  • eadf86710e fixup! feat: Ajout d'un film à la bibliothèque
  • 6e9f6fc4f7 feat: Mot de passe oublié
  • 82c6f15175 feat: Authentification d'un utilisateur
  • a86858b228 feat: Ajout d'un utilisateur
  • 9192a998a9 feat: Ajout d'un film à la bibliothèque

A la fin, on utilise l'option --autosquash avec le rebase interractif :

git rebase -i --autosquash PREMIER_COMMIT^1

Cela permet d'ordonner et de mettre automatiquement l'option fixup sur les commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment