« Git/Branches » : différence entre les versions

Contenu supprimé Contenu ajouté
m JackPotte a déplacé la page Git/Branching & merging vers Git/Branches sans laisser de redirection
m refonte, en reprenant les exemples du chapitre précédent et en se concentrant sur l'essentiel, on n'aborde pas encore les dépôts distants, on explique plus pourquoi on fait les choses et pas uniquement le comment
Ligne 1 :
{{git}}
 
Précédemment, nous avons vu comment apporter des modifications à une branche telles que ajouter, modifier ou supprimer un fichier et <tt>commit</tt> nos modifications. Cela fonctionne parfaitement et cela peut suffire pour travailler seul sur un petit projet. Toutefois, ce n'est pas la meilleure façon de procéder sous git qui propose des mécanismes plus élaborés pour développer sur un projet.
== Gestion des branches ==
Les {{w|Branche (gestion de configuration)|branches}} permettent de faire évoluer parallèlement certaines versions. Chaque soumission est donc envoyée dans une branche précise.
 
L'approche de git est de favoriser l'utilisation de branche pour toute modification du code de l'application.
Le fait que Git ne nécessite pas de copier toutes ses branches sur un serveur central lui confère une plus grande rapidité.
 
Ainsi, il ne faut jamais travailler directement sur la branche *master* : cette branche doit rester stable et ne doit être utilisée que pour baser son travail dans d'autres branches.
=== Voir les branches ===
Utiliser <code>git branch</code> pour visualiser les branches du dépôts :
$ git branch
* master
La branche "master" est par défaut la principale ligne de développement. Même s'il est possible de la renommer elle est généralement utilisée sous ce nom.
 
Pour mieux comprendre, nous allons refaire, pas à pas, exactement les même modifications que celles que nous avons faites précédemment mais, cette fois, nous allons utiliser une branche afin de nous familiariser avec ce concept.
=== Créer des branches ===
Créons une branche "dev" :
$ git branch dev
$ git branch
dev
* master
 
Reprenons notre dépôt d'exemple :
{{remarque|La branche crée par cette commande ne devient pas celle qui sera utilisée : ''HEAD'' ne bouge pas comme le montre l'étoile, qui représente la branche courante.}}
 
<source lang="bash">
Pour basculer vers la nouvelle branche :
git clone https://gerrit.wikimedia.org/r/p/test/mediawiki/extensions/examples.git
$ git checkout dev
cd examples
</source>
 
=== Créer une première branche ===
Alternativement, il aurait possible de créer et basculer vers la nouvelle branche en une seule commande :
 
$ git checkout -b dev
D'abord, demandons à git de nous indiquer où nous en sommes au niveau des branches :
 
<source lang="bash">
git branch
</source>
<pre>
* master
</pre>
 
Git nous indique qu'il existe une seule branche appelée <tt>master</tt> et que c'est sur cette branche que nous travaillons comme l'indique l'astérisque en face de <tt>master</tt>.
 
Créons une nouvelle branche que nous allons appelé <tt>ma-branche</tt>
 
<source lang="bash">
git branch ma-branche
</source>
 
Constatons les effets
 
<source lang="bash">
git branch ma-branche
</source>
<pre>
ma-branche
* master
</pre>
 
Il y a maintenant deux branches : *master* et *ma-branche*. Actuellement, nous travaillons toujours sur *master* comme l'indique toujours l'astérisque.
 
<source lang="bash">
git log --decorate --graph
</source>
 
On peut voir, sur la première ligne que *master* et *ma-branche* sont au même niveau, sur le même commit. Nous allons maintenant demander à git de nous basculer sur *ma-branche* afin de pouvoir travailler sur celle-ci et non sur *master*.
 
<source lang="bash">
git checkout ma-branche
</source>
<pre>
Switched to branch 'ma-branche'
</pre>
 
On a basculé, et <tt>git branch</tt> nous le confirme.
 
<source lang="bash">
git branch
</source>
<pre>
* ma-branche
master
</pre>
 
=== Faire les modifications ===
 
On peut désormais faire les modifications dans '''ma-branche''' on peut développer, sans prendre le risque de modifier '''master'''.
 
Faisons les même modifications que précédemment :
 
<source lang="bash">
echo "Ceci est un test de git" > mon_nouveau_fichier.txt
git add mon_nouveau_fichier.txt
git commit -m "ajout d'un fichier"
echo "Une seconde ligne" >> mon_nouveau_fichier.txt
git add mon_nouveau_fichier.txt
git commit -m "ajout d'une seconde ligne dans le fichier"
echo "Une troisième ligne" >> mon_nouveau_fichier.txt
git add mon_nouveau_fichier.txt
git commit -m "ajout d'une troisième ligne dans le fichier"
</source>
 
Et ainsi de suite. Vous pouvez commiter et faire autant de commit que vous voulez dans '''ma-branche'''.
 
L'idée est que pour chaque évolution du logiciel développé, il faut créer une branche. Ainsi, on peut garder la branche aussi longtemps que nécessaire et continuer de travailler dessus tant qu'on a pas fini la fonctionnalité.
 
Regardons le <tt>log</tt> que cela produit :
 
<source lang="bash">
git log --decorate --graph
</source>
<pre>
* commit 635ace69f901dfb1aaff187e6abc54b0c95fe51e (HEAD, ma-branche)
| Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| Date: Tue Jul 22 23:33:15 2014 +0200
|
| ajout d'une troisième ligne dans le fichier
|
* commit dbc6c57019afe80dbb2f3d889eb63cb024656faa
| Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| Date: Tue Jul 22 23:33:14 2014 +0200
|
| ajout d'une seconde ligne dans le fichier
|
* commit e2cbadc10289e74a131a728e06ac2421e79b5b9f
| Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| Date: Tue Jul 22 23:33:14 2014 +0200
|
| ajout d'un fichier
|
* commit a59a042e1a7f1474a11c0bd2585ab2eb71b85c47 (origin/master, origin/HEAD, master)
|\ Merge: 5c511f2 12c8449
| | Author: Darkdadaah <darkdadaah@yahoo.fr>
| | Date: Sat May 25 08:49:21 2013 +0000
| |
| | Merge "TEST 1"
| |
</pre>
 
Examinons ce graphique : '''master''' est en retard tandis que '''ma-branche''' est en avance de trois ''commits''.
 
=== Fusionner la branche dans master ===
 
Supposons que nous sommes satisfaits du travail réalisé dans notre branche. Nous avons fait plusieurs ''commits'', nous avons vérifié que nous n'avons pas créé de bogue, etc. Supposons que notre branche est prête et qu'on peut intégrer les modifications dans master.
 
D'abord, se placer sur master.
 
<source lang="bash">
git checkout master
</source>
<pre>
Switched to branch 'master'
</pre>
 
Puis demander à git de fusionner la branche '''ma-branche''' :
 
<source lang="bash">
git merge ma-branche --no-ff -m "intégration de ma nouvelle fonctionnalité dans master"
</source>
 
Git va faire un commit pour intégrer les changements. Comme précédemment, nous avons choisi d'utiliser <tt>-m</tt> pour préciser le message de commit mais on aurait pu ne rien mettre et git nous aurait ouvert l'éditeur de texte.
 
<pre>
Merge made by the 'recursive' strategy.
mon_nouveau_fichier.txt | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 mon_nouveau_fichier.txt
</pre>
 
Examinons
 
<source lang="bash">
git log --decorate --graph
</source>
<pre>
* commit abd3ef0a5978b90db042bf076e82d64c3576194b (HEAD, master)
|\ Merge: a59a042 635ace6
| | Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| | Date: Tue Jul 22 23:43:51 2014 +0200
| |
| | intégration de ma nouvelle fonctionnalité dans master
| |
| * commit 635ace69f901dfb1aaff187e6abc54b0c95fe51e (ma-branche)
| | Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| | Date: Tue Jul 22 23:33:15 2014 +0200
| |
| | ajout d'une troisième ligne dans le fichier
| |
| * commit dbc6c57019afe80dbb2f3d889eb63cb024656faa
| | Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| | Date: Tue Jul 22 23:33:14 2014 +0200
| |
| | ajout d'une seconde ligne dans le fichier
| |
| * commit e2cbadc10289e74a131a728e06ac2421e79b5b9f
|/ Author: Michel Boudran <michel.boudran@fr.wikibooks.org>
| Date: Tue Jul 22 23:33:14 2014 +0200
|
| ajout d'un fichier
|
* commit a59a042e1a7f1474a11c0bd2585ab2eb71b85c47 (origin/master, origin/HEAD)
</pre>
 
On retrouve bien quatre ''commits'' nous appartenant (symbolisés par une * dans le graphe). On retrouve les trois premières modifications et un quatrième ''commit'' pour le <tt>merge</tt>. On voit que les branches ont convergé sur le graphique et que '''master''' est de nouveau sur la première ligne tout en haut du graphe. Nos changements ont bien été intégré à '''master'''.
 
=== Effacer une branche ===
Utiliser le paramètre <code>-d</code> :
$ git branch -d dev
 
Nos changements sont intégrés à master, la branche est désormais inutile. Supprimons-la :
Cela peut échouer si la branche à supprimer n'a pas été fusionnée dans ''master'' :
$ git branch -d dev
error: The branch 'dev' is not a strict subset of your current HEAD.
If you are sure you want to delete it, run 'git branch -D dev'.
 
<source lang="bash">
Git se prémunit donc d'effacer des changements potentiellement non vérifiés. Mais pour forcer la suppression malgré tout :
$ git branch '''-D'''d devma-branche
</source>
<pre>
Deleted branch ma-branche (was 635ace6).
</pre>
 
{{remarque|
=== Envoyer une branche dans un dépôt distant ===
La suppression de la branche peut échouer si la branche à supprimer n'a pas été fusionnée dans ''master'' :
Créer une branche locale ne la fait pas intrinsèquement se synchroniser avec un serveur. Donc de la même façon que nous pouvons les télécharger, <tt>git push</tt> les téléverse :
$ git push DepotDOrigine <NomBranche>
 
<source lang="bash">
=== Effacer une branche d'un dépôt distant ===
git branch -d ma-branche
Pour effacer une branche précédemment poussée vers un serveur distant :
</source>
$ git push DepotDOrigine :<NomBranche>
<pre>
error: The branch 'ma-branche' is not a strict subset of your current HEAD.
If you are sure you want to delete it, run 'git branch -D dev'.
</pre>
 
Git se prémunit donc d'effacer des changements potentiellement non vérifiés. Comme git l'indique, on peut forcer la suppression malgré tout :
Pour écraser une branche par une autre :
$ git push DepotDOrigine <BrancheLocale>:<BrancheDistante>
 
=== Fusionner des branches ===
Pour la branche courante avec une autre dont on connait le nom :
<source lang="bash">
git branch -D ma-branche
$ git merge NomBranche
</source>
}}
 
{{à faire|expliquer pourquoi --no-ff}}
 
== Continuer ==
 
Vous pouvez à tout moment créer des nouvelles branches depuis '''master''' et ce, à chaque nouvelle fonctionnalité ou nouvelle modification qu'il faudrait apporter au projet. Git vous permet de gérer plusieurs branches en parallèle et ainsi de cloisonner vos travaux et d'éviter de mélanger des modifications du code source qui n'ont rien à voir entre elles.
 
En gardant une branche '''master''' saine, vous vous laissez la possibilité de créer de nouvelles branches simplement et vous conservez ainsi une version du logiciel prête à être livrée à tout instant (puisqu'on ne <tt>merge</tt> dedans que lorsque le développement est bien terminé.
 
<tt>git log</tt> vous permet de retrouver dans l'historique les branches qui ont été crées, et les différents ''commits'' réalisés pour une même fonctionnalité sont bien regroupés entre eux.
Si la branche courante est une ancêtre de celle à fusionner, la tête (HEAD) se place directement dans la nouvelle branche. Sinon, un <code>merge commit</code> est enregistré de sorte que les précédentes soumissions des deux branches sont fusionnées comme parentes. Toutefois en cas de conflit, il faudra les résoudre avant le <code>merge commit</code>.
 
[[en:Git/Branching & merging]]
[[pl:Git/Branch]]