Mémo git

Configuration de l’outil

git --version voir sa version de git

git voir toutes les commandes possibles

git config voir ce qui est possible au niveau des configurations

  • git config --local configuration par projet, par dépôt
  • git config --global configuration pour tous les projets qui seront créés sur sa machine
  • git config --global user.name "[nom]" configure son nom, retaper la commande avec une autre valeur modifiera le nom
  • git config --global user.name affiche le nom
  • git config --global user.email "[adresse email]" configure l’adresse mail
  • git config --global core.autocrlf true (pour Windows, pour Mac ce sera git config --global core.autocrlf input) configure git pour qu’il gère correctement les fins de ligne. Paramètre recommandé si on collabore sur des Repository avec des personnes ayant des systèmes d’exploitation différents
  • git config --list voir ce qui a été configuré

Créer des dépôts

git init initialiser git dans un projet existant sur son pc local

git init [nom-du-projet] Démarrer un nouveau dépôt

git clone /path/to/repository Créer une copie locale d’un repository local

git clone username@host:/path/to/repository Créer une copie locale d’un repository présent sur un serveur distant

git clone https://github.com/xxxxx.git Cloner un dépôt Github sur son PC local

git clone https://github.com/xxxxx.git superapp Cloner un dépôt Github sur son PC local en le renommant

Si on ne veut plus que notre dossier soit un dépôt git, il suffit de supprimer le fichier .git présent à la racine du dossier.

Ajouter un remote distant pour son projet local

On a un projet développé en local. On veut en avoir une copie sur un service distant comme Gihub, GitLab, Bitbucket … ou sur un serveur perso.
On crée le dossier distant sur le service, on ne met rien dedans, pas de readme, rien.
Ensuite on ajoute cette adresse distante sur son dépôt local (par exemple ci dessous un dépôt Github)
Si https : git remote add origin https://github.com/user/repo.git
Si cle ssh : git remote add orgin git://github.com/user/repo.git
Puis on envoie le contenu de son dépôt local sur le repo distant
git push –u origin master

Supprimer un remote distant de son dépôt local

On liste ses remote distants : git remote -v
Par défaut on aura « origin » mais on peut en avoir d’autres qu’on aura nommé à sa convenance, par exemple « infomaniak » si on à créé un hub sur son serveur d’hébergement
Si on souhaite supprimer ce dépôt « infomaniak », on fera alors :
git remote rm infomaniak
On vérifie qu’on ne l’a plus :
git remote -v
Supprimer aussi le dépôt sur le serveur distant si ce remote distant ne sert plus à rien. On utilisera alors une commande de suppression récursive sur le dossier rm -rf chemin/du/dossier (!!! Attention avec ce type de commande !!!)

Exclure du suivi de version

Créer à la racine du projet versionné un fichier .gitignore

Inscrire dans ce fichier les dossiers ou fichiers qui ne doivent pas être trackés par Git. On peut demander d’ignorer :

  • un dossier complet : mondosssier/
  • un fichier précis: monfichiersensible.txt
  • Tous les fichiers se finissant par une extension particulière, par exemple : *.html ignorera tous les fichiers en html
*.log
build/
temp-*

Utile : Un générateur de .gitignore https://www.gitignore.io/

git ls-files --others --ignored --exclude-standard Liste tous les fichiers exclus du suivi de version dans le projet

Déplacer et supprimer des fichiers sous suivi de version

rm [fichier] Supprime le fichier du répertoire de travail et de l’index

git rm -r [répertoire] Supprime du répertoire de travail et de l’index tout un répertoire et les fichiers qu’il contient de manière récursive.

git rm --cached [fichier] Supprime le fichier de l’index mais le préserve localement

git mv [fichier-nom] [fichier-nouveau-nom] Renomme le fichier et prépare le changement pour un commit. Combine 3 opérations : mv sur un fichier puis git add et git rm

Mettre en suspens des modifications non finies pour y revenir plus tard

Si on travaille dans une branche, qu’on y fait des modifications mais qu’on ne valide pas par un commit, si on switche vers la branche master, on va transporter nos modifications vers la branche master … Dommage ce n’est pas ce qu’on veut !!! Le risque de poser des problèmes est quasi sûr !
Il ne faut jamais quitter une branche sans mettre en zone de staging tous ses fichiers et faire un commit ! MAIS si on ne veut pas faire cette opération. Si on ne veut pas faire de commit forcé ? Alors que faire ?

git stash Dans la branche sur laquelle on travaille, avant de switcher vers master, on va utiliser cette commande qui est un système de remisage . Cela permet de stocker temporairement les modifications effectuées dans la branche. On pourra les réhabiliter plus tard.

git stash save "j’ai dû aller modifier xxx dans master" Nommer son remisage pour mieux le repérer si on compte en faire plusieurs

git stash apply Réhabiliter ses fichiers remisés

git stash list Voir tous ses remisages. S’il y en a plusieurs, ils seront listés en commençant par stash@{0} puis stash@{1}

git stash apply stash@{0} Réhabiliter le stash visé

git stash drop Supprimer la dernière remise effectuée

git stash pop Permet de combiner les commandes git stash apply et git stash drop

Supprimer une branche que l’on veut abandonner

Si on débuté quelquechose sur une branche (essai1) et qu’on souhaite abandonner la branche, parce que pas concluante. Il ne faut pas la quitter pour master sans avoir fait un commit. On peut écrire par exemple git commit –m "abandon"

Ensuite on peut switcher sur master git checkout master

Comme on ne peut pas supprimer une branche qui n’aurait pas été fusionnée avec une autre on doit forcer la suppression en utilisation l’option -D (majuscule) au lieu du -d (minuscule)
git branch –D essai1

Consulter les changements et effectuer une opération de commit

git status voir l’état des fichiers

git diff Montre les modifications de fichier qui ne sont pas encore indexées (pas encore mises en zone de staging)

git diff --staged Montre les différences de fichier entre la version indexée et la dernière version.

git diff filename quand dans un git status on a un fichier en zone de staging, mais qu’il a subit des modifications il sera aussi signalé dans not staged comme modifié. A ce stade faire un git diff du fichier permet de voir les changements apporté depuis sa dernière capture, la dernière « photo » qui a été faite du fichier et mis en zone de staging

git diff sourcebranch targetbranch Aperçu des modifications, avant la fusion de 2 branches

git diff idcommit1 idcommit2 Voir la différence qui existe entre 2 commits de son choix

git diff idcommit Voir la différence qui existe entre le commit actuel celui sur le quel on se trouve et celui visé

git add . ou git add -A ou git add --all ajouter tous les fichiers pour les tracker (les ajouter en zone de staging)

git add filename tracker un fichier précisément

git commit -m "Message descriptif du commit" Enregistre des instantanés de fichiers dans l’historique des versions. Cela revient à faire un point de restauration. Ajouter –m permet d’ajouter le message directement (sans –m on ouvre un éditeur nano ou vi, ou vim)

Consulter l’historique du projet

git log voir tous les commits avec toutes les informations les concernant

git log --oneline voir tous les commits mais seulement la première ligne descriptive, moins verbeux.

git log --graph voir ses commits de manière graphique, voir les changements de branches, les fusions etc … verbeux mais on peut du coup le combiner avec la commande précédente git log --oneline --graph

git log --graph --oneline --all

git log --follow unfichier Montre l’historique des versions d’un fichier spécifié, y compris les actions de renommage

git log -p [mon_fichier] Historique d’un fichier avec visualisation des différences dans le contenu du fichier entre chaque commits.

git show identifiantducommitchiffrelettre Affiche les modifications intervenues dans le commit spécifié par rapport au commit précédent

Se promener dans l’historique du projet

git checkout identifiantduncommit permet de visualiser le projet dans l’état où il était lors du commit visé. En fait, on a détaché le HEAD sur le commit visé. On peut regarder le projet sous toutes ses coutures.

On peut faire des expérimentations, les commiter. On peut aussi supprimer tous les commits que l’on vient de faire sans avoir d’impact sur les branches en effectuant un autre checkout.
Si vous voulez créer une nouvelle branche pour conserver les commits que vous créez à ce niveau, vous pouvez le faire en utilisant -b avec la commande checkout : git checkout –b
Cette nouvelle branche aura sa base attachée à ce commit.

Par contre attention pas de git reset HEAD à ce niveau !!! Sinon vous perdrez tout ce qui a été fait après ce commit !!!

Pour revenir à l’état d’avancement normal (le dernier commit) du projet : git checkout master

En résumé : Si on switche sur une branche avec checkout le HEAD est placé sur le dernier commit effectué dans la branche. Si on switche sur un commit avec checkout le HEAD est détaché sur ce commit particulier.

Revenir en arrière ou modifier des choses

Détruire un repository git : il suffit de supprimer le dossier .git présent à la racine du repo. C’est un dossier caché, il faut autoriser l’affichage des dossiers et fichiers cachés pour le visualiser dans votre explorateur de fichiers.

Sur dépôt local non pushé uniquement

Les commandes suivantes ne se font que si l’on n’a pas encore poussé (push) son repo sur un dépôt distant comme Github ou Bitbucket parce qu’elles altèrent l’historique des commits. Donc ici, on ne les utilise que si on n’a pas encore publié ses commits, on est juste dans son repo local.

git reset --hard identifiantducommitchiffrelettre revenir à l’état du commit cité et annule toutes les modifications qui ont eu lieu après.

git reset --soft identifiantducommitchiffrelettre revenir à l’état du commit cité mais n’annule pas toutes les modifications qui ont eu lieu après.

git reset --soft HEAD^ annuler un commit qu’on vient de faire, un simple retour en arrière en gardant les modifications suffit

git resert --hard HEAD~3 annuler les 3 derniers commits

git commit --amend permet de rajouter un fichier en staging au précédent commit. Ouvre l’éditeur pour modifier le message du commit si nécessaire. Si on n’a pas de fichiers en zone de staging, permet juste de changer le message du commit. Faire :wq pour sauvegarder le changement de message.

git commit –amend –m "Nouveau message" permet de rajouter le nouveau message directement

git commit --amend --no-edit même chose mais sans modifier le message du commit

git rebase --interactive identifiantducommitchiffrelettre  faire des changements plus profonds dans le commit, affiche une interface permettant de modifier un ancien commit, puis remet en place les commits suivants une fois la modification effectuée

git reset [fichier] Enlève le fichier de l’index (de la zone de staging), mais conserve son contenu

git checkout -f permet de récupérer des fichiers que l’on viendrait de supprimer par erreur

git checkout -- [filename] Si on se trompe, on peut remplacer les changements dans son arborescence de travail par le dernier contenu dans HEAD (la tête). Les modifications déjà ajoutées à l’index, ainsi que les nouveaux fichiers, seront conservés. En fait permet d’annuler une modification faite sur un fichier non indexé quand on est dans une branche autre que master.

git branch -D [nom_de_la_branche] Supprimer une branche même si celle-ci n’a pas été fusionnée avec master. En fait on supprime tout le boulot fait dedans parce qu’on n’a pas abouti à quelquechose de satisfaisant.

git push origin --delete [nom_de_la_branche] Supprimer une branche distante

git mv index.html mapage.html Modifier le nom d’un fichier en le faisant savoir à Git. Si index.html était tracké, si on avait modifié son nom en faisant juste mv index.html mapage.html alors Git pensera que index.html n’existe plus, qu’il a été supprimé et qu’on en a créé un autre mapage.html qui lui sera non tracké et qu’il faudra ajouter.

Si les commits ont été publiés

Il est possible de créer un patch qui correspondra aux modifications à effectuer pour revenir en arrière, puis enregistrer les modifications avec un nouveau commit.

La commande revert sert à défaire ce qui avait été fait au moment du commit en créant un nouveau commit. Cela n’altère pas l’historique mais va ajouter un nouveau commit d’inversion (les lignes ajoutées seront supprimées, les fichiers supprimés seront recréés…).

git revert identifiantducommitchiffrelettre créer le patch qui applique la révision demandée au répertoire de travail.

git revert HEAD~4..HEAD utiliser la commande en donnant un nombre d’enregistrements que l’on souhaite annuler (4 dans cet exemple)

Ensuite : git commit –m "Mon message expliquant le patch"

Synchroniser des changements

git fetch origin master Récupère l’historique du dépôt nommé, c’est-à-dire l’historique sur le serveur qui n’existe pas encore dans votre version en local. Ces données seront stockées dans le répertoire de travail local mais ne seront pas fusionnées avec votre branche locale. Si vous souhaitez fusionner ces données pour que votre branche soit à jour, vous devez utiliser ensuite la commande git merge. Permet, si on a fait une erreur qu’on n’arrive pas à résoudre, de comparer son local avec son distant et si besoin de fusionner.

git merge [nom-de-depot]/[branche] Fusionne la branche du dépôt dans la branche locale courante

git pull Equivaut à un git fetch suivi d’un git merge

git pull --rebase [remote] Si votre dépôt local est en avance git fera alors un 3-way merge. Si vous souhaitez éviter ça vous pouvez demander à git de faire un rebase automatiquement lors du pull.

Travailler sur de nouvelles fonctionnalités, utiliser les branches

git branch affiche toutes les branches présentes dans le dépôt courant

git branch -a affiche toutes les branches d’un projet même celles sur les remotes distants

git branch -v Voir les branches mais aussi le dernier commit qu’il y a eu au niveau de chaque branches

git branch [branch_name] créer une nouvelle branche dont on choisit le nom. Son point de départ sera le commit à partir duquel elle a été créée. La branche récupèrera comme base de travail le commit de démarrage ainsi que tous les commits précédents. Si la branche est créée à partir de master, elle récupère le projet dans son entier.

git branch -m newnamefeature renomme la branche courante en newnamefeature

git branch -b newfeature créer une nouvelle branche nommée newfeature et en même temps s’y rendre

git checkout newfeature passer sur la branche newfeature

git branch -D newfeature Supprimer une branche même si celle-ci n’a pas été fusionnée avec master, en fait on supprime tout le boulot fait dedans parce qu’on n’a pas abouti à quelquechose de satisfaisant.

Fusionner des branches

Pour fusionner les branches il faut se positionner sur celle qui va récupérer le contenu de l’autre branche, en général la branche de développement (quand on utilise un système comme git flow) ou la branche master.

git merge newfeature Fusionne la branche désignée avec la branche courante. En se plaçant sur la branche master faire cette commande va fusionner la branche newfeature avec la branche principale. Cette fusion ne supprime en rien la branche newfeature qui existe toujours. La seule chose qu’on a fait ici c’est de rapatrier les commits de la branche newfeature dans la branche master.

git merge --no-ff newfeature Idem que précédemment sauf que là on n’autorise pas le fast forward. C’est à dire que les commits de la branche qu’on importe ne vont pas juste se placer à la suite de ceux de master, il va y avoir un commit suplémentaire indiquant qu’on a rapatrié une branche et son nom figurera dans le commit.

Une autre façon de fusionner 2 branches est d’utiliser Rebase.

Etape 1 : git rebase master déplacer le branche courante en changeant son commit de départ.

Explication : Rebase prend l’ensemble les commits de la branche courante, les recrée avec de nouveaux identifiants à partir de la nouvelle base qu’on lui a indiquée (ici le HEAD de master = le dernier commit de master). Git réécrit donc l’historique de la branche, les anciens commits sont alors supprimés.
Dans le cas d’un rebase sur master, la branche se positionne alors à nouveau comme une déviation directe de master.

Etape 2 : On peut ensuite switcher sur la branche master git checkout master

Etape 3 : il faut alors mettre à jour master, c’est-à-dire déplacer le HEAD de la branche master pour le placer sur le dernier commit de la branche qu’on souhaite rapatrier. Si cette branche à rapatrier se nomme newfeature on fera git rebase newfeature

Cette manière de procéder permet d’obtenir une séquence linéaire de commits en faisant un merge en fast forward.

git branch -d newfeature Supprimer une branche une fois qu’elle a été fusionnée avec master.

Gérer les conflits de fusion

Si, au niveau d’une branche Y, on a effectué des modifications sur un fichier sur certaines lignes et que dans une branche Z, les mêmes lignes du même fichier ont aussi modifiées, on va se retrouver lors d’un merge avec un « conflit ». Git va nous demander laquelle des deux modifications devra être retenue.

NB : Si modif du même fichier dans deux branches différentes mais sur des lignes différentes pas de conflit.

Git affichera dans la console ce genre de chose :

CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result

Il faut alors éditer le fichier concerné par le conflit de fusion,  qui affichera quelquechose de ce genre :

<!Doctype html>
<html>
    <head>
<<<<<<< HEAD
       <title>Welcome Everybody</title>
=======
       <title>Welcome Boys and Girls</title>
>>>>>>> index
    </head>
    <body>
        
    </body>
</html>

Supprimer ce que l’on ne souhaite pas garder.
Ensuite repasser le fichier en zone de staging : dans notre exemple git add index.html
Et refaire un commit git commit -m « Merge de index.html »
Ou pour regrouper les deux commandes précédentes git commit -a, une fenêtre d’édition s’ouvre avec un message de commit déjà renseigné, que l’on peut garder comme tel ou modifier. Valider
Le conflit est résolu.

git mergetool si votre fusion a donné lieu à des conflits, cette commande ouvrira votre mergetool et vous aidera à choisir la version à conserver

Les références relatives

Spécifier un commit par son identifiant n’est pas très pratique, c’est pourquoi Git a des références relatives.
Avec les références relatives vous pouvez commencer par vous placer à un endroit mémorisable (comme la branche bugFix ou HEAD) et travailler depuis cet endroit.

Les commits relatifs sont puissants, on va commencer par en voir deux simples :

  • Revenir d’un commit en arrière avec l’opérateur ^
  • Revenir de plusieurs commits en arrière avec l’opérateur tilde ~[num]

git checkout master^ On positionne HEAD au commit précédent sans avoir besoin de retrouver son identifiant (hash)

git checkout master^^ On positionne HEAD 2 commits en avant

git checkout HEAD^ On peut aussi utiliser HEAD comme référence relative

Si on souhaite remonter davantage de niveaux dans l’arbre des commits l’utilisation du ^ n’est plus approprié, Git met aussi à disposition l’opérateur tilde ~ à la suite duquel on ajoute un nombre qui indique de combien de commits on veut remonter.

git checkout HEAD~5 Revenir de 5 commits en arrière

git diff HEAD HEAD^ Voir la différence avec le commit actuel et le précédent (A supposer que HEAD n’a pas été détaché et est bien positionné sur le dernier commit de la branche sur laquelle on se trouve, HEAD pouvant être déplacé sur le commit de son choix)

Déplacer son travail et le réorganiser

Bientôt …

Travailler avec des dépôts distants

git init --bare Permet d’initialiser un dossier en précisant que ce n’est pas un dossier de travail, que ce dossier ne va contenir que l’historique d’un projet qu’on a en local. On parle aussi de dépôt « nu ».

S’utilise par exemple dans le cas d’un déploiement de site avec Dploy. Le serveur distant qui contiendra le projet n’est qu’une portion du dépôt local, mais contiendra un historique des commits dont va se servir Dploy pour effectuer uniquement les modifications faite depuis le dernier commit

git remote add origin [server_url] Connecter son repository local avec un serveur distant. On utilise communément le mot origin mais on peut aussi nommer son dépôt distant autrement. Par exemple bitbucket ou github ou autre !

Exemple :

git remote add origin https://github.com/nomutilisateurgithub/demo-app.git Après la création d’un dépôt distant sur Github, On nous donne cette commande à éxécuter sur notre projet local pour le lier au dépôt distant. L’adresse est bien évidemment celle du dépôt github créé.

git remote -v Lister les dépôts distants qui ont été configurés

git remote rm origin Supprimer le lien avec le dépôt distant origin

git push -u origin master Envoyer son dépôt local sur le distant. L’option -u n’est à ajouter que lors du premier push, pas les suivants.

git push [remote_name] [branch_name] habituellement origin master mais on peut aussi pousser vers un autre dépôt et une autre branche.

git push --all origin Envoyer toutes les branches sur son dépôt distant

git pull Récupérer et fusionner les changements présents sur le serveur distant dans votre répertoire de travail local

Taguer un commit

git tag 1.0.0 Vous pouvez utiliser les tags pour marquer un ensemble de modifications significatives, tel qu’une version

git push --tags origin Poussez tous les tags vers le référentiel distant

Des commandes utiles en vrac

Supprimer une branche d’un remote distant : git push origin --delete public

Utiliser l’outil Gitk

Lors de son installation, git est fourni avec l’outil gitk. Il s’agit d’une interface graphique conçue pour parcourir et afficher l’historique d’un repository.

gitk [mon_fichier] En précisant un nom de fichier, vous pouvez ainsi visualiser les différents changements ayant eu lieu entre les différents commits dans lesquels il a été modifié.

gitk --follow [mon_fichier] La commande par défaut ne gère pas le changement de nom d’un fichier. Si un fichier a été renommé, on ne voit pas l’historique précédant son changement de nom. Dans ce cas, il est nécessaire d’ajouter l’option –follow pour prendre en compte les changements de nom.

A venir

  • Faire une pull-request
  • Créer des alias pour les commandes
  • Utiliser Git Flow
  • Logiciel pour se simplifier la tâche : Source tree
  • Faire un squash