diff --git a/.gitignore b/.gitignore index c8a7696621ed6ba783b36556b2960a4806c84e9a..b6456b61260020a1a247fd574988db2e0447918b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ git*.pdf /gitrefcard.ilg /gitrefcard.ind *.xdv +/gitmain.fdb_latexmk +/gitmain.fls +/gitbranch.fdb_latexmk +/gitbranch.fls diff --git a/Makefile-gitbranch b/Makefile-gitbranch new file mode 100644 index 0000000000000000000000000000000000000000..9602614d9f5c5aae334a3faf8a206506d0c6f495 --- /dev/null +++ b/Makefile-gitbranch @@ -0,0 +1,19 @@ +TEXENGINE = latexmk -xelatex +COURSENAME = gitbranch +SOURCES_TEX := \ + branchintro.tex\ + branchmerge.tex\ + branchusecase.tex\ + gitpr.tex + +all: $(COURSENAME) + +$(COURSENAME): $(COURSENAME).pdf + +$(COURSENAME).pdf: $(SOURCES_TEX) + $(TEXENGINE) $(COURSENAME).tex + +clean: + /bin/rm -f *~ *.dvi *.log *.aux *.flg *.tmp *.ch *.bbl *.blg *.bat *.lof *.toc *.idx *.ind *.ilg *.out *.snm *.nav *.fls *.fdb_latexmk + + diff --git a/Makefile-gitmain b/Makefile-gitmain new file mode 100644 index 0000000000000000000000000000000000000000..1b95cf7a64408ca2e09bd590af4038ecf14e2ae4 --- /dev/null +++ b/Makefile-gitmain @@ -0,0 +1,25 @@ +TEXENGINE = latexmk -xelatex +COURSENAME = gitmain +SOURCES_TEX := \ + gitmain.tex\ + intro.tex\ + basegit.tex\ + collabowork.tex\ + config.tex\ + ssh.tex\ + maincommands.tex\ + github.tex\ + gitlabul.tex\ + moregit.tex + +all: $(COURSENAME) + +$(COURSENAME): $(COURSENAME).pdf + +$(COURSENAME).pdf: $(SOURCES_TEX) + $(TEXENGINE) $(COURSENAME).tex + +clean: + /bin/rm -f *~ *.dvi *.log *.aux *.flg *.tmp *.ch *.bbl *.blg *.bat *.lof *.toc *.idx *.ind *.ilg *.out *.snm *.nav *.fls *.fdb_latexmk + + diff --git a/basegit.tex b/basegit.tex index 6b4cc7330095a40a0a3eafc672b946c648ddf48b..6ce95892b460bcfe9af4ad726dcdd04cca032913 100644 --- a/basegit.tex +++ b/basegit.tex @@ -11,7 +11,7 @@ \frame{\frametitle{Possibilités} \begin{itemize} \item - Les VCS travaillent principalement sur les fichiers texte + Les VCS travaillent principalement sur les fichiers texte\\ (\ex{.txt}, \ex{.c}, \ex{.java}, \ex{.xml}...) \item Les fichiers binaires (\ex{.jpg}, \ex{.doc}, \ex{.pdf}...) peuvent @@ -25,7 +25,9 @@ d'un projet... \item ...\textbf{à l'exception} de celles qui sont générées - automatiquement (\ex{.o} en C, \ex{.class} en Java...) + automatiquement\\ + (\ex{.o} en C, \ex{.class} en Java...) et des données + \textbf{sensibles} \end{itemize} \end{itemize} } @@ -51,23 +53,25 @@ %====================================================================== -\frame{\frametitle{Principe de fonctionnement d'un dépôt} +\frame{\frametitle{Principe d'utilisation d'un dépôt (\emph{repository})} \begin{itemize} \item - Création d'un dépôt (\emph{repository}) vide + Création d'un dépôt vide ou clonage d'un existant \item Alimentation du dépôt par l'intermédiaire de \emph{commits} \item Un \emph{commit} contient \begin{itemize} \item - un ensemble de modifications de données, suite aux manipulations - des fichiers du projet (création, édition, suppression, - renommage...) + un \textbf{ensemble de modifications de données}, suite aux + manipulations des fichiers du projet (création, suppression, + édition, renommage...) \item - un \emph{log} associé : commentaire sur la nature des modifications + un \textbf{\emph{log} associé} : commentaire sur la nature des + modifications \item - des méta-informations : identifiant de \emph{commit}, auteur, date + des \textbf{méta-informations} : identifiant de \emph{commit}, + auteur, date \end{itemize} \end{itemize} } @@ -76,7 +80,7 @@ \frame{\frametitle{Différents niveaux de stockage} \begin{center} - \includegraphics[height=5cm]{couches-git.eps} + \includegraphics[height=5cm]{couches_git.png} \end{center} } @@ -121,7 +125,7 @@ contient toutes les méta-informations : historique, \emph{logs}, \emph{tags}... \item - propre à un utilisateur donné + \textbf{chaque contributeur possède son propre dépôt local} \end{itemize} \item \emph{Dépôt(s) distant(s)} @@ -217,7 +221,7 @@ \item Il faudrait que $10$ milliards de programmeurs fassent $1$ \emph{commit} par seconde pendant presque $4$ millions d'années - pour qu'il y ait 50\% de chance qu'une collision se produise + pour qu'il y ait $50\%$ de chance qu'une collision se produise \item «~\emph{Il y a plus de chances que tous les membres d'une équipe soient attaqués et tués par des loups dans des incidents sans diff --git a/brancheintro.tex b/brancheintro.tex index 710e7abed0cfd8f4d586a321ea99afc2c07f5660..9572e1d11df6e7bc068e70932321afa4d956535a 100644 --- a/brancheintro.tex +++ b/brancheintro.tex @@ -12,12 +12,12 @@ \begin{itemize} \item La manipulation des branches est certainement une des - fonctionnalités les plus puissantes sous Git + fonctionnalités les plus puissantes sous \ex{git} \item Elle est particulièrement simple et rapide par rapport aux autres VCS, où les branches sont généralement difficiles à gérer \item - Sous Git, la création d'une branche est un processus léger, ce qui + Sous \ex{git}, la création d'une branche est un processus léger, ce qui encourage son utilisation \item Une \emph{branche} représente une partie de l'arborescence @@ -27,7 +27,7 @@ %====================================================================== -\frame{\frametitle{Représentation arborescente} +\frame{\frametitle{Structure interne d'un dépôt} \begin{itemize} \item Chaque \emph{commit} créé possède au moins un père : le @@ -35,7 +35,8 @@ naturellement) \item Il existe ainsi une filiation entre les différents \emph{commits} - d'un dépôt, représentée sous forme d'arbre + d'un dépôt, représentable \emph{majoritairement} sous forme + d'arbre\\(c'est un graphe en fait) \end{itemize} \begin{center} \includegraphics[scale=.4]{arbre.eps} @@ -44,11 +45,12 @@ %====================================================================== -\frame{\frametitle{Branches et branche \ext{master}} +\frame{\frametitle{Branches et branche \ex{master}} \begin{itemize} \item - Rappel : la création d'un dépôt Git entraîne automatiquement la - création d'une branche par défaut, appelée \ex{master} + Rappel : la création d'un dépôt \ex{git} entraîne automatiquement la + création d'une branche par défaut, appelée \ex{master} (ou + \ex{main}) \item Techniquement, une branche est représentée par une variable pointant \textbf{toujours} vers le dernier \emph{commit} réalisé @@ -76,14 +78,14 @@ \item Il est possible de créer de nouvelles branches pour faire évoluer, \textit{simultanément}, le développement dans des directions - différentes pour, entre autres, + différentes pour, entre autres \begin{itemize} \item - un développement collaboratif (= plusieurs développeurs) + un développement collaboratif ($\to$ plusieurs développeurs) \item - la correction de bugs + la correction de bugs (\emph{bugfix branch}) \item - l'ajout de fonctionnalités + l'ajout de fonctionnalités (\emph{feature branch}) \end{itemize} \item Un moyen simple de savoir sur quelle branche on se trouve @@ -91,8 +93,8 @@ \mygit{git branch}{gitbranch1.txt} \end{codebox} \item - Le symbole \ex{*} désigne la branche courante (utile lorsque - plusieurs branches existent) + Le symbole \ex{*} désigne la branche courante\\ + (utile lorsque plusieurs branches existent) \end{itemize} } @@ -108,11 +110,12 @@ \mygit{git branch}{gitbranch2.txt} \end{codebox} \item - Cette commande ne fait que créer une nouvelle branche, elle ne - permet pas de basculer vers cette nouvelle branche + En l'état, cette commande ne fait que créer une nouvelle branche, + elle ne permet pas de basculer vers cette celle-ci \item La nouvelle branche est créée par défaut au niveau du même - \emph{commit} que celui de la branche actuelle + \emph{commit} que celui de la branche actuelle\\ + (techniquement, c'est en fait au niveau de \ex{HEAD}, voir après) \end{itemize} } @@ -132,12 +135,12 @@ %====================================================================== -\frame{\frametitle{Le pointeur \ext{HEAD}} +\frame{\frametitle{Le pointeur \ex{HEAD}} \begin{itemize} \item - Pour savoir où greffer le prochain \emph{commit}, Git utilise un + Pour savoir où greffer le prochain \emph{commit}, \ex{git} utilise un pointeur spécial appelé \ex{HEAD}, pointant vers un \emph{commit} - de référence + particulier \item \ex{HEAD} pointe \emph{généralement} vers (le dernier \emph{commit} de) la branche courante @@ -145,6 +148,13 @@ \begin{center} \includegraphics[scale=.4]{arbrehead.eps} \end{center} + \begin{itemize} + \item + Remarque : \ex{HEAD} peut en fait pointer sur n'importe quel + \emph{commit}\\ + (typiquement dans le cas d'un \ex{checkout} sur un \emph{commit} + quelconque : on parle alors de \emph{tête détachée}) + \end{itemize} } %====================================================================== @@ -153,10 +163,10 @@ \begin{itemize} \item La commande permettant de changer de branche est\\ - \ex{git checkout \emph{branche}}\\ + \ex{git switch \emph{branche}}\\ \begin{minipage}{0.5\linewidth} \begin{codebox} - \mygitplus{git checkout nouveau}\\ + \mygitplus{git switch nouveau}\\ \mygit{git branch}{gitbranch3.txt} \end{codebox} \end{minipage} @@ -183,18 +193,21 @@ \end{center} \begin{itemize} \item - La commande \ex{gitk --all} permet de visualiser l'historique de + La commande \ex{gitk -{}-all} permet de visualiser l'historique de toutes les branches \end{itemize} } %====================================================================== -\frame{\frametitle{Remarques sur \ext{checkout}} +\frame{\frametitle{\ex{git checkout}} \begin{itemize} \item - Techniquement, la commande \ex{git checkout} n'est pas limitée aux - branches : elle accepte n'importe quel \emph{commit} en paramètre + Techniquement, la commande \ex{git checkout} peut également être + utilisée pour passer d'une branche à une autre + \item + Mais \ex{git checkout} n'est pas limitée aux branches : elle + accepte n'importe quel \emph{commit} en paramètre \item Son premier impact est de déplacer le pointeur \ex{HEAD} \item @@ -203,6 +216,10 @@ \item Dans le cas contraire, \ex{HEAD} ne correspond à aucune tête de branche : on parle alors de \emph{tête détachée} + \item + Autre impact : l'espace de travail (\emph{filesystem}) du projet + reflète l'état du projet au \emph{commit} désigné\\ + (c'est une conséquence du déplacement de \ex{HEAD}) \end{itemize} } @@ -212,9 +229,9 @@ \framesubtitle{Aspects techniques} \begin{itemize} \item - Lors du passage d'une branche à une autre, Git restaure le + Lors du passage d'une branche à une autre, \ex{git} restaure le répertoire de travail dans l'état correspondant à la branche - sélectionnée (uniquement pour les fichiers suivis par Git) + sélectionnée (uniquement pour les fichiers suivis par \ex{git}) \item Attention : on ne peut pas changer de branche s'il reste des modifications en attente dans le répertoire de travail ou dans @@ -254,10 +271,10 @@ \begin{itemize} \item Pour créer une branche tout en s'y déplaçant\\ - \ex{git checkout -b \emph{branche}} + \ex{git switch -c \emph{branche}} \begin{codebox} \mygit{git branch}{gitbranch1.txt} - \mygitplus{git checkout -b nouveau}\\ + \mygitplus{git switch -c nouveau}\\ \mygit{git branch}{gitbranch3.txt} \end{codebox} \end{itemize} diff --git a/branchmerge.tex b/branchmerge.tex index c13c5593d9c33a14e4d013d888a6d1442f32ed27..b161dd3bb2185dd04786327e2629aaf7c4dceb52 100644 --- a/branchmerge.tex +++ b/branchmerge.tex @@ -12,7 +12,7 @@ \begin{itemize} \item Une fois le développement relatif à la nouvelle branche - terminé, on peut l'intégrer dans la branche de base + terminé, on peut l'intégrer dans la branche de base (typiquement) \item Dans le même temps, il est possible que le développement ait continué dans la branche de base @@ -37,7 +37,8 @@ concernées \item la commande \ex{git rebase}, permettant de réécrire l'historique - et d'obtenir un résultat similaire, mais différent + et d'obtenir un résultat similaire sur le principe, mais + différent techniquement \end{itemize} \end{itemize} } @@ -73,11 +74,15 @@ %====================================================================== -\frame{\frametitle{Exemple de fusion avec \ext{merge}} +\frame{\frametitle{Exemple de fusion avec \ex{merge}} \framesubtitle{Avant la fusion} - \includegraphics[scale=.37]{beforemerge.eps}\\ + \includegraphics[scale=.37]{beforemerge.eps} + + \medskip + + Pour effectuer la fusion, on saisit les commandes \begin{codebox} - \mygitplus{git checkout master}\\ + \mygitplus{git switch master}\\ \mygitplus{git merge nouveau}\\ % \mygit{git branch}{gitbranch3.txt} \end{codebox} @@ -85,10 +90,10 @@ %====================================================================== -\frame{\frametitle{Exemple de fusion avec \ext{merge}} +\frame{\frametitle{Exemple de fusion avec \ex{merge}} \framesubtitle{Après la fusion} \includegraphics[scale=.37]{aftermerge.eps} - \vspace*{1.5cm} + \vspace*{2.2cm} } %====================================================================== @@ -96,7 +101,7 @@ \frame{\frametitle{Principe de fonctionnement} \begin{itemize} \item - Pour réaliser la fusion, Git repose, en interne, sur la + Pour réaliser la fusion, \ex{git} repose, en interne, sur la disponibilité de plusieurs algorithmes choisis suivant la configuration de départ \item @@ -109,6 +114,10 @@ la création d'un nouveau \emph{commit} (s'il y a eu des modifications sur les 2 branches) \end{itemize} + \item + Point important : les \emph{commits} qui existaient avant la + fusion ne sont donc pas affectés ($\to$ pratique pour les + synchronisations \emph{via} \ex{push}) \end{itemize} } @@ -167,6 +176,9 @@ Au final, la nouvelle branche intègre aussi bien les \emph{commits} qui lui sont spécifiques que ceux ajoutés à la branche de départ + \item + Contrairement à \ex{merge}, il faut cette fois se positionner au + départ sur la nouvelle branche avant de lancer \ex{rebase} \end{itemize} } @@ -175,8 +187,9 @@ \frame{\frametitle{Principe de fonctionnement} \framesubtitle{Exemple : situation de départ} \includegraphics[scale=.37]{beforerebase.eps} + \vspace*{.65cm} \begin{codebox} - \mygitplus{git checkout nouveau}\\ + \mygitplus{git switch nouveau}\\ \mygitplus{git rebase master} \end{codebox} } @@ -186,7 +199,19 @@ \frame{\frametitle{Principe de fonctionnement} \framesubtitle{Exemple : situation d'arrivée} \includegraphics[scale=.37]{afterrebase.eps} - \vspace*{1.5cm} + \begin{itemize} + \item + Remarque : les \emph{commits} de la nouvelle branche étant + réécrits\\ + (= modifications de SHA-1) + \begin{itemize} + \item + \ex{rebase} est plus délicat à gérer que \ex{merge} pour les + synchronisations + \item + mais si la nouvelle branche est purement locale, pas de souci + \end{itemize} + \end{itemize} } %====================================================================== @@ -203,7 +228,7 @@ \item après un \ex{merge}, c'est la branche de départ qui contient l'intégralité des \emph{commits} réalisés (branche de départ + - nouvelle fonctionnalité) + nouvelle branche) \item après un \ex{rebase}, c'est la nouvelle branche qui contient l'intégralité des \emph{commits} réalisés @@ -225,14 +250,14 @@ nouvelle branche sont réécrits, et qu'ils changent donc de SHA-1 en particulier \item - Les anciens \emph{commits} n'existent donc plus, ce qui pose - problème si + Les anciens \emph{commits} n'existent plus, ce qui pose problème + si \begin{itemize} \item d'autres branches sont basées sur ces \emph{commits} \item ces \emph{commits} ont déjà été partagés (\emph{via} un - \ex{push}) vers des dépôt distants + \ex{push}) vers des dépôts distants \end{itemize} \end{itemize} } @@ -252,7 +277,7 @@ une nouvelle branche est définie pour implanter une nouvelle fonctionnalité \item - cette nouvelle branche reste locale à un utilisateur et n'est + et cette nouvelle branche reste locale à un utilisateur et n'est pas partagée tant que la nouvelle fonctionnalité n'est pas finalisée et n'est pas fusionnée avec un \ex{merge} \end{enumerate} @@ -264,13 +289,17 @@ \frame{\frametitle{Conclusion} \begin{itemize} \item - Généralement, les nouvelles branches sont utilisées localement par + Souvent, les nouvelles branches sont utilisées localement par un développeur pour implanter une nouvelle fonctionnalité, - corriger un bug, etc. + corriger un bug, préparer une PR (voir après), etc. + \item + D'ailleurs, le comportement par défaut de \ex{git} est maintenant + de ne synchroniser que la branche récupérée au moment du clonage + (un \ex{push} ne considère donc pas les nouvelles branches + locales) \item - D'ailleurs, le comportement par défaut de Git est maintenant de ne - synchroniser que la branche récupérée au moment du clonage (un - \ex{push} ne considère donc pas les nouvelles branches locales) + Il reste naturellement possible de synchroniser les nouvelles + branches, mais il faut lancer des commandes explicites pour cela \end{itemize} } @@ -285,6 +314,8 @@ \item Dans ce contexte, utiliser la commande \ex{rebase} est donc une bonne pratique + \item + Il faut sinon privilégier les \ex{merge} \end{itemize} } diff --git a/branchusecase.tex b/branchusecase.tex index 1d8e5781e8bed983df85dda5a0996d7e62c43d28..2074a82a18626a20b6b1e22e7afc99206f6ad6af 100644 --- a/branchusecase.tex +++ b/branchusecase.tex @@ -84,12 +84,14 @@ \begin{itemize} \item Les commandes suivantes sont ensuite exécutées\\ - \mygitplus{git checkout -b nouvfonc}\\ + \begin{codebox} + \mygitplus{git switch -c nouvfonc}\\ \mygitplus{git commit -m "Ajout d'une image"}\\ - \mygitplus{git checkout master}\\ + \mygitplus{git switch master}\\ \mygitplus{git commit -m "Changement de titre"}\\ - \mygitplus{git checkout nouvfonc}\\ + \mygitplus{git switch nouvfonc}\\ \mygitplus{git commit -m "Suppression de l'attribut class de l'image"} + \end{codebox} \end{itemize} } @@ -101,13 +103,15 @@ \newcommand{\branchstrategie}[4]{ \frame{\frametitle{#1} - \begin{tabular}{lp{3cm}} + \begin{tabular}{llp{3cm}} \begin{minipage}[b]{.5\linewidth} {\small #2 } \end{minipage} & + \hspace*{5mm} + & \centerline{\includegraphics[scale=.5]{#3}} \end{tabular} #4 @@ -117,15 +121,17 @@ \branchstrategie{Stratégie 1} { - \mygitplus{git checkout master}\\ - \mygitplus{git rebase nouvfonc}\\ - \mygitplus{git branch -d nouvfonc} + \begin{codebox} + \mygitplus{git switch master}\\ + \mygitplus{git rebase nouvfonc}\\ + \mygitplus{git branch -d nouvfonc} + \end{codebox} } {strat1.png} { \begin{itemize} \item - Dans cette stratégie, on utilise pas de \ex{merge} + Dans cette stratégie, on utilise \ex{rebase} sur \ex{master} \item L'historique est linéaire, le \emph{commit} de la branche \ex{master} étant en dernier @@ -139,9 +145,11 @@ \branchstrategie{Stratégie 2} { - \mygitplus{git checkout master}\\ - \mygitplus{git merge nouvfonc}\\ - \mygitplus{git branch -d nouvfonc} + \begin{codebox} + \mygitplus{git switch master}\\ + \mygitplus{git merge nouvfonc}\\ + \mygitplus{git branch -d nouvfonc} + \end{codebox} } {strat2.png} { @@ -159,11 +167,13 @@ \branchstrategie{Stratégie 3} { - \mygitplus{git checkout nouvfonc}\\ - \mygitplus{git rebase master}\\ - \mygitplus{git checkout master}\\ - \mygitplus{git merge nouvfonc}\\ - \mygitplus{git branch -d nouvfonc} + \begin{codebox} + \mygitplus{git switch nouvfonc}\\ + \mygitplus{git rebase master}\\ + \mygitplus{git switch master}\\ + \mygitplus{git merge nouvfonc}\\ + \mygitplus{git branch -d nouvfonc} + \end{codebox} } {strat3.png} { @@ -183,21 +193,25 @@ \branchstrategie{Stratégie 4} { - \mygitplus{git checkout nouvfonc}\\ - \mygitplus{git rebase master}\\ - \mygitplus{git checkout master}\\ - \mygitplus{git merge -{}-no-ff nouvfonc}\\ - \mygitplus{git branch -d nouvfonc} + \begin{codebox} + \mygitplus{git switch nouvfonc}\\ + \mygitplus{git rebase master}\\ + \mygitplus{git switch master}\\ + \mygitplus{git merge -{}-no-ff nouvfonc}\\ + \mygitplus{git branch -d nouvfonc} + \end{codebox} } {strat4.png} { \begin{itemize} + \item + Variation de la stratégie précédente \item Les \emph{commits} de la nouvelle fonctionnalité apparaissent clairement \item Le \ex{merge} est exécuté avec l'option \ex{-{}-no-ff}, obligeant - Git à choisir une stratégie de fusion différente de celle qu'il + \ex{git} à choisir une stratégie de fusion différente de celle qu'il aurait choisi par défaut \item \textbf{C'est l'historique le plus lisible si on souhaite faire @@ -266,9 +280,10 @@ \frame{\frametitle{Synthèse} \begin{itemize} \item - La stratégie 1 n'a pas de sens, on a pas intérêt à intégrer - progressivement une nouvelle fonctionnalité dans la version stable - (la branche \ex{master} dans ce modèle de développement) + La stratégie 1 n'a souvent pas de sens, on a pas intérêt à + intégrer progressivement une nouvelle fonctionnalité dans la + version stable (la branche \ex{master} dans ce modèle de + développement) \item La stratégie 2 reste possible, mais engendre potentiellement plus de conflits à la fusion car il n'y a aucun \ex{rebase} @@ -282,7 +297,7 @@ \framesubtitle{Pour un développement individuel sur une nouvelle fonctionnalité} \begin{itemize} \item - \emph{A priori}, il faut choisir la stratégie 4 (éventuellement la + \emph{A priori}, il faut choisir la stratégie 4 (ou la 3) \item En particulier, lors de l'insertion d'une nouvelle fonctionnalité @@ -361,23 +376,23 @@ %====================================================================== -\subsection{Modèles de développement} +\subsection{\emph{Workflows} de développement} %====================================================================== -\frame{\frametitle{Modèles de développement} +\frame{\frametitle{\emph{Workflows} de développement} \begin{itemize} \item - Le modèle de développement expliqué dans ces transparents est - celui basé sur le fait que la branche \ex{master} contient la + Le \emph{workflow} de développement expliqué dans ces transparents + est celui basé sur le fait que la branche \ex{master} contient la version de production du développement \item - Ce modèle est très proche de celui géré par des sites hébergeant - des projets Git comme Github par exemple + Ce \emph{worflow} est très proche de celui géré par des sites + hébergeant des projets \ex{git} comme Github par exemple \item - D'autres modèles de développement, comme gitflow, font un tout - autre usage de la branche \ex{master} et prévoient au minimum 5 - branches dans tout développement + D'autres \emph{workflows} de développement, comme gitflow, font un + tout autre usage de la branche \ex{master} et prévoient au minimum + 5 branches dans tout développement \item gitflow est utilisé dans beaucoup de développements professionnels : \url{http://nvie.com/posts/a-successful-git-branching-model/} diff --git a/collabowork.tex b/collabowork.tex index dfb894dae85723d30de795162b276c2ff280fa4e..4acc317c46d9d1d83623d90e838edf8faddd910f 100644 --- a/collabowork.tex +++ b/collabowork.tex @@ -11,6 +11,42 @@ % - git push -u origin master +\frame{\frametitle{Préliminaires} + \begin{itemize} + \item + Il faut se raccorder à un dépôt distant + \item + Une possibilité : utiliser une forge (Github, gitlab, + Bitbucket...) + \item + Deux commandes pour le raccordement\\ + (à réaliser par le contributeur principal) + \begin{itemize} + \item + syntaxe de raccordement\\ + \ex{git remote add \emph{nom} \emph{URL}} + \item + exemple de raccordement\\ + \ex{git remote add origin git@github.com:dosch/test.git} + \item + première synchronisation\\ + \ex{git push -u origin master} + \end{itemize} + \item + Les autres collaborateurs + \begin{itemize} + \item + font un \ex{git clone} pour récupérer leur copie locale du dépôt + \item + n'ont rien de particulier à configurer, c'est automatique lors + du clonage : \ex{git pull} et \ex{git push} sont utilisés sans + argument + \end{itemize} + \end{itemize} +} + +%====================================================================== + \frame{\frametitle{Introduction} \begin{itemize} \item diff --git a/config.tex b/config.tex index d6551069b6c852f5c12413b46a5511e1a1482de5..bb00a1e11f2b1dea5b0d65fdc0108479961ff174 100644 --- a/config.tex +++ b/config.tex @@ -5,18 +5,15 @@ %====================================================================== \frame{\frametitle{Fichiers de configuration} -Trois niveaux de configuration - \begin{itemize} - \item - \emph{Au niveau projet}\\ - Fichier \ex{.git/config} à la racine du projet - \item - \emph{Au niveau utilisateur}\\ - Fichier \ex{\textasciitilde/.gitconfig} - \item - \emph{Au niveau système}\\ - Fichier \ex{/etc/gitconfig} (rarement utilisé) - \end{itemize} +\framesubtitle{Deux niveaux principaux de configuration} +\begin{itemize} +\item + \emph{Au niveau projet}\\ + Fichier \ex{.git/config} à la racine du projet +\item + \emph{Au niveau utilisateur}\\ + Fichier \ex{\textasciitilde/.gitconfig} +\end{itemize} } %====================================================================== @@ -40,7 +37,7 @@ Trois niveaux de configuration \item Choix de l'éditeur par défaut\\ \ex{git config -{}-global core.editor "\emph{chemin vers - l'éditeur}"} (exemple de chemin sous Windows pour Atom : + l'éditeur}"} (exemple de chemin sous Windows pour Atom :\\ \ex{C:/Program Files (x86)/atom/atom.exe -{}-wait}) \end{itemize} } @@ -79,9 +76,9 @@ Trois niveaux de configuration Il est possible d'indiquer à Git d'ignorer ces fichiers \begin{itemize} \item - par un fichier \ex{.gitignore}, à placer à la racine du projet : - ce fichier pourra être suivi et partagé avec les autres membres - du projet (\emph{généralement plus intéressant}) + par un fichier \ex{.gitignore}, généralement placé à la racine + du projet : ce fichier pourra être suivi et partagé avec les + autres membres du projet (\emph{généralement plus intéressant}) \item grâce du fichier \ex{.git/info/exclude} : fichier propre au projet, mais qui ne sera pas partagé avec les autres membres du @@ -91,22 +88,32 @@ Trois niveaux de configuration La première solution est naturellement préférable, sauf cas particuliers \item - Il existe également une commande \ex{git ignore} qui permet - de déclarer ces fichiers + Chaque répertoire d'un dépôt peut contenir un \ex{.gitignore} : + chacun agit récursivement (1 seul à la racine suffit généralement) + % \item + % Il existe également une commande \ex{git-ignore} qui permet + % d'alimenter ces fichiers + % Finalement, la commande n'est pas standard (package git-extra + % sous Linux) et difficile à trouver sous Windows \end{itemize} } %====================================================================== \frame{\frametitle{Fichiers à ignorer} + \framesubtitle{Syntaxe des \ex{.gitignore}} \begin{itemize} \item Quel que soit le fichier utilisé, la syntaxe est la même \item - On peut y placer des noms de fichiers (un par ligne) + On peut y placer des noms de fichiers ou des \emph{patterns} de + noms (un par ligne) \item Le caractère \ex{*} est autorisé, permettant de désigner facilement des familles de fichiers (typiquement sur l'extension) + \item + Une ligne commençant par \ex{/} ne s'applique qu'au répertoire + courant : cela coupe court à la récursivité \item Un dépôt Github regroupe des \emph{templates} de \ex{.gitignore} (par langage / framework)\\ diff --git a/couches_git.png b/couches_git.png new file mode 100644 index 0000000000000000000000000000000000000000..291da08d424ba7e12ec9e1cee1d449cfbd01579a Binary files /dev/null and b/couches_git.png differ diff --git a/credentials_cont.txt b/credentials_cont.txt index fb8f55a1d353283fd464511711c0d1add499c2a3..f5444c9426b463e54f0ce92cf9846a2347ceb04f 100644 --- a/credentials_cont.txt +++ b/credentials_cont.txt @@ -1 +1 @@ -https://loginUL:valeur_token@gitlab.univ-lorraine.fr +https://login_UL:valeur_token@gitlab.univ-lorraine.fr diff --git a/gitbranch.tex b/gitbranch.tex index 0624049c134e3899294292ed76cef2727f670196..6022715a65a05452096c536f77a2cd779b3b1914 100644 --- a/gitbranch.tex +++ b/gitbranch.tex @@ -1,8 +1,10 @@ -\documentclass{IutSlideBeamerNew} +\documentclass{IutBeamer} \title[Git, gestion de branches]{Git} \subtitle{Gestion des branches} -\date{4 avril 2014} +\date{Février 2025} +\institute[]{\includegraphics[width=3cm]{UL_LOGO.png}} +\author{Philippe Dosch} \AtBeginSubsection[] { @@ -32,9 +34,10 @@ %====================================================================== -\input{brancheintro} +\input{branchintro} \input{branchmerge} \input{branchusecase} +\input{gitpr} % Idées d'amélioration suite à la première présentation % ===================================================== diff --git a/github.tex b/github.tex index bb5237cb2f6e1408affd0e73df22f2fba8034edb..ef3ff54d0bd86dc37685fa9dd70686d038c865dd 100644 --- a/github.tex +++ b/github.tex @@ -1,6 +1,6 @@ %====================================================================== -\section{Gérer un dépôt Git sur github} +\subsection{Gérer un dépôt Git sur github} %====================================================================== @@ -17,9 +17,9 @@ Au besoin, la créer \begin{itemize} \item - sous Linux : les indications sont fournies par Github + sous Linux\,/\,MacOS : les indications sont fournies par Github \item - sous Windows : utiliser puttygen + sous Windows : installer Git bash au préalable \end{itemize} \end{itemize} } @@ -31,7 +31,7 @@ \item À l'initiative d'une seule personne, le créateur du projet \item - Création d'un dépôt public avec un simple nom + Création d'un dépôt (public ou privé) avec un simple nom \item Suivre les indications fournies par le site ! \item diff --git a/gitlabul.tex b/gitlabul.tex index 245cbf914bd4c17e86ea6c4f9d57d5fa646c9ba9..701b4afde62c81ffd6f4e985d45ee584f0a6853d 100644 --- a/gitlabul.tex +++ b/gitlabul.tex @@ -1,6 +1,33 @@ %====================================================================== -\section{Gérer un dépôt Git sur le Gitlab UL} +\subsection{Gérer un dépôt Git sur le Gitlab UL} + +%====================================================================== + +\frame{\frametitle{Présentation (rapide) de Gitlab} + \begin{itemize} + \item + Gitlab : logiciel libre de \emph{forge} basé sur \ex{git} + \item + Propose des outils : dépôts \ex{git}, mais aussi wiki, gestion + des bugs, documentation, CI/CD... + \item + Utilisé par de nombreux laboratoires et universités, comme par + exemple + \begin{itemize} + \item + Université de Lorraine + \item + CNRS + \item + INRIA + \end{itemize} + \item + Nombre d'utilisateurs estimé à 30 millions, déployé par environ + 100.000 organisations\\ (source : + \url{https://about.gitlab.com/company/}) + \end{itemize} +} %====================================================================== @@ -28,18 +55,18 @@ \frame{\frametitle{Connexion HTTPS : les \emph{credentials}} \begin{itemize} \item - Les \emph{credentials} correspondent au mécanisme permettant de - gérer des identifiants + Les \emph{credentials} correspondent à un mécanisme permettant de + gérer des authentifications, notamment au travers de \emph{tokens} \item - Il est en particulier possible de désigner des fichiers de - \emph{credentials} depuis le fichier de configuration - \ex{\textasciitilde/.gitconfig} (extrait ci-dessous) + Il est possible de désigner des fichiers de \emph{credentials} + depuis le fichier de configuration \ex{\textasciitilde/.gitconfig} + (extrait ci-dessous) \begin{codebox} \mygit{tail \textasciitilde/.gitconfig}{credentials.txt} \end{codebox} \item - Le fichier désigné de credentials contient les informations de - connexion, dont le mot de passe ou, \textbf{mieux}, un + Le fichier désigné de \emph{credentials} contient les informations + de connexion, dont le mot de passe ou, \textbf{mieux}, un \emph{token} \end{itemize} } @@ -86,7 +113,7 @@ \mygit{\ex{cat \textasciitilde/.credentials/credentialsUL}}{credentials_cont.txt} \end{codebox} \item - Lors des prochaines commandes Git concernant ce site, les + Lors des prochaines commandes \ex{git} concernant ce site, les \emph{credentials} seront automatiquement utilisés \end{itemize} } diff --git a/gitpr.tex b/gitpr.tex new file mode 100644 index 0000000000000000000000000000000000000000..e67acd0c8d0ad8fbd458683f89a46e4b0fca979b --- /dev/null +++ b/gitpr.tex @@ -0,0 +1,142 @@ +%====================================================================== + +\section{Un cas pratique : les \emph{pull requests}} + +%====================================================================== + +% \subsection{Caractéristiques} + +%====================================================================== + +\frame{\frametitle{Préambule --- Quelques commandes utiles} + \begin{itemize} + \item + Raccorder un dépôt local à un dépôt distant + \begin{itemize} + \item + syntaxe\\ + \ex{git remote add [NOM REMOTE] [ADDRESSE REMOTE]} + \item + exemple\\ + \ex{git remote add origin git@github.com:phil/test.git} + \end{itemize} + \item + Pousser une nouvelle branche + \begin{itemize} + \item + syntaxe\\ + \ex{git push -u [NOM REMOTE] [NOM BRANCHE]} + \item + exemple\\ + \ex{git push -u origin ma-nouvelle-branche}\\ + (si la branche est déjà connue, un simple \ex{git push} est suffisant) + \end{itemize} + \end{itemize} +} + +%====================================================================== + +\frame{\frametitle{Les \emph{pull requests} (PR)} + \begin{itemize} + \item + \emph{Workflow} popularisé par les forges (Github, gitlab...) + \item + Consiste à envoyer des contributions par l'intermédiaire d'une + nouvelle branche + \item + Côté site web + \begin{itemize} + \item + la branche envoyée est désignée lors de la création d'une + \emph{pull request} (PR) + \item + le mainteneur du dépôt \emph{review} la PR et décide ou pas de + l'intégrer à la branche principale + \end{itemize} + \item + La branche candidate doit contenir le code complet, commenté, + accompagné de tests... + \end{itemize} +} + +%====================================================================== + +\frame{\frametitle{Une bonne PR...} + \begin{itemize} + \item + Doit donner du contexte : quel est le sujet de cette PR ? Pourquoi + ? + \item + Doit adresser un et un seul problème + \item + Doit tourner en local + \item + Doit avoir des tests + \item + Doit avoir des commits qui expliquent la démarche + \item + Ne doit plus avoir de code mort / de debuggage + \item + Ne doit plus avoir de commentaires superflus + \item + Doit être facile à comprendre (nommage, architecture, anglais + partout...) + \item + Ne doit pas avoir de \emph{code smells} + \end{itemize} +} + +%====================================================================== + +\frame{\frametitle{Une bonne \emph{review}} + \begin{itemize} + \item + Doit étudier attentivement la proposition en prenant en compte + tous les points précédents + \item + Doit bien prendre en considération le contexte + \item + Doit récupérer en local, lancer, tester la proposition d'ajout de + code + \item + Doit être une occasion d'une discussion bienveillante + \item + Pour les «~bons~» commentaires, voir aussi\\ + \url{https://conventionalcomments.org/} + \end{itemize} + + \bigskip + + \textbf{L'objectif est d'œuvrer ensemble pour que le code soit plus + simple à maintenir, il n'est jamais de critiquer le travail d'un + autre} +} + +%====================================================================== + +\frame{\frametitle{Cas d'utilisation typiques} + \begin{itemize} + \item + Contributions à un dépôt où on est pas soi-même contributeur + enregistré + \item + Bonne pratique : \emph{workflow} de travail en équipe + \begin{itemize} + \item + même si tous les membres d'une équipe ont tous les droits sur un + dépôt, \emph{workflow} renforçant la qualité du projet + \item + les évolutions ne sont pas envoyées par un \ex{push} direct, + mais \emph{via} une PR + \item + principe : interdiction d'intégrer ses propres PR, obligation de + traiter les PR des autres membres + \item + résultat : toutes les contributions sont revues par au moins 2 + personnes différentes + \end{itemize} + \end{itemize} +} + +%====================================================================== + diff --git a/intro.tex b/intro.tex index 14d0c00d49ca884046a08818e55edb3bccd09b43..f587ac3e9e4608dd7e74b7003957295c958fcdc4 100644 --- a/intro.tex +++ b/intro.tex @@ -37,9 +37,9 @@ \item Comment \impt{partager} du code source ? \item - Comment travailler \impt{à plusieurs} sur des sources ? + Comment travailler \impt{à plusieurs} sur du code source ? \item - Comment travailler \impt{au même moment} sur des sources ? + Comment travailler \impt{au même moment} sur du code source ? \item Comment \impt{réconcilier les changements} de contributeurs ? \item @@ -147,9 +147,20 @@ \item Part de marché parfois estimée à 90\% sur le segment des DVCS utilisés par la communauté logiciel libre + \item + Popularisé par des sites et outils comme Github, Bitbucket, + Gitlab... \item Exemples de projets gérés : Linux (!), Gnome, Eclipse, KDE, X.org, Qt, Perl, Debian, Android, Facebook, Twitter, Rails, Google... + \item + Juste sur Github (source : \emph{Github blog}, 2024) + \begin{itemize} + \item + $\approx$~100~millions d'utilisateurs + \item + $\approx$~500~millions de dépôts + \end{itemize} \end{itemize} } diff --git a/maincommands.tex b/maincommands.tex index 21fd96c93eced9740cda9da8bf9bf473762d2170..bf6c2aa01934ad7ec9295570d30b7a119582cb61 100644 --- a/maincommands.tex +++ b/maincommands.tex @@ -1,6 +1,34 @@ %====================================================================== -\subsection{Commandes essentielles de Git} +\subsection{Commandes essentielles} + +%====================================================================== + +\frame{\frametitle{Les commandes de \ex{git}} + % \framesubtitle{\gitall} + \begin{itemize} + \item + \ex{git} est un \emph{toolkit} + \item + \ex{git}, c'est plus de 150 commandes différentes + \begin{itemize} + \item + $\approx$~une cinquantaine de haut-niveau (\emph{porcelaine}) + \item + $\approx$~une centaine de bas-niveau (\emph{plomberie}) + \end{itemize} + \item + En pratique, une trentaine de commandes suffisent à un usage + «~classique~» (une \textbf{quinzaine au quotidien}) + \item + Elles sont utilisables en ligne de commande, mais également + interfacées à la quasi-totalité des IDE + \item + Cela autorise de nombreux \emph{workflows} d'utilisation, même si + seulement 2 ou 3 sont très populaires (et suffisants pour la + plupart des usages), comme les \emph{pull requests} + \end{itemize} +} %====================================================================== @@ -198,12 +226,15 @@ Supprime la fonctionnalité DDFD\_08 entravant la stabilité du code (\textit{exemple d'ajout de fonctionnalité}) \end{itemize} + \item + Un bon site pour rédiger ses \emph{logs} de façon normalisée\\ + {\small \url{https://www.conventionalcommits.org}} \end{itemize} } %====================================================================== -\frame{\frametitle{\ext{git commit}} +\frame{\frametitle{\ex{git commit}} \framesubtitle{\gitajout} \begin{itemize} \item @@ -220,6 +251,17 @@ Les fichiers qui n'ont jamais été indexés (typiquement, les nouveaux fichiers du projet) ne sont donc pas concernés~: c'est \textbf{très généralement} ce qu'on souhaite + \item + Une commande pratique : \ex{git commit -{}-amend} + \begin{itemize} + \item + permet de modifier le dernier commit réalisé (mauvais message de + log, oubli d'un fichier) + \item + modifie naturellement le SHA1 de ce dernier commit... + \item + ne doit donc pas être lancé si un \ex{push} a été réalisé... + \end{itemize} \end{itemize} } @@ -386,7 +428,9 @@ modifications effectuées depuis)\\ \ex{git restore .} \item - Par défaut, restaure à partir de l'index (cas le plus général) + Par défaut, restaure à partir de l'index (cas le plus général)\\ + $\to$ utilise le dernier commit si l'index est vide sur un fichier + donné \item Utiliser \ex{-{}-staged} pour restaurer à partir du dépôt local sinon diff --git a/makefile b/makefile new file mode 120000 index 0000000000000000000000000000000000000000..412236a80a454baef557b5b7aa8eed15fb47b32f --- /dev/null +++ b/makefile @@ -0,0 +1 @@ +Makefile-gitmain \ No newline at end of file diff --git a/moregit.tex b/moregit.tex index 0d71b7d44ed4e834ec477aa7e4ed168480d9016f..4b4e32ab749cbc254953c26aa642052bc9f067eb 100644 --- a/moregit.tex +++ b/moregit.tex @@ -17,12 +17,15 @@ \ex{git gui} : un \emph{front-end} graphique pour dépôt Git (\emph{i.e.} lecture et écriture) \item - \ex{gitstats} : un outil de génération de statistiques pour dépôt - Git + Nombreuses possibilités de statistiques sur les sites en ligne, + comme les \emph{insights} sous GitHub \item \ex{gource} : visualisation, sous forme d'une animation, de l'évolution d'un dépôt (inutile, donc rigoureusement indispensable) + \item + Et plein d'autres, \ex{git} étant un standard de fait pour + le développement \end{itemize} } @@ -103,3 +106,24 @@ } %====================================================================== + +\frame{\frametitle{Vidéos Youtube d'initiation à Git} +\emph{Public : DUT informatique (Nancy-Charlemagne)} + + \begin{itemize} + \item + \emph{Git : principes et utilisation de base} + \url{https://youtube.com/watch?v=CrMVRQFMeyU} + \item + \emph{Live coding Git : usages avec un seul utilisateur} + \url{https://youtube.com/watch?v=3thnpVwLyMc} + \item + \emph{Live coding Git : usage avec deux (et plus) utilisateurs} + \url{https://youtube.com/watch?v=sbdqRBsXt5k} + \item + \emph{Git : fin du cours et création de paire de clés SSH} + \url{https://youtube.com/watch?v=CkVPVcaePVs} + \end{itemize} +} + +%====================================================================== diff --git a/ssh.tex b/ssh.tex index 374b20f707e197193fef5890239be0eaa7965828..2f0882b183698a7828774a9cbfecc6aaecf84ae8 100644 --- a/ssh.tex +++ b/ssh.tex @@ -1,18 +1,27 @@ %====================================================================== -\section{Authentification SSH} +\section{Aspects techniques} + +%====================================================================== + +\subsection{Authentification SSH} %====================================================================== \frame{\frametitle{Problématique} \begin{itemize} \item - De nombreux serveurs Git utilisent une authentification par clés - publiques SSH + De nombreux serveurs \ex{git} utilisent une authentification par + clés publiques SSH \item - Si le répertoire \ex{\textasciitilde/.ssh} existe et qu'il - contient des fichiers \ex{id\_rsa} et \ex{id\_rsa.pub}, une clé - existe déjà~! + Vous avez déjà une clé si le répertoire \ex{\textasciitilde/.ssh} + existe et qu'il contient des fichiers + \begin{itemize} + \item + \ex{id\_rsa} et \ex{id\_rsa.pub} + \item + ou \ex{id\_ed25519} et \ex{id\_ed25519.pub} + \end{itemize} \item Sinon, il faut en générer une pour pouvoir communiquer avec les serveurs... @@ -21,7 +30,7 @@ %====================================================================== -\frame{\frametitle{Génération de clé SSH RSA} +\frame{\frametitle{Génération de clé SSH RSA ou Ed25519} \begin{itemize} \item Pour générer une clé, utiliser \ex{ssh-keygen} @@ -40,8 +49,8 @@ \item c'est fondamentalement un mot de passe \item - un mot de passe fait généralement entre 6 et 8 caractères, là où - une \emph{passphrase} fait plutôt entre 20 et 30 caractères + un mot de passe fait généralement entre 8 et 12 caractères, là où + une \emph{passphrase} fait plutôt entre 15 et 30 caractères \item cette \emph{passphrase} sera demandée lors des connexions SSH, c'est-à-dire pour chaque opération impliquant un dépôt distant @@ -56,7 +65,7 @@ \item Pour pouvoir communiquer \emph{via} SSH avec un serveur, il est nécessaire d'y déposer sa clé publique (le contenu du fichier - \ex{id\_rsa.pub}) + \ex{id\_rsa.pub} ou \ex{id\_ed25519.pub}) \item Les serveurs proposent généralement d'effectuer ce dépôt \emph{via} une interface Web diff --git a/to_add.txt b/to_add.txt new file mode 100644 index 0000000000000000000000000000000000000000..f5a0fea20357a38d9fe82dc4a52abe7b92c49d65 --- /dev/null +++ b/to_add.txt @@ -0,0 +1,108 @@ +Sous git, quelle commande utiliser pour récupérer une nouvelle branche distante en local ? +ChatGPT a dit : +Pour récupérer une nouvelle branche distante en local sous Git, utilise la commande suivante : + +bash +Copier +Modifier +git fetch origin +Ensuite, pour créer une branche locale qui suit la branche distante : + +bash +Copier +Modifier +git checkout -b nom-de-la-branche origin/nom-de-la-branche +Ou, si tu utilises Git 2.23 ou plus récent, la version recommandée est : + +bash +Copier +Modifier +git switch -c nom-de-la-branche origin/nom-de-la-branche +Si tu veux récupérer toutes les branches distantes et mettre à jour tes références locales, tu peux aussi utiliser : + +bash +Copier +Modifier +git fetch --all +Et si la branche existe déjà en local mais que tu veux simplement te synchroniser avec la dernière version distante : + +bash +Copier +Modifier +git checkout nom-de-la-branche # ou `git switch nom-de-la-branche` +git pull origin nom-de-la-branche +Est-ce que tu veux un comportement particulier, par exemple automatiser cela dans un script ? + + +2/2 + + +Vous avez dit : +Et pour récupérer toutes les branches distantes d'un coup ? +ChatGPT a dit : +Pour récupérer toutes les branches distantes en local d’un coup, utilise : + +bash +Copier +Modifier +git fetch --all +Cela mettra à jour toutes les références des branches distantes. Cependant, cela ne crée pas automatiquement des branches locales pour chacune. + +Si tu veux créer automatiquement des branches locales pour toutes les branches distantes, tu peux exécuter : + +bash +Copier +Modifier +for branch in $(git branch -r | grep -v '\->' | sed 's/origin\///'); do + git branch --track "$branch" "origin/$branch" +done +Puis, pour toutes les récupérer en local : + +bash +Copier +Modifier +git fetch --all +git pull --all +Si tu veux simplement voir la liste des branches distantes sans les récupérer : + +bash +Copier +Modifier +git branch -r + + + + + + + + +Sous git, comment supprimer le staging d'un fichier ? +ChatGPT a dit : +Sous Git, si tu as ajouté un fichier à la zone de staging avec git add, mais que tu veux annuler cette action sans supprimer les modifications dans le fichier, tu peux utiliser : + +bash +Copier +Modifier +git reset <nom_du_fichier> +Explication : +Cela retire le fichier de la zone de staging, mais conserve ses modifications dans ton répertoire de travail. + +Si tu veux retirer tous les fichiers du staging, utilise : + +bash +Copier +Modifier +git reset +Si tu veux annuler complètement les modifications du fichier (et revenir à son état du dernier commit), utilise : + +bash +Copier +Modifier +git checkout -- <nom_du_fichier> +ou, avec les versions plus récentes de Git : + +bash +Copier +Modifier +git restore <nom_du_fichier>