5 min read

Git et contrôle de version

Git and version control

Apprendre Git

Git simulation

Principles essentielles

Visualier la mindmap

Utilisation de base

Config

git config --global user.name "Rong Zhou"
git config --global user.email "ron@ronzz.org"
git config user.<valeur>
git config credential.helper 'cache --timeout 36000' # --global

Rendre .git fichiers visible en VSCode:
CTRL+, > >Exclude > x**/.git

Visioner l'histoire de révision

git log --graph --oneline --decorate {branch-name : default HEAD }# --all --color

Pour une branche remote :

git fetch origin
# Voir les commits d'une branche distante origin/feature-x
git log --graph --oneline --decorate --color origin/feature-x

commit, branches, et rebase

git commit
git branch {branch_name}
git switch {branch_name/commit_name/relative_commit_reference} # e.g., {main/fec0/main^^|main~2 # La branche sera crée si elle n'existe pas encore  --orphan : sans historique

git merge {branch_name} # Integrates changes from another branch into your current branch. The commit graph preserves the fact that two lines of development existed.
git branch -d {branch_name} # supprime une branche locale déjà fusionnée
git push origin --delete init # supprime davantage ref distante
git rebase {target_parent_branch_name} # -i pour interactive # Re‑applies commits from your current branch on top of another branch for a linear history.

rollback

git branch -f {branch/HEAD to be deplaced} {destination-branch/HEAD} # changer seulement le postionnement des branches et HEAD sans bouger les commits
git reset HEAD~1 # annule dernier commit (LOCAL seulement)
git revert HEAD # faire un nouveau commit qui en effet annule le dernier commit
# remarquez qu'en `reset` on specifie l'état cible où en `revert` on specifie le commit à annuler 

Dupliquer un fichier/dossier d'une branche à une autre

git restore --source main resources/

Cherry Pick

git cherry-pick {commit_name}
git commit --amend

Tag

git tag {tag_name} {target_commit : default HEAD}
git describe {commit}

Stash

git stash push -m "Message descriptif" # -k Stasher uniquement les fichiers suivis -u include-untracked
git stash list
git stash show -p stash@{0}
git stash pop stash@{0}
git stash apply stash@{0} # Garde le stash après l'application. Utile pour l'appliquer sur différentes branches
git stash drop stash@{0} # Supprimer un stash spécifique
git stash clear # Supprimer tous (DANGER !)

Collaboration en ligne

Init : clone

git clone <URL>
git clone --single-branch --branch <nom-de-la-branche> <url>

.gitignore : à placer à la racine du dépôt Git

passwords.txt
*.txt
rm -rf .git
git init
git status # -s: montrer moin des détails
git add . # tout les modifications dois sont validé par `add` avant `commit`.*
git add <filename>*
git diff # --staged
git commit -m "message" -a # -a = add .
  • . inclut tous les fichiers dans les SOUS-DOSSIERs de répertoire actuel du terminal. Exécutez git add . à la racine du répertoire de dépôt pour valider des changements sur tous les fichiers.

Annuler les modifications :

git rm --cached  {files*} # Cesser de traquer des fichiers
git reset --soft HEAD~1 # roll-back dernier commit. --soft: ne changera pas les fichiers dans votre répertoire de travail, et les commits annulés sont conservé dans l'index comme 'staged', prêt pour refaire.

Repo à distance

git remote add origin <URL>
git branch -M main
git pull origin main # = fetch + merge. --rebase  = fetch + rebase
git push -u origin main --force-with-lease # force-with-lease prévien l'écrasement accidentel des changements effectuer par les autres développeurs depuis votre dernier `pull`
git push --set-upstream origin bugfix1 # pousser nouvelle branche

Annuler les modifications

git revert HEAD~1
git restore --source=origin/main --worktree file.txt # restaure file.txt depuis origin/main dans le répertoire de travail 

Revenir à l'état de distant (écraser des changements locals)

git fetch origin
git reset --hard origin/main

Pour restaurer uniquement certains fichiers à partir de la branche distante :

git restore --source=origin/main --staged --worktree chemin/vers/fichier1 chemin/vers/fichier2

Submodules et Subtrees

  • Ajouter dépendance externe et la maintenir : submodule.
  • Intégrer code externe pour simplifier le workflow des contributeurs : subtree.

Submodules

Un submodule lie le dépôt parent à un autre dépôt Git distinct. Le dépôt parent conserve une référence à un commit précis du sous‑dépôt, pas son historique complet, utile pour dépendances versionnées et pour garder l’historique séparé.

Ajouter un submodule

git submodule add https://github.com/orga/projet-externe.git path/to/submodule
git commit -m "Add submodule projet-externe"

Cloner un dépôt avec submodules

git clone --recurse-submodules <url>
# ou après clone
git submodule update --init --recursive

Mettre à jour un submodule

# aller dans le submodule, récupérer et checkout la version voulue
cd path/to/submodule
git fetch
git checkout main
git pull

# revenir au parent et enregistrer la nouvelle référence
cd ../..
git add path/to/submodule
git commit -m "Update submodule {projet-externe} to latest main"

Supprimer un submodule proprement

git submodule deinit -f path/to/submodule
git rm -f path/to/submodule
rm -rf .git/modules/path/to/submodule
git commit -m "Remove submodule"

Mise à jour automatisés

Suivre une branche automatiquement

git submodule add -b main https://github.com/orga/projet-externe.git path/to/submodule
  • Remarque: même en suivant une branche, le parent enregistre un commit précis ; il faut toujours git add + git commit dans le parent après mise à jour du submodule.

Mettre à jour directement depuis le parent

git submodule update --remote --merge

Avantages

  • Historique séparé, dépendance versionnée, contrôle précis du commit utilisé.

Inconvénients

  • Workflow plus complexe pour les contributeurs (init/update), gestion manuelle des mises à jour, pièges lors des merges et des clones sans --recurse-submodules.

Subtrees

Concept
Un subtree intègre le contenu d’un dépôt externe directement dans un sous‑répertoire du dépôt parent tout en conservant la possibilité d’importer/exporter des changements entre les deux dépôts. Pas de .gitmodules, pas de dépôt séparé dans le dossier.

Ajouter un subtree

git remote add {projet-externe} https://github.com/orga/projet-externe.git
git fetch {projet-externe}
git subtree add --prefix=path/to/subtree {projet-externe} main --squash
  • --prefix : dossier où placer le code.
  • --squash : regroupe l’historique importé en un seul commit (optionnel).

Mettre à jour depuis le remote

git subtree pull --prefix=path/to/subtree {projet-externe} main --squash

Pousser des changements vers le remote

git subtree push --prefix=path/to/subtree {projet-externe} main

Extraire un subtree en tant que nouveau dépôt

git subtree split --prefix=path/to/subtree -b {split-branch}
# puis push split-branch vers un remote
git push origin {split-branch}:refs/heads/main

Avantages

  • Simplicité pour les contributeurs (pas d’init/update), tout est dans un seul dépôt, facile à cloner.
  • Pas de dossiers .git imbriqués.

Inconvénients

  • Historique externe peut être aplati si --squash utilisé ; synchronisation bidirectionnelle moins naturelle que submodule pour workflows complexes.
  • Opérations subtree peuvent être plus lourdes pour de très gros historiques.

Quand utiliser quoi

  • Submodule si vous voulez garder l’historique séparé, pinner une dépendance à un commit précis, ou si le sous‑projet est développé indépendamment (librairie, composant réutilisable).
  • Subtree si vous préférez simplicité pour les contributeurs, intégrer le code directement dans le dépôt parent et éviter la gestion explicite des submodules.

Bonnes pratiques

  • Documenter dans le README comment cloner et mettre à jour (--recurse-submodules ou git submodule update --init --recursive).
  • Pour submodules, committer la mise à jour du pointeur dans le dépôt parent après avoir changé de commit dans le submodule.
  • Pour subtrees, tester pull/push sur une branche dédiée avant de fusionner.
  • Éviter de mélanger submodule et subtree pour le même sous‑répertoire.
  • Automatiser les mises à jour via CI si vous dépendez de versions externes (PR automatique, tests).

Opérations courant

Problèmes connu

Dossier nommé comme fichiers ❌

reveal.js/reveal.js

git l'interpreter la premier reveal.js comme fichier Javascript et ignorer la actuel javascript.

Inclusion des .git dossier (potentiellement invisible*) en sou-dossiers ❌

*: nombreuses OS n'afficher pas les dossier /\..*/ par défaut

plutôt:

# suivres les changes de ce sous-dossier .git 
git submodule add <url_du_dépôt*> assets/js/reveal-js/ # Dépôt distant, comme Github, ou locale, en un autre dossier

ou:

# ne suivres pas les changes
rm -rf assets/js/reveal-js/.git

pdfs, tomls ignoré par defaut ❌

find . -name "*.toml" -o -name "*.pdf" -exec git add -f {} +

Please enter a commit message ❌

# Merge branch 'repair2' of https://gitlab.com/ronzz-public/CDN into repair2 
# Please enter a commit message to explain why this merge is necessary, 
# especially if it merges an updated upstream into a topic branch. 
# Lines starting with '#' will be ignored, and an empty message aborts # the commit. 
~

Naviguez avec les flèches sur votre clavier jusqu'à la fin des lignes de commentaires précédées par #, puis taper o pour insérer une nouvelle ligne. Entrez un message, puis tape esc et :wq pour enregistrer et fermer.

Github

gh auth login
gh auth status

# Create a repository interactively
gh repo create
Purpose Permissions
git commit metadata, contents (read&write)
git admin issues, pull requests
repo admin administration, actions, workflows

Gitlab

L'utilisation de Gitlab VScode extension est conseillé.

Diagnostiques

git fsck --full