Contrôle de Version (Avancé)
Dans cette unité, nous couvrirons les fonctionnalités avancées des systèmes de contrôle de version (VCS) à l'exemple
de git
.
Nous commencerons par un petit récapitulatif des bases apprises précédemment, puis nous nous pencherons sur les branches
et sur la manière dont elles peuvent être utilisées au mieux pour collaborer efficacement.
Résumé de la lecture
Les branches permettent de travailler sur plusieurs fonctionnalités logicielles en parallèle. Si elles sont utilisées efficacement, votre logiciel gagne en fonctionnalité sans jamais régresser. En particulier, vous aurez toujours une version stable et présentable de votre produit.
Récapitulatif des bases de Git
Le modèle
Git gère les versions de logiciels en utilisant un modèle graphe.
- Chaque nœud du graphe est un commit, c'est-à-dire un instantané de la version du code.
- Ajouter une fonctionnalité correspond à ajouter de nouveaux commits à un nœud feuille, c'est-à-dire à étendre le graphe.
- Le système de fichiers montre toujours le contenu basé sur un commit donné. Le commit sur lequel vous travaillez
actuellement est également appelé
HEAD
, c'est-à-dire où vous vous trouvez dans le graphe des commits. - Pour changer la représentation du système de fichiers vers un autre nœud du graphe, utilisez la
commande
git checkout
.
Les dépôts
Chaque dépôt git contient un graphe git.
- Un dépôt peut être local, ou sur un serveur distant.
- Les serveurs git sont utiles pour partager le travail, mais git peut être utilisé sans serveur, par exemple, un lecteur USB commun peut être utilisé pour partager le travail.
Synchroniser les commits
Lors de la synchronisation du travail entre des dépôts, par exemple entre local et distant (serveur), vous essayez effectivement de combiner des modèles graphes.
- Si les différences dans le modèle graphe sont purement additionnelles, la combinaison du graphe se fait automatiquement.
- Si des modifications divergentes ont été apportées aux modèles graphes et affectent les mêmes fichiers, il faudra résoudre manuellement le conflit.
Création de branches
Jusqu'à présent, vous avez travaillé avec une seule branche, c'est-à-dire que le graphe était en réalité juste une longue ligne de commits :
---
title: "Single branch graph model"
---
gitGraph:
commit id: "1"
commit id: "2"
commit id: "HEAD" type: HIGHLIGHT
C'est en réalité une pratique dangereuse :
- Pendant que vous travaillez sur une fonctionnalité, votre code pourrait ne pas du tout être dans un état fonctionnel.
- Les tests pourraient échouer, ou le programme pourrait même ne pas se compiler.
- Il serait bon de commettre régulièrement...
- ... mais d'un autre côté, vous ne voulez pas de commits régressifs (avec un état de logiciel cassé) sur votre branche de production.
C'est ici que les branches interviennent :
- Les branches vous permettent de bifurquer à partir de n'importe quel commit existant, puis de développer tranquillement sur une fonctionnalité spécifique.
- Si vous avez des "états cassés" intermédiaires du logiciel et que vous effectuez un commit, c'est acceptable : Les
nouveaux commits se trouvent sur une branche séparée et n'interfèrent pas avec ceux qui ont besoin d'une
branche
main
propre. - Exemple :
- Pendant que vous travaillez sur votre contrôleur de halma, vous pourriez aussi travailler sur autre chose, par exemple une interface utilisateur alternative, ou un joueur robot IA.
- Une branche supplémentaire vous permet de développer une fonctionnalité tout en laissant la ligne
main
intacte.
Comme pour tout le reste autour de git
, il existe une commande pour créer de nouvelles branches :
- Pour créer et placer le HEAD sur une nouvelle branche :
git checkout -b user-interface
- Décomposons la commande :
checkout
: aller à un autre commit-b
(pour branche) : le commit se trouve en fait sur une nouvelle brancheuser-interface
: le nom de votre nouvelle branche
- Notez que les nouvelles branches se créent toujours à partir de votre HEAD, c'est-à-dire du commit dans le graphe que vous avez sélectionné le plus récemment.
Utilisez la convention kebap pour les noms de branches
Les noms de branches doivent être lisibles, mais ne pas contenir d'espaces. Tout le monde semble être d'accord pour utiliser des mots tout en minuscules, séparés par un tiret. Cette notation est également connue sous le nom de notation kebap, en référence à la viande (ou tofu) sur un bâton.
Note : Il existe également l'option de créer une branche sans placer directement le
HEAD
. D'après mon expérience, ce n'est généralement pas ce que vous voulez, mais pour être complet :git branch user-interface
provoque uniquement la création de la branche.
Créer une branche à partir de main
-
Dans la plupart des cas, vous voudrez développer de nouvelles fonctionnalités à partir de la version la plus récente du code.
- Dans ce cas, la première étape consiste toujours à vérifier que vous êtes sur le commit le plus récent de
main
. Vous voulez que votreHEAD
soit à la fin de la lignemain
. - Pour en être sûr, vous pouvez commencer par
git checkout main
. - Dans tous les cas, vérifiez votre
git status
. Vous devriez voir ceci :
- Dans ce cas, la première étape consiste toujours à vérifier que vous êtes sur le commit le plus récent de
-
Ensuite, vous pouvez créer une nouvelle branche en toute sécurité avec
git checkout -b user-interface
---
title: "Creating a branch from main"
---
gitGraph:
commit id: "1"
commit id: "2"
commit id: "3"
branch "user-interface"
checkout "user-interface"
commit id: "4"
commit id: "HEAD" type: HIGHLIGHT
* Quel est l'effet ?
* Vous pouvez développer de nouvelles fonctionnalités, basées sur le commit le plus récent.
* Quel que soit le progrès expérimental que vous réalisez sur la branche user-interface
, la branche main
reste
stable.
* Si vous vous approchez d'une échéance, au moins avec main
vous avez quelque chose à soumettre qui fonctionnera à
peu près pour une démo / soumission – même si tout va très mal sur la branche user-interface
.
Créer une branche à partir d'un HEAD détaché
- Parfois, vous voulez ajouter une nouvelle fonctionnalité à partir d'une version antérieure du code.
- Cela signifie : vous voulez créer une nouvelle branche, mais vous voulez qu'elle soit basée sur un commit antérieur dans le graphe.
- Mais attention, avoir un
HEAD
détaché n'est généralement pas ce que vous voulez. Vous travaillez effectivement avec un code obsolète. Cependant, cela peut avoir du sens si...- Vous suspectez un bug grave dans le dernier commit de
main
, et vous êtes assez sûr qu'il sera annulé. - Le dernier commit a introduit un refactoring majeur, et vous ne pouvez pas mentalement gérer à la fois le refactoring et l'ajout de nouvelles fonctionnalités. Mais pour une raison quelconque, le travail sur la fonctionnalité ne doit pas être retardé.
- Vous suspectez un bug grave dans le dernier commit de
Qu'est-ce qu'un HEAD détaché, déjà ?
"HEAD" est simplement une métaphore de l'endroit où vous vous trouvez dans le graphe (sur quel commit vous êtes pointé). "Détaché" signifie que vous ne pointez pas vers le commit le plus récent de la branche.
- Créer une branche à partir d'un commit antérieur se ferait ainsi :
Cela donnerait lieu au graphe de commits suivant :
---
title: "Creating a branch from detached HEAD"
---
gitGraph:
commit id: "1"
commit id: "2"
branch "user-interface"
checkout "main"
commit id: "3"
checkout "user-interface"
commit id: "4"
commit id: "HEAD" type: HIGHLIGHT
Créer une branche à partir d'une branche
- Parfois, vous voulez créer une nouvelle fonctionnalité qui dépend d'une autre fonctionnalité actuellement en développement.
- Dans ce cas, vous devez créer une branche à partir d'une autre branche.
- Comme précédemment, l'astuce consiste à d'abord placer le HEAD sur la branche à partir de laquelle vous souhaitez dévier.
- Le code ci-dessus peut être représenté comme suit :
--- title: "Creating a branch from main" --- gitGraph: commit id: "1" commit id: "2" commit id: "3" branch "user-interface" checkout "user-interface" commit id: "4" commit id: "5" branch "some-extra-feature" commit id: "HEAD" type: HIGHLIGHT
Journal des branches
Comme vous l'avez déjà appris dans les bases de git, il est toujours bon d'inspecter régulièrement le graphe avant de taper plus de commandes git.
- Cependant, le
git log
standard ne montre que les commits de la branche sur laquelle vous vous trouvez actuellement.- Lorsqu'on travaille avec des branches, cela donne une représentation incomplète, et parfois trompeuse.
- Si vous voulez vraiment savoir ce qui se passe, ajoutez quelques paramètres :
--all
: pour voir tous les commits sur toutes les branches--decorate
: pour afficher les informations sur les branches--oneline
: pour représenter chaque commit sur une seule ligne, et obtenir une visualisation plus compacte--graph
: pour obtenir une visualisation de l'ensemble du graphe
- Exemple :
# Setup repo
git init
# Create initial commit on main
echo "Keksli is cute" > keksli.txt
git add keksli.txt
git commit -m "initial commit"
# Add two commits to other branch
git checkout -b funny-branch
echo "We <3 Keksli" >> keksli.txt
git add keksli.txt
git commit -m "branch commit 1"
echo "We love him so so much" >> keksli.txt
git add keksli.txt
git commit -m "branch commit 2"
# Add another commit on main
git checkout main
echo "He is so cute" >> keksli.txt
git add keksli.txt
git commit -m "main commit 2"
git log --all --decorate --oneline --graph
Que doit afficher un git log
complet ?
Réponse : Il doit afficher une représentation textuelle de l'ensemble du graphe des commits :
A dog
- La commande est en fait facile à retenir ! Il suffit de penser "Un Chien !"
Créez un alias
Si vous trouvez cette ligne trop longue à mémoriser, créez un alias avec : `git config --global alias.adog "log --all --decorate --oneline --graph"
git log --oneline
02dd18a (HEAD -> main, origin/main, origin/HEAD) most recent commit
c764ed0 some commit before
cd1062f some commit even earlier before
c5434da the first commit
git checkout c764ed0
- La commande
checkout
vous permet en réalité de naviguer vers n'importe quel commit dans le graphe, il n'est pas nécessaire que ce soit un commit sur la branchemain
. - Ainsi, dans l'exemple suivant, vous pourriez déplacer votre HEAD vers n'importe quel commit de n'importe quelle
branche, en utilisant la commande
checkout
:--- title: "Moving to another commit" --- gitGraph: commit id: "1" commit id: "HEAD" type: HIGHLIGHT commit id: "3" branch "user-interface" checkout "user-interface" commit id: "4" commit id: "5"
git checkout 4
gitGraph: commit id: "1" commit id: "2" commit id: "3" branch "user-interface" checkout "user-interface" commit id: "HEAD" type: HIGHLIGHT commit id: "5"
Garder le HEAD sur vos épaules
- La plupart du temps, vous voudrez déplacer votre HEAD vers la fin d'une branche.
- Les noms de branches sont plus faciles à retenir que les numéros de commits. Mais changer pour un nom de branche vous garantit également de garder votre HEAD attaché.
- Vous pouvez simplement fournir le nom de la branche :
git checkout user-interface
- Mais pour éviter toute confusion avec le changement vers un commit spécifique, il existe aussi la
commande
switch
:
git switch user-interface
(Certains préfèrent cela. Je n'ai pas de préférence. Utilisez ce que vous préférez.)--- title: "Moving to the \"end\" of a branch" --- gitGraph: commit id: "1" commit id: "2" commit id: "3" branch "user-interface" checkout "user-interface" commit id: "4" commit id: "HEAD" type: HIGHLIGHT
Étendre les branches
Les commits sont toujours ajoutés au commit sur lequel vous vous trouvez actuellement.
- Idéalement, votre HEAD est attaché à la fin d'une branche.
- Dans ce cas, vous étendez simplement la branche sur laquelle vous avez effectué le dernier
checkout
. - Exemple :
- Dans ce cas, vous étendez simplement la branche sur laquelle vous avez effectué le dernier
# Make sure to place HEAD at end of the user-interface branch
git checkout user-interface
echo "Some new file content" > some-new-file
git add some-new-file
git commit -m "Added some new file"
# Here we've added a new commit to the end of the user-interface branch.
# Initial state: two commits, and HEAD is detached
git adog
* a99d339 (main) added whiskers
* 6a66966 (HEAD) initial commit
echo "..." >> keksli
git add keksli
git commit -m "added more ..."
[detached HEAD 767f84c] added more ...
1 file changed, 1 insertion(+)
git adog
* 767f84c (HEAD) added more ...
| * a99d339 (main) added whiskers
|/
* 6a66966 initial commit
Fusionner les branches
- Jusqu'à présent, vous avez vu comment créer de nouvelles branches, c'est-à-dire de nouvelles lignes de commits.
- Mais peu importe la nouvelle fonctionnalité que vous implémentez, à la fin de la journée, vous voulez la fusionner
avec la branche
main
, pas sur une branche de fonctionnalité isolée. C'est-à-dire :- Une fois que vous avez atteint un état stable, vous voulez fusionner votre nouveau code (les nouveaux commits sur
votre branche de fonctionnalité) avec la branche
main
. - Surtout, vous ne voulez pas fusionner du code tant qu'il est en cours de développement. Le code doit être dans un état stable, et tout votre nouveau code doit être compilé, correctement testé et commenté.
- Une fois que vous avez atteint un état stable, vous voulez fusionner votre nouveau code (les nouveaux commits sur
votre branche de fonctionnalité) avec la branche
- Ce processus qui consiste à ramener une fonctionnalité d'une branche à une autre s'appelle la fusion.
- Plus précisément : La fusion est l'effort de combiner le travail de différentes branches locales.
- La syntaxe de base est :
# Go to the branch that wants to receive the commits: git checkout main # Merge from the branch that has the commits to receive: git merge user-interface
- Illustration
--- title: "Merging branch into main" --- gitGraph: commit id: "1" commit id: "2" commit id: "3" branch "user-interface" checkout "user-interface" commit id: "4" commit id: "5" checkout "main" merge "user-interface" commit id: "HEAD" type: HIGHLIGHT
- Illustration
- La syntaxe de base est :
Scénarios de fusion
Selon la structure du graphe, la fusion peut être simple et entièrement automatisée, ou nécessiter une intervention manuelle :
- Si seule la branche à partir de laquelle vous effectuez la fusion a de nouveaux commits : La fusion est simple, un nouveau commit est créé, combinant le résultat de tous les commits fusionnés.
- Si les deux branches ont de nouveaux commits...
- si elles n'affectent pas les mêmes fichiers : Il n'y a aucun conflit, un nouveau commit est créé, combinant le résultat de tous les commits fusionnés.
- si elles affectent les mêmes fichiers, mais pas les mêmes lignes : Il n'y a aucun conflit, un nouveau commit est créé, combinant le résultat de tous les commits fusionnés.
- si elles affectent les mêmes fichiers et les mêmes lignes : Il y a un conflit de fusion. Vous devez manuellement indiquer quelle version de ligne doit l'emporter. Ensuite, un nouveau commit est créé.
C'est pourquoi vous voulez un dépôt sans encombrement
Les conflits de fusion sont gérables pour le code, mais extrêmement fastidieux pour les fichiers binaires ou générés, car il n'existe pas de moyen significatif de les résoudre manuellement au niveau des lignes. C'est pourquoi vous ne voulez pas d'encombrement dans votre dépôt. Gardez les fichiers non pertinents hors de votre dépôt, vous ne voulez pas perdre votre temps avec des conflits de fusion absurdes !
Fusion fréquente de main
dans la branche de fonctionnalité
- Plus vous attendez pour fusionner des branches, plus cela devient complexe.
- Plus vous attendez, plus il est probable qu'il y ait de nouveaux commits sur les deux branches, plus il y a de chances que des changements affectent les mêmes fichiers et les mêmes lignes.
- Si le développement de votre fonctionnalité prend un certain temps, vous pouvez régulièrement fusionner
main
dans votre branche, avant de finalement fusionner avecmain
. - Des fusions multiples et plus petites sont plus faciles que des fusions massives et rares !
- Voici une illustration de la fusion de
main
dans une branche de fonctionnalité :
---
title: "Merging branch into main"
---
gitGraph:
commit id: "1"
commit id: "2"
commit id: "3"
branch "user-interface"
checkout "user-interface"
commit id: "4"
checkout "main"
commit id: "5"
checkout "user-interface"
merge "main"
checkout "main"
commit id: "6"
checkout "user-interface"
commit id: "7"
checkout "main"
merge "user-interface"
commit id: "HEAD" type: HIGHLIGHT
La fusion fréquente ne contredit pas les commits fréquents !
Bien que vous souhaitiez attendre que votre code soit dans un bon état avant de fusionner, vous devez garder des commits fréquents sur la branche de fonctionnalité. Évitez les méga-commits, ce sera un vrai casse-tête à fusionner.
Synchroniser les branches entre les dépôts
- Contrairement à Dropbox, iCloud ou Google Drive, les dépôts Git ne se synchronisent pas automatiquement.
- (La synchronisation automatique serait horrible, vous auriez constamment peur des mises à jour en cours de développement cassées de vos pairs !)
- Dans la leçon de bases de VCS, vous avez déjà appris que les commits doivent être activement poussés ou tirés vers
et depuis un serveur distant.
git commit
crée seulement un commit local.- Le commit n'est pas encore sur le serveur. Il reste strictement sur votre machine jusqu'à ce que vous
push
le commit sur le serveur.
- Les branches fonctionnent de la même manière !
git checkout -b ma-nouvelle-branche
crée une nouvelle branche locale.- La branche n'est pas encore sur le serveur. Elle reste strictement sur votre machine jusqu'à ce que vous
push
la branche sur le serveur.
Envoyer des branches vers le serveur distant
- Pousser une nouvelle branche vers le serveur est simplement une commande
push
plus longue :
git push --set-upstream origin ma-nouvelle-branche
Vous n'avez pas besoin de vous souvenir de cela
Il n'est pas nécessaire de vous souvenir de cette commande push
spéciale. Si vous tentez un push
normal, Git vous rappellera la syntaxe correcte.
Tirer des branches vers votre machine locale
- Il est fréquent que vous souhaitiez travailler sur une branche qui se trouve sur le dépôt distant, mais qui n'est pas
encore présente sur votre dépôt local.
- Cela se produit, par exemple, lorsqu'un collègue a créé une nouvelle branche sur sa machine et l'a ensuite poussée sur le serveur distant.
- Avant de pouvoir utiliser leur branche et y ajouter de nouveaux commits, vous devez obtenir une copie de cette branche dans votre dépôt.
- Exemple :
- Vous commencez par vérifier vos branches locales
- Vous savez que votre collègue a commencé à travailler sur une branche
user-interface
, mais elle n'est pas présente dans votre dépôt. - Vous ne voulez PAS créer une nouvelle branche vous-même, vous souhaitez récupérer la branche de votre collègue !
- Il existe deux principales façons de récupérer des branches depuis le serveur, et elles sont étroitement liées mais présentent une différence subtile.
Récupérer (Fetch)
- Dans le cas le plus simple, vous voulez simplement récupérer les nouvelles branches du serveur distant.
- Vous pouvez le faire avec
git fetch
. - Exemple :
- Vous commencez par vérifier vos branches locales
- La branche que vous recherchez n'est pas présente, donc vous utilisez
git fetch
pour récupérer les nouveaux commits depuis le serveur :
Fetch ne fait pas de fusion automatique !
Un détail important à propos de fetch
est qu'il ne tente pas de fusionner, mais récupère uniquement les nouveaux commits.
- Les commits récupérés par
fetch
sont toujours stockés sur des branches supplémentaires, c'est-à-dire que les nouveaux commits ne sont pas combinés avec les branches que vous avez déjà. - Dans l'exemple précédent, ce n'était pas un problème, car vous vouliez récupérer une branche entièrement nouvelle.
- Mais la plupart du temps, vous récupérez de nouveaux commits ou branches, non pas pour les laisser sur des branches locales inutilisées, mais parce que vous souhaitez aussi les intégrer avec vos propres nouveaux commits.
- À moins que vous ne soyez intéressé par une branche entièrement nouvelle,
fetch
est toujours suivi par unmerge
, afin que vous puissiez réellement intégrer les nouveaux commits avec vos propres progrès.
Pull
- Dans le premier cours et atelier sur le VCS, vous avez déjà vu brièvement la commande
pull
. pull
n'est en réalité pas nouveau, mais c'est juste la combinaison defetch
+merge
.- Je n'utilise que rarement
fetch
. Les nouveaux commits ne servent à rien à moins d'être également fusionnés avec vos propres progrès.
Pull vs Fetch
Pull
et fetch
récupèrent tous les deux les commits du dépôt distant, mais pull
tente implicitement aussi de fusionner
les nouveaux commits (il essaie de combiner et de déplacer votre HEAD
dans la branche actuelle), tandis que fetch
ne récupère que le commit sans déplacer votre HEAD
. Dans la plupart des cas, vous voulez faire un pull
.
Suppression des branches
- À un moment donné, les branches ont rempli leur objectif.
- Par exemple, si une fonctionnalité est finalisée et que la branche a été fusionnée dans la branche principale, vous n'avez plus besoin de cette branche.
- C'est une bonne pratique de supprimer également la branche dans ce cas, afin qu'elle ne vous distrait pas lorsque vous
inspectez votre dépôt avec
git branch -a
.
L'un n'implique pas l'autre
Supprimer une branche locale n'implique pas la suppression de la branche distante.
De même, supprimer une branche distante n'implique pas la suppression de la branche locale.
Local
-
Pour supprimer une branche locale, utilisez simplement l'une des commandes suivantes :
git branch --delete user-interface
git branch -d user-interface
-
Pour vous éviter de supprimer accidentellement du travail non sauvegardé, git ne vous laissera pas supprimer des branches non fusionnées. Vous pouvez forcer la suppression avec l'une des commandes suivantes :
git branch --delete --force user-interface
git branch -D user-interface
Remote
- Supprimer une branche d'un dépôt distant nécessite de pousser vos modifications du graphe.
- La commande correspondante est :
git push -d origin user-interface
Rebase
- En général, vous voulez que les développeurs fassent des commits régulièrement et de manière fine-grainée.
- Cela vous offre plus de liberté pour revenir en arrière en cas de problème.
- Cependant, lorsque plusieurs personnes travaillent sur le même graphe git et poussent vers plusieurs branches en même temps, cela conduit à des "diamants" dans l'historique du graphe :
La raison est que la suppression d'une branch ne supprime pas ses commits, seulement le nom de la branch associé avec. Tout branch qui a été merge laisse un diamant, peu import si supprimé ou pas.
- Il serait plus agréable d'avoir des branches qui reprennent un commit spécifique sur
main
et qui, immédiatement après, poussent leur progrès (finalisé) versmain
.- Mais cela est presque impossible, car développer de nouvelles fonctionnalités prend du temps.
- Plus l'équipe est grande, plus de nouveaux contenus seront constamment ajoutés à
main
.
-
Illustration de l'évolution de
main
, au fur et à mesure du développement deuser-interface
:--- title: main evolving in parallel to user-interface --- gitGraph commit id: "1" commit id: "2" branch user-interface checkout user-interface commit id: "3" commit id: "4" commit id: "5" type: HIGHLIGHT checkout main commit id: "6"
-
Le rebase est une astuce qui permet de modifier rétroactivement l'historique des commits, de sorte à ce que les commits sur une branche apparaissent comme s'ils s'étaient produits de manière séquentielle, plutôt que parallèlement.
- Dans l'exemple ci-dessus, le graphe est modifié pour ressembler à ceci :
--- title: Commit graph after rebase --- gitGraph commit id: "1" commit id: "2" commit id: "6" branch user-interface checkout user-interface commit id: "3R" commit id: "4R" commit id: "5R" type: HIGHLIGHT checkout main
Syntaxe
- Pour faire en sorte que les commits d'une branche de fonctionnalité soient réorganisés (rebase) à partir du dernier commit de la branche principale (voir illustration ci-dessus) :
# place the HEAD on the user-interface branch
git checkout user-interface
# make the commits on user-interface branch rebase from the most recent main commit
git rebase main
- Il est fort probable que vous souhaitiez ensuite ramener vos changements sur
main
(sans les diamants !) - Vous venez de faire un rebase, vous êtes donc assuré de ne pas avoir de conflits de fusion.
# go back to the main branch
git checkout main
# merge the rebased feature branch into main
git merge user-interface
Fonctionnement interne du rebase
Comment le rebase fonctionne-t-il réellement ?
- L'idée de déplacer des commits est quelque peu artificielle, car l'idée même d'un commit est de définir une certaine position dans le graphe des commits.
- Le rebase ne déplace pas réellement les commits, mais plutôt :
- Cache les commits originaux d'une certaine série, par exemple une branche.
- Rejoue chacun des commits originaux, c'est-à-dire :
- Créer une copie ailleurs dans le graphe
- Imiter exactement les mêmes modifications de fichiers que dans le commit original
- Créer un nouveau conflit de fusion pour chaque problème rencontré
- Optionnel : Supprimer les commits cachés.
Cherry-pick
- La fusion tente de combiner le travail de tous les commits d'une branche différente jusqu'à un commit spécifique.
- Dans certaines situations, cela peut être trop grossier :
- Imaginez qu'un collègue travaille sur une branche de fonctionnalité et qu'il a également corrigé un petit bug pertinent pour vous.
- Dans ce cas, vous ne voulez pas nécessairement fusionner tout leur travail, juste pour récupérer cette petite correction de bug.
- La commande
cherry-pick
vous permet de combiner les travaux de manière plus sélective. - Plus précisément, le cherry-pick (un autre commit étant la cerise sur le gâteau) vous permet de fusionner avec un commit spécifique, indépendamment de ce qui s'est passé avant sur cette branche.
- Exemple :
# trace the commits of all branches
git adog
* 9ff78e3 (HEAD -> main) some-recent-commit
| * 89afd4f (some-other-branch) commit-to-cherrypick
| * c081b9e some-non-relevant-commit
|/
* 151c4c6 first-commit
# just making sure the HEAD is attached to main
git checkout main
# go get that commit from another branch!
git cherry-pick 89afd4f
Tags
- Les tags vous permettent d'étiqueter un commit spécifique, afin de pouvoir le retrouver plus facilement plus tard.
- Les tags sont souvent utilisés pour les versions majeures, par exemple
Halma-1.4.0
.
Tags "soft"
- Pour taguer le commit le plus récent (là où votre HEAD pointe), utilisez :
git tag Halma-1.4.0
- Vous pouvez également fournir une description plus longue avec :
git tag -m "Une nouvelle version de Halma, présentant quelques joueurs bots IA." Halma-1.5.0
Afficher les tags
- Dès que vous avez des tags, vous pouvez inspecter la liste avec :
git tag
Publier les tags
- Comme tout le reste de votre dépôt local, les tags restent locaux jusqu'à ce que vous les partagiez activement, en les
poussant vers le dépôt :
git push origin Halma-1.5.0
Pensées conclusives
- Q : J'ai un bouton
git
dans mon IDE, pourquoi devrais-je m'embêter à apprendre les commandes ? - R : Tout d'abord, sentez-vous libre d'utiliser l'outil qui fonctionne le mieux pour vous. Mais voici mon avis sur les outils graphiques pour les débutants :
" git
est complexe, et vous voulez réfléchir à deux fois avant toute action. Les outils graphiques accélèrent les choses, mais mènent facilement à une approche du "essayer et échouer", un peu comme : "Je vais juste cliquer sur ceci et cela, et espérer que ça marche" (Sans vraiment comprendre ce que "ça marche" veut dire ou ce qu'on peut en attendre exactement). Ce n'est pas ainsi qu'on devient compétent avec une technologie complexe, et ce n'est pas ce qu'on attend de vous dans une entreprise. On n'apprend pas en copiant-collant depuis ChatGPT, et personne ne paiera un ingénieur qui ne sait que copier-coller depuis ChatGPT. Par contre, comprendre réellement est précieux. Mais apprendre prend du temps et de la pratique. Si vous tapez vous-même les commandesgit
, vous avez au moins plus de temps pour RÉFLÉCHIR à ce qu'elles servent à faire. Quand vous vous sentirez à l'aise avec les commandes, bien sûr, allez-y et essayez de nouveaux outils."
Littérature
Inspiration et lectures supplémentaires pour les esprits curieux :
- Learn git branching
- Git Cheatsheet (basic)
- Pro Git (free)
- MIT, the missing semester: Git