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
avantgit commit
pour vérifier les modifications qui vont être enregistrées avant de polluer son dépôt. - éviter
git add .
ougit 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 sigit
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.
- vous travaillez directement dans la branche
main
de votre copie de travail à jour.- donc faire
git pull
et tester avant de commencer vos développements…
- donc faire
- développez et vérifiez que ça marche
- faire, refaire des tests !
- quand ça marche :
git commit ...
(si besoin) puisgit push
- si vous êtes la première à le faire, vous avez gagné !
- sinon, vous devez faire un
git pull
… git se lance dans un rebase pour rejouer vos modifs après les modifs récupérées- si pas de chance vous avez un conflit,
voir la question 1.3.
sinon il n'y avait pas de conflit, cool ! - une fois le rebase fini, GO TO 2
- si pas de chance vous avez un conflit,
voir la question 1.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
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
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.