
belaran@953: \chapter{Un rapide tour de Mercurial: fusionner les travaux}
bos@95: \label{chap:tour-merge}
bos@94: 
belaran@954: Nous avons maintenons étudié comment cloner un dépôt, effectuer
belaran@953: des changements dedans, et récupérer ou transférer depuis un 
belaran@953: autre dépôt. La prochaine étape est donc de \emph{fusionner} les
belaran@953: modifications de différents dépôts.
belaran@953: 
belaran@953: \section{Fusionner différents travaux} %%%TODO: better translation
belaran@953: 				       %%% for 'Merging streams of work' ?
belaran@953: La fusion\footnote{NdT: Je garde fusion mais le jargon professionnel 
belaran@954: emploiera généralement le terme \textit{merge}.} est un aspect 
belaran@953: fondamental lorsqu'on travail avec un gestionnaire de source 
belaran@954: distribué.
bos@94: \begin{itemize}
belaran@953: \item Alice et Bob ont chacun une copie personnelle du dépôt d'un
belaran@953:   projet sur lequel ils collaborent. Alice corrige un \textit{bug} 
belaran@953:   dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le
belaran@953:   sien. Ils veulent un dépôt partagé avec à la fois le correctif du
belaran@953:   \textit{bug} et la nouvelle fonctionnalité.
belaran@953: \item Je travaille régulièrement sur plusieurs tâches différentes sur
belaran@953:   un seul projet en même temps, chacun isolée dans son propre dépôt.
belaran@953:   Travailler ainsi signifie que je dois régulièrement fusionner une 
belaran@953:   partie de mon code avec celui des autres.
bos@94: \end{itemize}
bos@94: 
belaran@953: Parce que la fusion est une opération si commune que je dois réaliser,
belaran@954: Mercurial la rend facile. Étudions ensemble le déroulement des opérations.
belaran@954: Nous commencerons par faire un clone de encore un autre dépôt (vous voyez
belaran@953: comment on fait ça tout le temps ?) puis nous ferons quelques modifications
belaran@953: dessus.
bos@94: \interaction{tour.merge.clone}
belaran@953: Nous devrions avoir maintenant deux copies de \filename{hello.c} avec 
belaran@953: des contenus différents. Les historiques de ces deux dépôts ont aussi 
belaran@953: divergés, comme illustré dans la figure~\ref{fig:tour-merge:sep-repos}.
belaran@953: 
bos@94: \interaction{tour.merge.cat}
bos@94: 
bos@99: \begin{figure}[ht]
bos@99:   \centering
bos@99:   \grafix{tour-merge-sep-repos}
belaran@953:   \caption{Historiques récent divergents des dépôts \dirname{my-hello} 
belaran@953:   et \dirname{my-new-hello}}
bos@99:   \label{fig:tour-merge:sep-repos}
bos@99: \end{figure}
bos@99: 
belaran@953: Nous savons déjà que récupérer les modifications depuis notre dépôt 
belaran@953: \dirname{my-hello} n'aura aucun effet sur l'espace de travail.
belaran@953: 
bos@94: \interaction{tour.merge.pull}
belaran@953: 
belaran@954: Néanmoins, la commande \hgcmd{pull} nous indique quelque chose au 
belaran@953: sujet des ``heads''.
belaran@953: 
belaran@953: \subsection{\textit{Head changesets}} %%%TODO: Hard (too?) to translate
belaran@953: 
belaran@953: Une \textit{head}\footnote{NdT: Je garde \textit{head} que j'accorde 
belaran@953: au féminin comme la coutume oral l'a imposée.} est un \textit{changeset} 
belaran@953: sans descendants, ou enfants, comme on les désigne parfois. La révision 
belaran@953: \textit{tip} est une \textit{head}, car la dernière révision dans un dépôt 
belaran@953: n'a aucun enfant, mais il est important de noter qu'un dépôt peut contenir 
belaran@953: plus d'une \textit{head}.
bos@99: 
bos@99: \begin{figure}[ht]
bos@99:   \centering
bos@99:   \grafix{tour-merge-pull}
belaran@953:   \caption{Contenu d'un dépôt après avoir transférer le contenu du dépôt 
belaran@953:     \dirname{my-hello} dans le dépôt \dirname{my-new-hello}}
bos@99:   \label{fig:tour-merge:pull}
bos@99: \end{figure}
bos@99: 
belaran@953: Dans la figure~\ref{fig:tour-merge:pull}, vous pouvez constater l'effet
belaran@953: d'un \textit{pull} depuis le dépôt \dirname{my-hello} dans le dépôt 
belaran@953: \dirname{my-new-hello}. L'historique qui était déjà présent dans le dépôt
belaran@953: \dirname{my-new-hello} reste intact, mais une nouvelle révision a été 
belaran@953: ajoutée. En vous reportant à la figure~\ref{fig:tour-merge:sep-repos},
belaran@953: vous pouvez voir que le \textit{\emph{changeset ID}} reste le même dans
belaran@953: le nouveau dépôt, mais que le \emph{numéro de révision} reste le même.
belaran@953: (Ceci est un parfait exemple de pourquoi il n'est fiable d'utiliser les
belaran@953: numéro de révision lorsque l'on discute d'un \textit{changeset}.) Vous
belaran@953: pouvez voir les \texit{heads} présente dans le dépôt en utilisant la 
belaran@953: commande \hgcmd{heads}.
bos@94: \interaction{tour.merge.heads}
bos@102: 
belaran@953: \subsection{Effectuer la fusion}
belaran@953: 
belaran@953: Que se passe-t-il quand vous essayez d'utiliser la commande \hgcmd{update} 
belaran@953: pour mettre à jour votre espace de travail au nouveau \textit{tip}.
bos@94: \interaction{tour.merge.update}
belaran@953: Mercurial nous prévient que la commande \hgcmd{update} n'effectuera pas
belaran@953: la fusion, il ne veut pas mettre à jour l'espace de travail quand il 
belaran@953: estime que nous pourrions avoir besoin d'une fusion, à moins de lui
belaran@953: forcer la main. À la place, il faut utiliser la commande \hgcmd{merge}
belaran@953: pour fusionner les deux \textit{heads}.
bos@94: \interaction{tour.merge.merge}
bos@100: 
bos@100: \begin{figure}[ht]
bos@100:   \centering
bos@100:   \grafix{tour-merge-merge}
belaran@953:   \caption{Espace de travail et dépôt lors d'une fusion, et dans le
belaran@953:     \textit{commit} qui suit.}
bos@100:   \label{fig:tour-merge:merge}
bos@100: \end{figure}
bos@100: 
belaran@953: Ceci met à jour de l'espace de travail de manière à ce qu'il contienne
belaran@954: les modifications des \emph{deux} \textit{heads}, ce qui apparaît dans
belaran@953: les sorties de la commande \hgcmd{parents} et le contenu de 
belaran@953: \filename{hello.c}. 
bos@94: \interaction{tour.merge.parents}
bos@102: 
belaran@954: \subsection{Effectuer le \textit{commit} du résultat de la fusion}
belaran@954: 
belaran@954: Dès l'instant où vous avez effectuer une fusion, \hgcmd{parents} vous
belaran@954: affichera deux parents, avant que vous n'exécuter la commande 
belaran@954: \hgcmd{commit} sur le résultat de la fusion.
bos@94: \interaction{tour.merge.commit}
belaran@953: Nous avons maintenant un nouveau \textit{tip}, remarquer qu'il contient
belaran@953: \emph{à la fois} nos anciennes \textit{heads} et leurs parents. Ce sont
belaran@953: les mêmes révisions que nous avions affichés avec la commande 
belaran@953: \hgcmd{parents}.
belaran@953: 
bos@94: \interaction{tour.merge.tip}
belaran@953: Dans la figure~\ref{fig:tour-merge:merge}, vous pouvez voir une représentation
belaran@953: de ce qui se passe dans l'espace de travail pendant la fusion, et comment ceci
belaran@953: affecte le dépôt lors du \textit{commit}. Pendant la fusion, l'espace de travail,
belaran@953: qui a deux \texit{changesets} comme parents, voit ces derniers devenir le parent
belaran@953: d'un nouveau \textit{changeset}.
belaran@953: 
belaran@953: \section{Fusionner les modifications en conflit}
belaran@953: 
belaran@953: La plupart des fusions sont assez simple à réaliser, mais parfois 
belaran@954: vous vous trouverez à fusionner des fichiers où la modification touche
belaran@953: la même portion de code, au sein d'un même fichier. À moins que ces
belaran@953: modification ne soient identiques, ceci aboutira à un \emph{conflit},
belaran@954: et vous devrez décider comment réconcilier les différentes modifications
belaran@953: dans un tout cohérent. 
bos@103: 
bos@103: \begin{figure}[ht]
bos@103:   \centering
bos@103:   \grafix{tour-merge-conflict}
belaran@953:   \caption{Modifications conflictuelles dans un document}
bos@103:   \label{fig:tour-merge:conflict}
bos@103: \end{figure}
bos@103: 
belaran@953: La figure~\ref{fig:tour-merge:conflict} illustre un cas de modifications
belaran@953: conflictuelles dans un document. Nous avons commencé avec une version simple
belaran@953: de ce fichier, puis nous avons ajoutés des modifications, pendant que 
belaran@953: quelqu'un d'autre modifie le même texte. Notre tâche dans la résolution
belaran@953: du conflit est de décider à quoi le fichier devrait ressembler.
belaran@953: 
belaran@953: Mercurial n'a pas de mécanisme interne pour gérer les conflits. 
belaran@954: À la place, il exécute un programme externe appelé \command{hgmerge}.
belaran@953: Il s'agit d'un script shell qui est embarqué par Mercurial, vous
belaran@953: pouvez le modifier si vous le voulez. Ce qu'il fait par défaut est
belaran@953: d'essayer de trouver un des différents outils de fusion qui seront
belaran@953: probablement installé sur le système. Il commence par les outils
belaran@953: totalement automatique, et si ils échouent (parce que la résolution
belaran@953: du conflit nécessite une intervention humaine) ou si ils sont absents,
belaran@953: le script tente d'exécuter certains outils graphiques de fusion.
belaran@953: 
belaran@953: Il est aussi possible de demander à Mercurial d'exécuter un autre
belaran@953: programme ou un autre script au lieu de la commande \command{hgmerge},
belaran@954: en définissant la variable d'environnement \envar{HGMERGE} avec le nom
belaran@953: du programme de votre choix.
belaran@953: 
belaran@953: \subsection{Utiliser un outil graphique de fusion}
belaran@953: 
belaran@953: Mon outil de fusion préféré est \command{kdiff3}, que j'utilise ici
belaran@953: pour illustré les fonctionnalités classiques des outils graphiques 
belaran@953: de fusion. Vous pouvez voir une capture d'écran de l'utilisation de 
belaran@953: \command{kdiff3} dans la figure~\ref{fig:tour-merge:kdiff3}. Cet outil
belaran@953: effectue une \emph{fusion \textit{three-way}}, car il y a trois différentes
belaran@953: versions du fichier qui nous intéresse. Le fichier découpe la partie
belaran@953: supérieure de la fenêtre en trois panneaux:
belaran@953: 
bos@103: \begin{itemize}
belaran@953: \item A gauche on la version de \emph{base} du fichier, soit ~la plus 
belaran@953:   récente version des deux versions qu'on souhaite fusionner.
belaran@953: \item Au centre, il y a ``notre'' version du fichier, avec le contenu 
belaran@953:   que nous avons modifié.
belaran@953: \item Sur la droite, on trouve ``leur'' version du fichier, celui qui qui
belaran@953:   contient le \textit{changeset} que nous souhaitons intégré. 
bos@103: \end{itemize}
belaran@953: 
belaran@953: Dans le panneau en dessous, on trouve le \emph{résultat} actuel de notre
belaran@953: fusion. Notre tâche consiste donc à remplacement tout les textes en rouges,
belaran@953: qui indiquent des conflits non résolus, avec un fusion manuel et pertinente
belaran@953: de ``notre'' version et de la ``leur''. 
belaran@953: 
belaran@954: Tout les quatre panneaux sont \emph{accrochés ensemble}, si nous déroulons
belaran@953: les ascenseurs verticalement ou horizontalement dans chacun d'entre eux, les
belaran@953: autres sont mise à jours avec la section correspondantes dans leurs fichiers.
bos@103: 
bos@103: \begin{figure}[ht]
bos@103:   \centering
bos@103:   \grafix{kdiff3}
belaran@953:   \caption{Utilisation de  \command{kdiff3} pour fusionner différents versions
belaran@953:   d'un fichier.}
bos@103:   \label{fig:tour-merge:kdiff3}
bos@103: \end{figure}
bos@103: 
belaran@953: Pour chaque portion de fichier posant problème, nous pouvons choisir 
belaran@954: de résoudre le le conflit en utilisant en utilisant une combinaison 
belaran@953: de texte depuis la version de base, la notre, ou la leur. Nous pouvons 
belaran@953: aussi éditer manuellement les fichiers à tous moments, si c'est
belaran@953: nécessaire.
belaran@953: 
belaran@953: Il y a \emph{beaucoup} d'outils de fusion disponibles, bien trop pour
belaran@954: en parler de tous ici. Leurs disponibilités varient selon les plate formes
belaran@954: ainsi que leurs avantages et inconvénients. La plupart sont optimisé pour
belaran@953: la fusion de fichier contenant un texte plat, certains sont spécialisé
belaran@954: dans un format de fichier précis (généralement XML).
belaran@954: 
belaran@954: \subsection{A worked example} %TODO: Find a translation for this !
belaran@954: 
belaran@954: Dans cet exemple, nous allons reproduire la modification de l'historique
belaran@954: du fichier de la figure~\ref{fig:tour-merge:conflict} ci dessus. Commençons
belaran@954: par créer un dépôt avec une version de base de notre document.
belaran@954: 
bos@103: \interaction{tour-merge-conflict.wife}
belaran@954: Créons un clone de ce dépôt et faisons une modification dans le fichier.
bos@103: \interaction{tour-merge-conflict.cousin}
belaran@954: Et un autre clone, pour simuler que quelqu'un d'autre effectuer une
belaran@954: modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare
belaran@954: de devoir effectuer des \textit{merge} avec vos propres travaux quand 
belaran@954: vous isoler les tâches dans des dépôts distincts. En effet, vous 
belaran@954: aurez alors à trouver et résoudre certains conflits).
bos@103: \interaction{tour-merge-conflict.son}
belaran@954: Maintenant que ces deux versions différentes du même fichier sont 
belaran@954: créées, nous allons configurer l'environnement approprié pour exécuter 
belaran@954: notre \textit{merge}.
bos@103: \interaction{tour-merge-conflict.pull}
bos@103: 
belaran@954: Dans cette exemple, je n'utiliserais pas la commande Mercurial
belaran@954: habituelle \command{hgmerge} pour effectuer le \textit{merge},
belaran@954: car il me faudrait abandonner ce joli petit exemple automatisé
belaran@954: pour utiliser un outil graphique. À la place, je vais définir
belaran@954: la variable d'environnement \envar{HGMERGE} pour indiquer à 
belaran@954: Mercurial d'utiliser la commande non-interactive \command{merge}.
belaran@954: Cette dernière est embarqué par de nombreux systèmes ``à la Unix''.
belaran@954: Si vous exécuter cet exemple depuis votre ordinateur, ne vous
belaran@954: occupez pas de définir \envar{HGMERGE}.
bos@103: \interaction{tour-merge-conflict.merge}
belaran@954: Parce que \command{merge} ne peut pas résoudre les modifications
belaran@954: conflictuelles, il laisse des \emph{marqueurs de différences}
belaran@954: \footnote{NdT: Oui, je traduis \textit{merge markers} par un sens
belaran@954: inverse en Français, mais je pense vraiment que c'est plus clair 
belaran@954: comme ça...} à l'intérieur du fichier qui a des conflits, indiquant
belaran@954: clairement quelles lignes sont en conflits, et si elles viennent de
belaran@954: notre fichier ou du fichier externe.
belaran@954: 
belaran@954: Mercurial peut distinguer, à la manière dont la commande \command{merge}
belaran@954: se termine, qu'elle n'a pas été capable d'effectuer le \textit{merge},
belaran@954: alors il nous indique qu'il faut devons effectuer de nouveau cette
belaran@954: opération. Ceci peut être très utile si, par exemple, nous exécutons un
belaran@954: outil graphique de fusion et que nous le quittons sans se rendre compte
belaran@954: qu'il reste des conflits ou simplement par erreur.
belaran@954: 
belaran@954: Si le \textit{merge} automatique ou manuel échoue, il n'y a rien pour
belaran@954: nous empêcher de ``corriger le tir'' en modifiant nous même les fichiers,
belaran@954: et enfin effectuer le \textit{commit} du fichier:
bos@103: \interaction{tour-merge-conflict.commit}
bos@103: 
belaran@959: \section{Simplifier l'enchaînement de \textit{pull-merge-commit} }
bos@224: \label{sec:tour-merge:fetch}
bos@102: 
belaran@959: Le processus de fusion des modifications, comme indiqué ci dessus,
belaran@959: est simple, mais il requiert d'exécuter 3 commandes de suite.
bos@102: \begin{codesample2}
bos@102:   hg pull
bos@102:   hg merge
bos@102:   hg commit -m 'Merged remote changes'
bos@102: \end{codesample2}
belaran@959: Dans le cas d'un \textit{commit} final, vous avez aussi besoin
belaran@959: de saisir un message, qui sera presque systématiquemetn un texte
belaran@959: sans grand interêt, juste pour mentionner qu'un \textit{merge} a
belaran@959: eu lieu.
belaran@959: 
belaran@959: Il serait agréable de pouvoir réduire le nombre d'étape nécessaire.
belaran@959: En effet, Mercurial est distribué avec une extension nommée \hg{fetch}
belaran@959: qui le permet.
belaran@959: 
belaran@959: Mercurial fournit un méchanisme flexible d'extension qui permet à 
belaran@959: quiquonque d'ajouter des fonctionnalités, tout en conservant le 
belaran@959: coeur de Mercurial relativement petit et facile à maintenir. Quelques
belaran@959: extensions ajoutent des nouvelles commandes que vous pouvez utiliser
belaran@959: depuis votre terminal, alors que d'autres opèrent ``dans les coulisses'',
belaran@959: pour ajouter par exemple des fonctionnalités au server.
belaran@959: 
belaran@959: L'extension \hgext{fetch} ajoute une nouvelle commande appelée, sans
belaran@959: surprise, \hgcmd{fetch}. Cette extension agit comme une combinaison
belaran@959: de \hgcmd{pull}, \hgupdate{update} et \hgcmd{merge}. Elle commence
belaran@959: par faire un \textit{pull} des modifications depuis un autre dépôt dans
belaran@959: le dépôt local. Si elle trouve des modifications ajoutés à la \textit{head}
belaran@959: du dépôt, elle commencera à effectuer le \textit{merge}, puis elle 
belaran@959: déclenchera le \textit{commit} du résultat avec un message généré
belaran@959: automatiquement. Si aucune nouvell \textit{head} n'est ajouté elle
belaran@959: met à jour l'espace de travail avec le nouveau \textit{tip}.
belaran@959: 
belaran@959: Activé l'extension \hgext{fetch} est très facile. Ouvrez le fichier
belaran@959: \sfilename{.hgrc}, et, soit allez dans la section \rcsection{extensions}
belaran@959: ou créer une section \rcsection{extensions} si elle absente. Ensuite, 
belaran@959: ajoutée une ligne qui contient simplement ``\Verb+fetch +''.
bos@102: \begin{codesample2}
bos@102:   [extensions]
bos@102:   fetch =
bos@102: \end{codesample2}
belaran@959: (Normalement, à droite du signe ``\texttt{=}'' on verrait apparaître
belaran@959: l'adresse de l'extension sur le système, mais comme \hgext{fetch} est
belaran@959: une extension distribué avec Mercurial, ce dernier sait où la 
belaran@959: retrouver.)
bos@102: 
bos@84: %%% Local Variables: 
bos@84: %%% mode: latex
bos@84: %%% TeX-master: "00book"
bos@84: %%% End: 




