Aller au contenu

GIT

1.0 Configuration et conseils

Configurer correctement son environnement git !

# Make git show your commits with your id
git config --global --add user.name "Prénom Nom"
git config --global --add user.email "prenom.nom@etu.minesparis.psl.eu"

# Force "pull --rebase" to get a linear commit history
git config --global --add pull.rebase true

# Keep HTTP(S) password for some time
git config credential.helper "cache --timeout=3600"

CONSEILS À SUIVRE POUR DE VRAI

  • toujours faire un git status avant git commit pour vérifier les modifications qui vont être enregistrées avant de polluer son dépôt.
  • éviter git add . ou git add --all qui peut ajouter un peu n'importe quoi… si vous le faites néanmoins parce que vous savez mieux que tout le monde, voir le conseil précédent.
  • ne jamais faire des git add -f (aka --force), car c'est toujours une mauvaise idée, même si git vous indique que cela vous permet de faire ce que vous demandez. En réalité, vous n'avez pas demandé ce que vous croyez…

Utilisation normale de git, avec un dépôt cloné…

# ajouter un fichier pour le prochain commit
git add fichier
# NE PAS FAIRE : git add . ou git add --all
# regarder où on en est
git status    # situation des fichiers édités
# IL NE DOIT Y AVOIR QUE DES FICHIERS QUE VOUS AVEZ ECRITS/ÉDITÉS
git diff      # les modifications locales en cours
git diff main # les modification par rapport à la référence
# VÉRIFIER QUE LES TESTS PASSENT !
#
# SI
# - le status montre les fichiers que vous avez édités
# - le diff main montre bien vos éditions
# - les tests, anciens ET nouveaux, passent
# ALORS
git commit    # enregistrer les modifs AVEC UN MESSAGE CLAIR !
git push      # partager avec les copains/copines
git pull      # récupérer les modifications des autres
              # ATTENTION si conflit, voir la section REBASE ci-dessous

Vous devez faire des git pull et git push régulièrement de manière à détecter au plus tôt les conflits, surtout en début de projet où ceux-ci arrivent plus volontiers car tout le monde travaille sur quelques fichiers.

1.1 Méthode de travail simplifiée avec git

Voici une proposition de méthode de travail simplifiée avec git, sans utilisation de branche, qui peut fonctionner de manière raisonnable avec un petit groupe pour des développements incrémentaux dans une copie de travail clonée.

  1. vous travaillez directement dans la branche main de votre copie de travail.
  2. quand ça marche (faire/refaire des tests !) : git commit ... (si besoin) puis git push
    • si vous êtes la première à fait le push, vous avez gagné !
    • sinon, vous devez faire un git pullgit se lance dans un rebase pour rejouer vos modifs après les modifs récupérées
      • si ça se passe bien, GO TO 2
      • si pas de chance vous avez un conflit, voir la question 1.3. une fois le rebase fini, GO TO 2
  3. vous pouvez passer au ticket suivant : GO TO 1

Remarques :

  • attention de bien tester avant git push, sinon vous envoyez du code pourri à vos camarades, qui ne vous en seront pas reconnaissants.
  • attention de bien retester après git pull, même sans conflit il peut y avoir des bugs ajoutés.
  • le pull exécute un rebase parce que c'est configuré comme ça au 1.0.

Avantages :

  • pas de branche ni de merge explicites : chaque main d'une copie de travail est implicitement une branche, le pull rebase est un merge.
  • les conflits ou incompatibilités sont détectés au plus tôt, et peuvent être traîtés immédiatement.
  • l'historique est linéaire, simple à comprendre et manipuler si besoin.

1.2 Corruption .git objects

Peut-être dû à un arrêt intempestif de la VM similaire à un arrachage de cable sur un ordinateur réel…

Une solution nucléaire :

# afficher l'URL du dépôt upstream (si nécessaire)
git remote -v
# création d'un clone depuis l'upstream, dans le sous-répertoire cccc
git clone {url_du_depot} cccc
# on remplace le `.git` de notre dépôt par le `.git` du nouveau clone
# - renommage du .git en .git.BAD
mv .git .git.BAD
# - importation du .git depuis le clone
mv cccc/.git .
# - ménage (plus besoin du répertoire cccc/)
rm -rf cccc
# - si tout est bon, suppression du `.git` corrompu
rm -rf .git.BAD

Dans l'opération, les commits locaux qui n'étaient pas sur l'upstream sont perdus (mais les fichiers modifiés sont, eux, inchangés par la manip), il faut refaire ces commits.

1.3 Conflit dans un git pull --rebase

Quand on fait un git pull, il se lance dans un rebase pour rejouer les commits locaux après les commits récupérés. S'il n'y a pas de conflits, l'opération est transparente. En cas de conflits, il faut intervenir manuellement :

EN AUCUN CAS NE FAIRE UN "git commit" EN COURS DE REBASE

git status  # 'rebase in progress' + des explications
# LES LIRE. ENCORE. ENCORE. ENCORE.
# éditer les fichiers pour résoudre les conflits, puis
git add fichier-dont-le-conflit-a-été-corrigé
git status  # plus de conflit ?
# après les résolutions
git rebase --continue  # et surtout pas 'git commit'
# un nouveau conflit peut apparaître avec des commits suivant, reprendre la procédure ci-dessus.

Si vous souhaitez abandonner le rebase : git rebase --abort.

RTFM : git help rebase

1.4 Annulation de quelques commits

# identifier le commit à éliminer grâce aux messages très clairs…
git log
# ensuite, avec l'identifiant (moche) du commit
git revert <commit-id>
# cela peut générer des conflits !
# éditer les fichiers pour résoudre les conflits, puis
git add fichier-dont-le-conflit-a-été-corrigé
git status  # plus de conflit?
# après les résolutions
git commit  # avec un message pertinent

RTFM : git help revert

1.5 Restaurer un état (commit) précédent

git restore --source <commit-id> .
# vérifier, tester…
git status  # ok ?
git commit  # avec un message pertinent

RTFM : git help restore

1.6 Oublier définitivement les éditions en cours

git reset --hard

RTFM : git help reset

1.7 Récupérer les éditions d'effacées avec la méthode précédente

Non. Ouvrir le dictionnaire au mot définitif. Peut-être vouliez vous faire un git stash, voir la question suivante.

Note : VS Code et Pycharm conservent un historique des modifications en local, il est éventuellement possible, de façon limitée et avec plus de travail (procéder fichier par fichier) de récupérer des choses.

1.8 Mettre de côté les éditions en cours

git stash
# pour les récupérer
git stash pop

RTFM : git help stash

1.9 Impossible de clone/pull/push

Solution 1 : ne pas se connecter au WIFI MOVIE. Utiliser eduroam ou MobApp-PI qui ne filtrent pas les connexions SSH.

Solution 2 : vérifier que votre ordinateur est bien connecté. (VM only) si le message que vous obtenez est fatal: unable to access 'https://gitlab.../projet.git': Could not resolve host: gitlab... tentez de déconnecter puis de reconnecter la VM au réseau (Menu en haut : Périphériques - Réseau - Connecter la carte réseau, ou clic droit sur le raccourci tout en bas)

1.10 Rétablir un fichier dans un état antérieur

# trouver le commit qui vous intéresse
git log  # par exemple : deadbeef...
# extraire le fichier à ce commit particulier
git checkout deadbeef main.react.js
# vérifier que ça fonctionne… puis valider
git commit -a

1.11 Enregistrer un répertoire vide sous git

On peut souhaiter qu'un git clone crée certains répertoires vides automatiquement, typiquement des répertoires destinés à recevoir des fichiers utilisateur (images, ...) ou des données temporaires (sessions, ...).

Pour ce faire, il faut placer un fichier vide dans chaque répertoire (généralement nommé .gitkeep par convention) et l'enregistrer dans git. Bien sûr le répertoire n'est plus réellement vide, c'est ça le truc.

La création d'un fichier vide peut se faire, notamment, à l'aide de la commande "touch" :

# On crée le répertoire
mkdir static
# On crée un fichier vide
touch static/.gitkeep
# On le met dans git
git add static/.gitkeep
# puis on propage
git commit; git push

1.12 Dépôt énorme (x00 MiB), ☠ 😠 👿

Vous avez ajouté des fichiers sous git qui ne devraient pas y être. Ils polluent les disques, y compris sur le serveur gitlab. C'est pas bien.

  • Je récupère git-filter-repo qui va réécrire toute l'histoire, de manière coordonnée avec tous les membres du projet (on arrête tous les développements, git push, on efface les branches…).
  • Je parcours la documentation de git-filter-repo… et il faut bien se lancer, voir ci-dessous.
  • Je prends la bonne résolution d'apprendre à utiliser git correctement ! RTFM
# on prend une nouvelle copie de travail
cd
git clone git@gitlab.cri.minesparis.psl.eu:mobapp-2023/projet.git projet-TMP
cd projet-TMP
# on regarde la taille du `.git`
du -sh .git
# on regarde ce qui ne va pas
git-filter-repo --analyze
# on repère les gros répertoires inutiles, style `android/build` and autres `node_modules`
# voir en particulier `directories-all-sizes.txt`
# on lance le grand nettoyage, par exemple :
git-filter-repo --path node_modules/ --invert-paths
# puis on regarde la nouvelle taille
du -sh .git
# on vérifie que TOUT MARCHE BIEN, vive les tests !
# on refait un *analyze* pour vérifier que ça va mieux…
# si pour une raison quelconque, le dépôt a perdu son *remote*, le remettre :
git remote add origin git@gitlab.cri.minesparis.psl.eu:mobapp-2023/projet.git
# on pousse enfin la nouvelle version vers le gitlab
git push --force origin main # ATTENTION CELA ÉCRASE TOUT
# tout le monde refait maintenant un clone
cd
mv projet projet-OLD
git clone git@gitlab.cri.minesparis.psl.eu:mobapp-2023/projet.git projet
# on peut aussi effacer projet-OLD et projet-TMP, en faisant bien attention
rm -rf projet-OLD projet-TMP

Note : écraser le dépôt sur le gitlab est normallement interdit par la configuration par défaut. Cette protection souhaitable doit être levée afin de permettre le nettoyage.