<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>#gitfr</title>
    <link>http://www.gitfr.net/blog</link>
    <description>Projet pour la promotion du bien et la destruction du mal</description>
    <pubDate>Sun, 15 Apr 2012 21:04:43 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Comportement par défaut du git push</title>
      <link>http://www.gitfr.net/blog/2011/12/11/comportement-par-defaut-du-git-push</link>
      <pubDate>Sun, 11 Dec 2011 23:19:00 CET</pubDate>
      <category><![CDATA[git-pull]]></category>
      <category><![CDATA[git-push]]></category>
      <category><![CDATA[git]]></category>
      <category><![CDATA[refspec]]></category>
      <category><![CDATA[configuration]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/12/11/comportement-par-defaut-du-git-push</guid>
      <description>Comportement par défaut du git push</description>
      <content:encoded><![CDATA[<p>Git est hautement configurable, avec des dizaines de variables possibles
dans le fichier de configuration, la longueur de l'aide de l'option config
donnant d'ailleurs quelques vertiges. Au lieu de faire un (très) long billet
sur les différentes possibilités de configuration, je vous propose plutôt
des billets courts sur un thème particulier de la configuration.</p>
<p>Pour ce premier billet, je souhaite aborder le comportement de Git lors d'un
push. Ce qui ont suivis l'atelier Git à Bordeaux ne seront pas étonnés par ce
choix : ayant totalement oublié cette option, je ne comprenais pas que ma
machine ne se comporte pas comme ceux des participants à l'atelier (ma
crédibilité en tant qu'expert Git en a sérieusement pâti :).</p>
<p>Commençons par lire le manuel sur l'option push.default :</p>
<p>Defines the action git push should take if no refspec is given on the command
line, no refspec is configured in the remote, and no refspec is implied by any
of the options given on the command line. Possible values are: </p>
<ul>
<li>nothing - do not push anything.</li>
<li>matching - push all matching branches. All branches having the same name in
both ends are considered to be matching. This is the default.</li>
<li>upstream - push the current branch to its upstream branch.</li>
<li>tracking - deprecated synonym for upstream.</li>
<li>current - push the current branch to a branch of the same name.</li>
</ul>
<p>Comme vous pouvez le constater, si aucun refspec n'est fourni (en ligne de
commande ou par configuration) le comportement par défaut est de pousser
toutes les branches qui existent en local et sur le serveur. Cela veut donc
dire que si vous tapez la commande <code>git push</code>, vous allez mettre à jour sur le
serveur toutes les branches que vous avez modifié en local, ce qui est rarement
souhaitable. Il faudra indiquer le refspec complet <code>git push origin mybranch</code>
pour éviter cela.</p>
<p>C'est pour cette raison que je configure Git avec l'option upstream :</p>
<blockquote>
<p>$ git config --global push.default upstream</p>
</blockquote>
<p>2 avantages immédiats :</p>
<ul>
<li>Il ne pousse que la branche courante.</li>
<li>Il m'oblige à faire un <em>tracking</em>, ce qui est bien utile.</li>
</ul>
<p>Maintenant, si vous tentez de pousser la branche <em>test</em> avec la commande
<code>git push</code> sans tracking préalable, Git vous répond :</p>
<blockquote>
<p>fatal: The current branch test has no upstream branch.
To push the current branch and set the remote as upstream, use</p>
<p>git push --set-upstream origin test</p>
</blockquote>
<p>Suivez le conseil de Git en tapant la commande ci dessus pour suivre votre
la branche distante test sur origin avec votre branche locale test. Vous verrez
immédiatement un changement sur votre shell avec l'information <strong>u=</strong>, qui 
indique que vos deux branches sont synchronisées.</p>
<h2>Rappel sur le tracking</h2>
<p>Le tracking consiste à <em>associer</em> une branche locale et une branche distante
(dite <em>upstream</em> dans la terminologie Git), ce qui informe Git de la branche
distante à utiliser lors d'un <code>git pull</code>. Si vous ne comprenez pas pourquoi
vous n'êtes pas plus souvent confronté à cette notion de tracking, c'est tout
simplement que Git le fait pour vous la plupart du temps :</p>
<ul>
<li>Git suit la branche master lors d'un clone.</li>
<li>Git suit la branche que vous venez de créer si celle ci existe déjà sur le
   serveur </li>
</ul>
<p>C'est donc (la plupart du temps) dans le cas ou créer une nouvelle branche en
locale sans existance préalable sur le serveur que vous devez explicitement
faire cette association.</p>]]></content:encoded>
    </item>
    <item>
      <title>Comprendre le refspec</title>
      <link>http://www.gitfr.net/blog/2011/10/09/comprendre-le-refspec</link>
      <pubDate>Sun, 09 Oct 2011 17:53:00 CEST</pubDate>
      <category><![CDATA[git]]></category>
      <category><![CDATA[refspec]]></category>
      <category><![CDATA[git-push]]></category>
      <category><![CDATA[git-pull]]></category>
      <category><![CDATA[git-fetch]]></category>
      <category><![CDATA[git-remote]]></category>
      <category><![CDATA[git-clone]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/10/09/comprendre-le-refspec</guid>
      <description>Comprendre le refspec</description>
      <content:encoded><![CDATA[<p>Si vous avez déjà travaillé avec un dépôt distant, vous savez comment se
comporte Git : il vous indique les références du dépôt distant en
ajoutant l'espace de nom <code>origin</code> (dans le cas d'un clone) ou le nom que
vous lui donnez si vous l'avez ajouter avec la commande <code>git-remote add</code>.
Mais pourquoi Git a t'il ce comportement ?</p>
<p>La réponse se trouve dans le <strong>refspec</strong>, nom un peu barbare, qui pourrait
se traduire en bon français par : «comment je gère les dépôts distants
chef ?». Soit ce refspec est spécifié en ligne de commande au moment
de l'action (fetch ou push), soit elle se trouve dans le fichier de
configuration du dépôt.</p>
<h2>Petit rappel</h2>
<p>Il est <strong>impossible</strong> de modifer directement un dépôt distant, vous devez
obligatoirement modifier le dépôt local puis pousser vos commits
sur le dépôt distant. Autrement dit, modifier un dépôt consiste à
synchroniser les bases de données.</p>
<p>C'est là que le refspec rentre en jeu, il permet de définir les branches
concernées au moment de la synchronisation.</p>
<h2>Clonage</h2>
<p>Si vous joué rarement avec le refspec, c'est que vous travaillé la plupart
du temps sur un dépôt local que vous avez créé avec la commande <code>git-clone</code>.
Ce dernier génère un refspec générique suffisant. Editez le fichier
<code>.git/config</code> et vous verrez ces lignes :</p>
<pre><code>[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = /path/to/repos
</code></pre>
<p>Une explication rapide : le dépôt distant qui se trouve à l'url spécifié
s'appelle en local <em>origin</em> et on associe à chaque référence de branche
du dépôt distant une référence de branche locale préfixée par <em>origin</em>.</p>
<p>Mais un deuxième rappel avant d'aller plus loin.</p>
<h2>Structure des références</h2>
<p>La gestion des références est d'une simplicité affligeante. Tout est contenu
dans le répertoire <code>.git/refs</code>. Un répertoire étant un espace de nom, un
fichier une référence. Pour fonctionner, Git à besoin de 2 espaces de nom
bien particulier :</p>
<ul>
<li>
<p><em>heads</em> pour stocker les références locales de type branche.</p>
</li>
<li>
<p><em>tags</em> pour stocker les références locales de type tag.</p>
</li>
</ul>
<p>Vous ne faites pas attention à ces répertoires en temps normal car les
commandes Git savent pertinamment que les références sont à ces endroits
précis.</p>
<h2>Explication</h2>
<p>Si je vous dis qu'un refspec s'écrit toujours <code>source:destination</code>, la ligne
suivante ne doit pas vous poser trop de soucis. Examinons la de plus prêt :</p>
<blockquote>
<p>fetch = +refs/heads/<em>:refs/remotes/origin/</em></p>
</blockquote>
<ul>
<li>
<p>Le mot clé fetch indique que c'est lu à chaque utilisation de cette commande
  Le sens de transfert est du dépôt distant (la source) vers le dépôt local
  (la destination).</p>
</li>
<li>
<p>Le symbole <code>+</code> signifie qu'on autorise les récuparation <em>non fast-forword</em>.</p>
</li>
<li>
<p>le reste de la ligne est assez explicite. Pour toutes les références se
  trouvant dans le chemin <code>refs/heads/</code> dans le dépôt distant, on associe une
  référence dans le chemin <code>refs/remotes/origin/</code> dans le dépot local. </p>
</li>
</ul>
<p>Si par exemple le dépôt distant a 3 branches qui se nomment <code>riri</code>, <code>fifi</code> et
<code>loulou</code>, vous aurez donc en local 3 branches <code>origin/riri</code>, <code>origin/fifi</code> et
<code>origin/loulou</code>.</p>
<h2>Importance du refspec</h2>
<p>Il est important de maitriser le refspec car tout part de là, c'est en fonction
des références à récupérer ou à pousser que Git détermine les objets à 
synchroniser. Si je demande à récupérer toutes les références distantes, je demande
implicitement tous les objets accessibles par ces références, donc toute la base.
Au contraire, si le refspec implique des références précises, seuls les objets
nécessaires à ces références seront impactés.</p>
<h2>Ajout d'un dépôt distant</h2>
<p>La commande <code>git-remote</code> permet de manipuler les dépôts distants, avec
notamment la commande <code>git-remote add</code> pour en ajouter. Ce dernier se comporte
comme la commande <code>git-clone</code>, en configurant le refspec au plus
large (toutes les références donc).</p>
<h2>refspec en ligne de commande</h2>
<p>Le refspec se manipule aussi en ligne de commande, ce qui permet de passer
outre la configuration ou d'utiliser Git sans configuration préalable.</p>
<p>Quelques exemples :</p>
<blockquote>
<p>git fetch origin +pu:tmp</p>
</blockquote>
<p>Récupére la référence <em>pu</em> et les objets associés et appeles la <em>tmp</em>
en local.</p>
<blockquote>
<p>git push HEAD:master</p>
</blockquote>
<p>Pousse la branche actuelle sur la branche distante master.</p>
<blockquote>
<p>git push origin master:refs/heads/qa/experimental</p>
</blockquote>
<p>Pousse la branche master sur la branche distante expérimental. Nous
utilisons ici le nom complet de la référence. </p>
<h2>Le refspec :</h2>
<p>Refspec particulier qui indique de mettre à jour toutes les branches
distantes existantes qui ont un nom identique aux branches locales. C'est en
fait le refspec utilisé par défaut au push quand nous en spécifions pas.</p>
<h2>Effacer une référence distante</h2>
<p>Autre cas particulier. Si vous souhaitez par exemple effacer la référence
distante test si vous souhaitez effacer une référence distante,
il faut taper :</p>
<blockquote>
<p>git push :test</p>
</blockquote>
<p>Autrement dit, je pousse une référence vide sur la référence test.</p>
<h2>Associer branche locale / branche distante</h2>
<p>Comme nous l'avons vu, le refspec en ligne de commande permet d'associer
temporairement une branche locale et une branche sur le dépôt distant. Mais
comment associer ces deux branches dans la configuration et éviter ainsi de
le répêter à chaque fois ? Tout se situe encore dans le fichier
<code>.git/config</code> du dépôt local :</p>
<pre><code>[branch "master"]                                                                                   
remote = origin                                                                             
merge = refs/heads/master
</code></pre>
<p>Qui veut dire : associe la branche master du dépôt <em>origin</em> à ma référence
locale <code>master</code>. Et oh surprise, la ligne est utilisée pour la commande
<code>merge</code>, ce qui est tout à faire logique. la commande <code>git-fetch</code> ne fait que
récupérer les objets et associer des références. Si vous voulez mélanger
votre travail avec le travail distant, il faut donc faire un merge.</p>
<p>Petite remarque, c'est uniquement quand vous avez spécifiée une branche
distante (<em>upstream</em> dans le vocabulaire Git) que votre shell vous indiquera
si vous avez des commits en avance ou en retard (logique non ?). Cela arrive
quand vous avez créé une nouvelle branche locale mais sans l'avoir poussée
sur le dépôt distant.</p>
<h2>pull = fetch + merge</h2>
<p>Vous devez maintenant comprendre pourquoi on dit que la commande <code>git-pull</code>
n'est en fait qu'un raccouri pour :</p>
<ol>
<li>git-fetch</li>
<li>git-merge origin/master</li>
</ol>
<h2>A quoi sert le fetch ?</h2>
<p>La commande <code>git-pull</code> est une commodité car c'est dans 90% des cas ce que l'on
souhaite faire. Mais le merge est seulement une des nombreuses possibilités que
vous offre Git. La beauté du travail collaboratif avec Git est que cette branche
distante est en fait une branche locale (c'est uniquement la référence qui est
distante), et que vous pouvez donc faire ce que vous souhaitez avec, comme
cherrypicker des commits, faire un rebase... ou un merge. C'est à vous de voir
ce qui vous intéresse. C'est la raison pour laquelle des personnes disent sur
le Net de ne pas faire que des fetch.</p>
<p>Notez qu'il existe l'option <code>--rebase</code> pour rebaser automatiquement votre
branche locale sur la branche distante (ce qui est la aussi un scénario de
base).</p>
<h2>Conclusion</h2>
<p>Je pense avoir fait le tour. Comme d'habitude je vous conseille de de lire
les pages du manuel (git-clone, git-fetch, git-push et git-pull).</p>]]></content:encoded>
    </item>
  </channel>
</rss>

