<?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:42 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Git 1.7.10 publiée</title>
      <link>http://www.gitfr.net/blog/2012/04/15/git-1.7.10-publiee</link>
      <pubDate>Sun, 15 Apr 2012 22:52:00 CEST</pubDate>
      <category><![CDATA[release]]></category>
      <category><![CDATA[git]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2012/04/15/git-1.7.10-publiee</guid>
      <description>Git 1.7.10 publiée</description>
      <content:encoded><![CDATA[<p>Pas mal de petites changements dans cette version 1.7.10 sortie le 10 avril. Je
voulais initialement tester cette version avant de publier l'annonce mais je
n'ai pas eu le cou^H^H^Htemps :(. Mais rapidement de ce qu'ai pu voir :</p>
<ul>
<li>
<p>gitk a pas mal de petites évolutions.</p>
</li>
<li>
<p>Un éditeur s'ouvre lors d'un <code>git-commit</code> pour pousser les gens à expliquer
  les changements.</p>
</li>
<li>
<p>On peut cloner qu'un répertoire.</p>
</li>
</ul>
<p>N'hésitez pas comme d'habitude à commenter ce billet si vous voyez des 
changements intéressants dans votre façon de travailler avec Git.</p>
<h2>Le changelog</h2>
<ul>
<li>
<p>various "gitk" updates.</p>
</li>
<li>
<p>Teams for localizing the messages from the Porcelain layer of
  commands are starting to form, thanks to Jiang Xin who volunteered
  to be the localization coordinator.  Translated messages for
  simplified Chinese, Swedish and Portuguese are available.</p>
</li>
<li>
<p>The configuration mechanism learned an "include" facility; an
  assignment to the include.path pseudo-variable causes the named
  file to be included in-place when Git looks up configuration
  variables.</p>
</li>
<li>
<p>A content filter (clean/smudge) used to be just a way to make the
  recorded contents "more useful", and allowed to fail; a filter can
  now optionally be marked as "required".</p>
</li>
<li>
<p>Options whose names begin with "--no-" (e.g. the "--no-verify"
  option of the "git commit" command) can be negated by omitting
  "no-" from its name, e.g. "git commit --verify".</p>
</li>
<li>
<p>"git am" learned to pass "-b" option to underlying "git mailinfo", so
  that a bracketed string other than "PATCH" at the beginning can be kept.</p>
</li>
<li>
<p>"git clone" learned "--single-branch" option to limit cloning to a
  single branch (surprise!); tags that do not point into the history
  of the branch are not fetched.</p>
</li>
<li>
<p>"git clone" learned to detach the HEAD in the resulting repository
  when the user specifies a tag with "--branch" (e.g., "--branch=v1.0").
  Clone also learned to print the usual "detached HEAD" advice in such
  a case, similar to "git checkout v1.0".</p>
</li>
<li>
<p>When showing a patch while ignoring whitespace changes, the context
  lines are taken from the postimage, in order to make it easier to
  view the output.</p>
</li>
<li>
<p>"git diff --stat" learned to adjust the width of the output on
  wider terminals, and give more columns to pathnames as needed.</p>
</li>
<li>
<p>"diff-highlight" filter (in contrib/) was updated to produce more
  aesthetically pleasing output.</p>
</li>
<li>
<p>"fsck" learned "--no-dangling" option to omit dangling object
  information.</p>
</li>
<li>
<p>"git log -G" and "git log -S" learned to pay attention to the "-i"
  option.  With "-i", "log -G" ignores the case when finding patch
  hunks that introduce or remove a string that matches the given
  pattern.  Similarly with "-i", "log -S" ignores the case when
  finding the commit the given block of text appears or disappears
  from the file.</p>
</li>
<li>
<p>"git merge" in an interactive session learned to spawn the editor
  by default to let the user edit the auto-generated merge message,
  to encourage people to explain their merges better. Legacy scripts
  can export GIT_MERGE_AUTOEDIT=no to retain the historical behavior.
  Both "git merge" and "git pull" can be given --no-edit from the
  command line to accept the auto-generated merge message.</p>
</li>
<li>
<p>The advice message given when the user didn't give enough clue on
  what to merge to "git pull" and "git merge" has been updated to
  be more concise and easier to understand.</p>
</li>
<li>
<p>"git push" learned the "--prune" option, similar to "git fetch".</p>
</li>
<li>
<p>The whole directory that houses a top-level superproject managed by
  "git submodule" can be moved to another place.</p>
</li>
<li>
<p>"git symbolic-ref" learned the "--short" option to abbreviate the
  refname it shows unambiguously.</p>
</li>
<li>
<p>"git tag --list" can be given "--points-at <object>" to limit its
  output to those that point at the given object.</p>
</li>
<li>
<p>"gitweb" allows intermediate entries in the directory hierarchy
  that leads to a project to be clicked, which in turn shows the
  list of projects inside that directory.</p>
</li>
<li>
<p>"gitweb" learned to read various pieces of information for the
  repositories lazily, instead of reading everything that could be
  needed (including the ones that are not necessary for a specific
  task).</p>
</li>
<li>
<p>Project search in "gitweb" shows the substring that matched in the
  project name and description highlighted.</p>
</li>
<li>
<p>HTTP transport learned to authenticate with a proxy if needed.</p>
</li>
<li>
<p>A new script "diffall" is added to contrib/; it drives an
  external tool to perform a directory diff of two Git revisions
  in one go, unlike "difftool" that compares one file at a time.</p>
</li>
<li>
<p>Improved handling of views, labels and branches in "git-p4" (in contrib).</p>
</li>
<li>
<p>"git-p4" (in contrib) suffered from unnecessary merge conflicts when
  p4 expanded the embedded $RCS$-like keywords; it can be now told to
  unexpand them.</p>
</li>
<li>
<p>Some "git-svn" updates.</p>
</li>
<li>
<p>"vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and
  support incremental imports.</p>
</li>
<li>
<p>"git difftool/mergetool" learned to drive DeltaWalker.</p>
</li>
<li>
<p>Unnecessary calls to parse_object() "git upload-pack" makes in
  response to "git fetch", have been eliminated, to help performance
  in repositories with excessive number of refs.</p>
</li>
<li>
<p>Recursive call chains in "git index-pack" to deal with long delta
  chains have been flattened, to reduce the stack footprint.</p>
</li>
<li>
<p>Use of add_extra_ref() API is now gone, to make it possible to
  cleanly restructure the overall refs API.</p>
</li>
<li>
<p>The command line parser of "git pack-objects" now uses parse-options
  API.</p>
</li>
<li>
<p>The test suite supports the new "test_pause" helper function.</p>
</li>
<li>
<p>Parallel to the test suite, there is a beginning of performance
  benchmarking framework.</p>
</li>
<li>
<p>t/Makefile is adjusted to prevent newer versions of GNU make from
  running tests in seemingly random order.</p>
</li>
<li>
<p>The code to check if a path points at a file beyond a symbolic link
  has been restructured to be thread-safe.</p>
</li>
<li>
<p>When pruning directories that has become empty during "git prune"
  and "git prune-packed", call closedir() that iterates over a
  directory before rmdir() it.</p>
</li>
<li>
<p>Build with NO_PERL_MAKEMAKER was broken and Git::I18N did not work
  with versions of Perl older than 5.8.3.
  (merge 5eb660e ab/perl-i18n later to maint).</p>
</li>
<li>
<p>"git tag -s" honored "gpg.program" configuration variable since
  1.7.9, but "git tag -v" and "git verify-tag" didn't.
  (merge a2c2506 az/verify-tag-use-gpg-config later to maint).</p>
</li>
<li>
<p>"configure" script learned to take "--with-sane-tool-path" from the
  command line to record SANE_TOOL_PATH (used to avoid broken platform
  tools in /usr/bin) in config.mak.autogen.  This may be useful for
  people on Solaris who have saner tools outside /usr/xpg[46]/bin.</p>
</li>
<li>
<p>zsh port of bash completion script needed another workaround.</p>
</li>
<li>
<p>git-gui updated to 0.16.0.</p>
</li>
<li>
<p>git-p4 (in contrib/) updates.</p>
</li>
<li>
<p>Git uses gettext to translate its most common interface messages
  into the user's language if translations are available and the
  locale is appropriately set. Distributors can drop new PO files
  in po/ to add new translations.</p>
</li>
<li>
<p>The code to handle username/password for HTTP transactions used in
  "git push" &amp; "git fetch" learned to talk "credential API" to
  external programs to cache or store them, to allow integration with
  platform native keychain mechanisms.</p>
</li>
<li>
<p>The input prompts in the terminal use our own getpass() replacement
  when possible. HTTP transactions used to ask for the username without
  echoing back what was typed, but with this change you will see it as
  you type.</p>
</li>
<li>
<p>The internals of "revert/cherry-pick" have been tweaked to prepare
  building more generic "sequencer" on top of the implementation that
  drives them.</p>
</li>
<li>
<p>"git rev-parse FETCH_HEAD" after "git fetch" without specifying
  what to fetch from the command line will now show the commit that
  would be merged if the command were "git pull".</p>
</li>
<li>
<p>"git add" learned to stream large files directly into a packfile
  instead of writing them into individual loose object files.</p>
</li>
<li>
<p>"git checkout -B <current branch> <elsewhere>" is a more intuitive
  way to spell "git reset --keep <elsewhere>".</p>
</li>
<li>
<p>"git checkout" and "git merge" learned "--no-overwrite-ignore" option
  to tell Git that untracked and ignored files are not expendable.</p>
</li>
<li>
<p>"git commit --amend" learned "--no-edit" option to say that the
  user is amending the tree being recorded, without updating the
  commit log message.</p>
</li>
<li>
<p>"git commit" and "git reset" re-learned the optimization to prime
  the cache-tree information in the index, which makes it faster to
  write a tree object out after the index entries are updated.</p>
</li>
<li>
<p>"git commit" detects and rejects an attempt to stuff NUL byte in
  the commit log message.</p>
</li>
<li>
<p>"git commit" learned "-S" to GPG-sign the commit; this can be shown
  with the "--show-signature" option to "git log".</p>
</li>
<li>
<p>fsck and prune are relatively lengthy operations that still go
  silent while making the end-user wait. They learned to give progress
  output like other slow operations.</p>
</li>
<li>
<p>The set of built-in function-header patterns for various languages
  knows MATLAB.</p>
</li>
<li>
<p>"git log --format='<format>'" learned new %g[nNeE] specifiers to
  show information from the reflog entries when walking the reflog
  (i.e. with "-g").</p>
</li>
<li>
<p>"git pull" can be used to fetch and merge an annotated/signed tag,
  instead of the tip of a topic branch. The GPG signature from the
  signed tag is recorded in the resulting merge commit for later
  auditing.</p>
</li>
<li>
<p>"git log" learned "--show-signature" option to show the signed tag
  that was merged that is embedded in the merge commit. It also can
  show the signature made on the commit with "git commit -S".</p>
</li>
<li>
<p>"git branch --edit-description" can be used to add descriptive text
  to explain what a topic branch is about.</p>
</li>
<li>
<p>"git fmt-merge-msg" learned to take the branch description into
  account when preparing a merge summary that "git merge" records
  when merging a local branch.</p>
</li>
<li>
<p>"git request-pull" has been updated to convey more information
  useful for integrators to decide if a topic is worth merging and
  what is pulled is indeed what the requestor asked to pull,
  including:</p>
</li>
<li>
<p>the tip of the branch being requested to be merged;</p>
</li>
<li>the branch description describing what the topic is about;</li>
<li>
<p>the contents of the annotated tag, when requesting to pull a tag.</p>
</li>
<li>
<p>"git pull" learned to notice 'pull.rebase' configuration variable,
  which serves as a global fallback for setting 'branch.<name>.rebase'
  configuration variable per branch.</p>
</li>
<li>
<p>"git tag" learned "--cleanup" option to control how the whitespaces
  and empty lines in tag message are cleaned up.</p>
</li>
<li>
<p>"gitweb" learned to show side-by-side diff.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Git 1.7.9 publiée</title>
      <link>http://www.gitfr.net/blog/2012/01/28/git-1.7.9-publiee</link>
      <pubDate>Sat, 28 Jan 2012 21:13:00 CET</pubDate>
      <category><![CDATA[release]]></category>
      <category><![CDATA[git]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2012/01/28/git-1.7.9-publiee</guid>
      <description>Git 1.7.9 publiée</description>
      <content:encoded><![CDATA[<p>La version 1.7.9 est sortie le 27 janvier avec plusieurs évolutions
intéressantes : </p>
<ul>
<li>
<p>Un meilleur support des gros fichiers (Git n'étant pas réputé pour ça).</p>
</li>
<li>
<p>La signature des commits, qui fait suite au piratage de la machine qui 
  héberge le dépôt Git du projet Linux de Linus Torvalds.</p>
</li>
<li>
<p>L'internationalisation est maintenant activée (honte à moi, toujours pas
  démarré le projet de traduction en Français).</p>
</li>
<li>
<p>La possibilité d'ajouter une description à une branche.</p>
</li>
<li>
<p>L'option <code>--no-edit</code> quand on amende un commit. </p>
</li>
</ul>
<p>Je vous laisse comme d'habitude lire le changelog mais je trouve cette version
bien excitente ! J'attends la mise à jour sur ma machine pour faire quelques
tests.</p>
<h2>Le changelog</h2>
<ul>
<li>
<p>gitk updates accumulated since early 2011.</p>
</li>
<li>
<p>git-gui updated to 0.16.0.</p>
</li>
<li>
<p>git-p4 (in contrib/) updates.</p>
</li>
<li>
<p>Git uses gettext to translate its most common interface messages
  into the user's language if translations are available and the
  locale is appropriately set. Distributors can drop new PO files
  in po/ to add new translations.</p>
</li>
<li>
<p>The code to handle username/password for HTTP transactions used in
  "git push" &amp; "git fetch" learned to talk "credential API" to
  external programs to cache or store them, to allow integration with
  platform native keychain mechanisms.</p>
</li>
<li>
<p>The input prompts in the terminal use our own getpass() replacement
  when possible. HTTP transactions used to ask for the username without
  echoing back what was typed, but with this change you will see it as
  you type.</p>
</li>
<li>
<p>The internals of "revert/cherry-pick" have been tweaked to prepare
  building more generic "sequencer" on top of the implementation that
  drives them.</p>
</li>
<li>
<p>"git rev-parse FETCH_HEAD" after "git fetch" without specifying
  what to fetch from the command line will now show the commit that
  would be merged if the command were "git pull".</p>
</li>
<li>
<p>"git add" learned to stream large files directly into a packfile
  instead of writing them into individual loose object files.</p>
</li>
<li>
<p>"git checkout -B <current branch> <elsewhere>" is a more intuitive
  way to spell "git reset --keep <elsewhere>".</p>
</li>
<li>
<p>"git checkout" and "git merge" learned "--no-overwrite-ignore" option
  to tell Git that untracked and ignored files are not expendable.</p>
</li>
<li>
<p>"git commit --amend" learned "--no-edit" option to say that the
  user is amending the tree being recorded, without updating the
  commit log message.</p>
</li>
<li>
<p>"git commit" and "git reset" re-learned the optimization to prime
  the cache-tree information in the index, which makes it faster to
  write a tree object out after the index entries are updated.</p>
</li>
<li>
<p>"git commit" detects and rejects an attempt to stuff NUL byte in
  the commit log message.</p>
</li>
<li>
<p>"git commit" learned "-S" to GPG-sign the commit; this can be shown
  with the "--show-signature" option to "git log".</p>
</li>
<li>
<p>fsck and prune are relatively lengthy operations that still go
  silent while making the end-user wait. They learned to give progress
  output like other slow operations.</p>
</li>
<li>
<p>The set of built-in function-header patterns for various languages
  knows MATLAB.</p>
</li>
<li>
<p>"git log --format='<format>'" learned new %g[nNeE] specifiers to
  show information from the reflog entries when walking the reflog
  (i.e. with "-g").</p>
</li>
<li>
<p>"git pull" can be used to fetch and merge an annotated/signed tag,
  instead of the tip of a topic branch. The GPG signature from the
  signed tag is recorded in the resulting merge commit for later
  auditing.</p>
</li>
<li>
<p>"git log" learned "--show-signature" option to show the signed tag
  that was merged that is embedded in the merge commit. It also can
  show the signature made on the commit with "git commit -S".</p>
</li>
<li>
<p>"git branch --edit-description" can be used to add descriptive text
  to explain what a topic branch is about.</p>
</li>
<li>
<p>"git fmt-merge-msg" learned to take the branch description into
  account when preparing a merge summary that "git merge" records
  when merging a local branch.</p>
</li>
<li>
<p>"git request-pull" has been updated to convey more information
  useful for integrators to decide if a topic is worth merging and
  what is pulled is indeed what the requestor asked to pull,
  including:</p>
</li>
<li>
<p>the tip of the branch being requested to be merged;</p>
</li>
<li>the branch description describing what the topic is about;</li>
<li>
<p>the contents of the annotated tag, when requesting to pull a tag.</p>
</li>
<li>
<p>"git pull" learned to notice 'pull.rebase' configuration variable,
   which serves as a global fallback for setting 'branch.<name>.rebase'
   configuration variable per branch.</p>
</li>
<li>
<p>"git tag" learned "--cleanup" option to control how the whitespaces
   and empty lines in tag message are cleaned up.</p>
</li>
<li>
<p>"gitweb" learned to show side-by-side diff.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <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>Git 1.7.8 publiée</title>
      <link>http://www.gitfr.net/blog/2011/12/11/git-1.7.8-publiee</link>
      <pubDate>Sun, 11 Dec 2011 23:13:00 CET</pubDate>
      <category><![CDATA[release]]></category>
      <category><![CDATA[git]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/12/11/git-1.7.8-publiee</guid>
      <description>Git 1.7.8 publiée</description>
      <content:encoded><![CDATA[<p>La version 1.7.8 est sortie le 2 décembre. Comme vous pouvez constater, le
changelog est assez gros avec surtout de nouvelles options pour plusieurs
commandes et l'habituel lot de corrections.</p>
<h2>Le changelog</h2>
<ul>
<li>
<p>Some git-svn, git-gui, git-p4 (in contrib) and msysgit updates.</p>
</li>
<li>
<p>Updates to bash completion scripts.</p>
</li>
<li>
<p>The build procedure has been taught to take advantage of computed
  dependency automatically when the complier supports it.</p>
</li>
<li>
<p>The date parser now accepts timezone designators that lack minutes
  part and also has a colon between "hh:mm".</p>
</li>
<li>
<p>The contents of the /etc/mailname file, if exists, is used as the
  default value of the hostname part of the committer/author e-mail.</p>
</li>
<li>
<p>"git am" learned how to read from patches generated by Hg.</p>
</li>
<li>
<p>"git archive" talking with a remote repository can report errors
  from the remote side in a more informative way.</p>
</li>
<li>
<p>"git branch" learned an explicit --list option to ask for branches
  listed, optionally with a glob matching pattern to limit its output.</p>
</li>
<li>
<p>"git check-attr" learned "--cached" option to look at .gitattributes
  files from the index, not from the working tree.</p>
</li>
<li>
<p>Variants of "git cherry-pick" and "git revert" that take multiple
  commits learned to "--continue" and "--abort".</p>
</li>
<li>
<p>"git daemon" gives more human readble error messages to clients
  using ERR packets when appropriate.</p>
</li>
<li>
<p>Errors at the network layer is logged by "git daemon".</p>
</li>
<li>
<p>"git diff" learned "--minimal" option to spend extra cycles to come
  up with a minimal patch output.</p>
</li>
<li>
<p>"git diff" learned "--function-context" option to show the whole
  function as context that was affected by a change.</p>
</li>
<li>
<p>"git difftool" can be told to skip launching the tool for a path by
  answering 'n' to its prompt.</p>
</li>
<li>
<p>"git fetch" learned to honor transfer.fsckobjects configuration to
  validate the objects that were received from the other end, just like
  "git receive-pack" (the receiving end of "git push") does.</p>
</li>
<li>
<p>"git fetch" makes sure that the set of objects it received from the
  other end actually completes the history before updating the refs.
  "git receive-pack" (the receiving end of "git push") learned to do the
  same.</p>
</li>
<li>
<p>"git fetch" learned that fetching/cloning from a regular file on the
  filesystem is not necessarily a request to unpack a bundle file; the
  file could be ".git" with "gitdir: <path>" in it.</p>
</li>
<li>
<p>"git for-each-ref" learned "%(contents:subject)", "%(contents:body)"
  and "%(contents:signature)". The last one is useful for signed tags.</p>
</li>
<li>
<p>"git grep" used to incorrectly pay attention to .gitignore files
  scattered in the directory it was working in even when "--no-index"
  option was used. It no longer does this. The "--exclude-standard"
  option needs to be given to explicitly activate the ignore
  mechanism.</p>
</li>
<li>
<p>"git grep" learned "--untracked" option, where given patterns are
   searched in untracked (but not ignored) files as well as tracked
   files in the working tree, so that matches in new but not yet
   added files do not get missed.</p>
</li>
<li>
<p>The recursive merge backend no longer looks for meaningless
  existing merges in submodules unless in the outermost merge.</p>
</li>
<li>
<p>"git log" and friends learned "--children" option.</p>
</li>
<li>
<p>"git ls-remote" learned to respond to "-h"(elp) requests.</p>
</li>
<li>
<p>"mediawiki" remote helper can interact with (surprise!) MediaWiki
  with "git fetch" &amp; "git push".</p>
</li>
<li>
<p>"git merge" learned the "--edit" option to allow users to edit the
  merge commit log message.</p>
</li>
<li>
<p>"git rebase -i" can be told to use special purpose editor suitable
  only for its insn sheet via sequence.editor configuration variable.</p>
</li>
<li>
<p>"git send-email" learned to respond to "-h"(elp) requests.</p>
</li>
<li>
<p>"git send-email" allows the value given to sendemail.aliasfile to begin
  with "~/" to refer to the $HOME directory.</p>
</li>
<li>
<p>"git send-email" forces use of Authen::SASL::Perl to work around
  issues between Authen::SASL::Cyrus and AUTH PLAIN/LOGIN.</p>
</li>
<li>
<p>"git stash" learned "--include-untracked" option to stash away
  untracked/ignored cruft from the working tree.</p>
</li>
<li>
<p>"git submodule clone" does not leak an error message to the UI
  level unnecessarily anymore.</p>
</li>
<li>
<p>"git submodule update" learned to honor "none" as the value for
  submodule.<name>.update to specify that the named submodule should
  not be checked out by default.</p>
</li>
<li>
<p>When populating a new submodule directory with "git submodule init",
  the $GIT_DIR metainformation directory for submodules is created inside
  $GIT_DIR/modules/<name>/ directory of the superproject and referenced
  via the gitfile mechanism. This is to make it possible to switch
  between commits in the superproject that has and does not have the
  submodule in the tree without re-cloning.</p>
</li>
<li>
<p>"gitweb" leaked unescaped control characters from syntax hiliter
  outputs.</p>
</li>
<li>
<p>"gitweb" can be told to give custom string at the end of the HTML
  HEAD element.</p>
</li>
<li>
<p>"gitweb" now has its own manual pages.</p>
</li>
<li>
<p>HTTP transport did not use pushurl correctly, and also did not tell
  what host it is trying to authenticate with when asking for
  credentials.
  (merge deba493 jk/http-auth later to maint).</p>
</li>
<li>
<p>"git blame" was aborted if started from an uncommitted content and
  the path had the textconv filter in effect.
  (merge 8518088 ss/blame-textconv-fake-working-tree later to maint).</p>
</li>
<li>
<p>Adding many refs to the local repository in one go (e.g. "git fetch"
  that fetches many tags) and looking up a ref by name in a repository
  with too many refs were unnecessarily slow.
  (merge 17d68a54d jp/get-ref-dir-unsorted later to maint).</p>
</li>
<li>
<p>Report from "git commit" on untracked files was confused under
  core.ignorecase option.
  (merge 395c7356 jk/name-hash-dirent later to maint).</p>
</li>
<li>
<p>"git merge" did not understand ":/<pattern>" as a way to name a commit.</p>
</li>
<li>
<p>"git push" on the receiving end used to call post-receive and post-update
  hooks for attempted removal of non-existing refs.
  (merge 160b81ed ph/push-to-delete-nothing later to maint).</p>
</li>
<li>
<p>Help text for "git remote set-url" and "git remote set-branches"
  were misspelled.
  (merge c49904e fc/remote-seturl-usage-fix later to maint).
  (merge 656cdf0 jc/remote-setbranches-usage-fix later to maint).</p>
</li>
</ul>]]></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>
    <item>
      <title>Git 1.7.7 publiée</title>
      <link>http://www.gitfr.net/blog/2011/10/01/git-1.7.7-publiee</link>
      <pubDate>Sat, 01 Oct 2011 10:34:00 CEST</pubDate>
      <category><![CDATA[release]]></category>
      <category><![CDATA[git]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/10/01/git-1.7.7-publiee</guid>
      <description>Git 1.7.7 publiée</description>
      <content:encoded><![CDATA[<p>Reprenons la bonne habitude d'annoncer les nouvelles versions. Rien de bien
méchant dans cette 1.7.7, il faut attendre la 1.8 je pense pour des plus gros
changements.</p>
<h2>Le changelog</h2>
<ul>
<li>
<p>The scripting part of the codebase is getting prepared for i18n/l10n.</p>
</li>
<li>
<p>Interix, Cygwin and Minix ports got updated.</p>
</li>
<li>
<p>Various updates to git-p4 (in contrib/), fast-import, and git-svn.</p>
</li>
<li>
<p>Gitweb learned to read from /etc/gitweb-common.conf when it exists,
  before reading from gitweb_config.perl or from /etc/gitweb.conf
  (this last one is read only when per-repository gitweb_config.perl
  does not exist).</p>
</li>
<li>
<p>Various codepaths that invoked zlib deflate/inflate assumed that these
  functions can compress or uncompress more than 4GB data in one call on
  platforms with 64-bit long, which has been corrected.</p>
</li>
<li>
<p>Git now recognizes loose objects written by other implementations that
  use a non-standard window size for zlib deflation (e.g. Agit running on
  Android with 4kb window). We used to reject anything that was not
  deflated with 32kb window.</p>
</li>
<li>
<p>Interaction between the use of pager and coloring of the output has
  been improved, especially when a command that is not built-in was
  involved.</p>
</li>
<li>
<p>"git am" learned to pass the "--exclude=<path>" option through to underlying
  "git apply".</p>
</li>
<li>
<p>You can now feed many empty lines before feeding an mbox file to
  "git am".</p>
</li>
<li>
<p>"git archive" can be told to pass the output to gzip compression and
  produce "archive.tar.gz".</p>
</li>
<li>
<p>"git bisect" can be used in a bare repository (provided that the test
  you perform per each iteration does not need a working tree, of
  course).</p>
</li>
<li>
<p>The length of abbreviated object names in "git branch -v" output
  now honors the core.abbrev configuration variable.</p>
</li>
<li>
<p>"git check-attr" can take relative paths from the command line.</p>
</li>
<li>
<p>"git check-attr" learned an "--all" option to list the attributes for a
  given path.</p>
</li>
<li>
<p>"git checkout" (both the code to update the files upon checking out a
  different branch and the code to checkout a specific set of files) learned
  to stream the data from object store when possible, without having to
  read the entire contents of a file into memory first. An earlier round
  of this code that is not in any released version had a large leak but
  now it has been plugged.</p>
</li>
<li>
<p>"git clone" can now take a "--config key=value" option to set the
  repository configuration options that affect the initial checkout.</p>
</li>
<li>
<p>"git commit <paths>..." now lets you feed relative pathspecs that
  refer to outside your current subdirectory.</p>
</li>
<li>
<p>"git diff --stat" learned a --stat-count option to limit the output of
  a diffstat report.</p>
</li>
<li>
<p>"git diff" learned a "--histogram" option to use a different diff
  generation machinery stolen from jgit, which might give better
  performance.</p>
</li>
<li>
<p>"git diff" had a weird worst case behaviour that can be triggered
  when comparing files with potentially many places that could match.</p>
</li>
<li>
<p>"git fetch", "git push" and friends no longer show connection
  errors for addresses that couldn't be connected to when at least one
  address succeeds (this is arguably a regression but a deliberate
  one).</p>
</li>
<li>
<p>"git grep" learned "--break" and "--heading" options, to let users mimic
  the output format of "ack".</p>
</li>
<li>
<p>"git grep" learned a "-W" option that shows wider context using the same
  logic used by "git diff" to determine the hunk header.</p>
</li>
<li>
<p>Invoking the low-level "git http-fetch" without "-a" option (which
  git itself never did---normal users should not have to worry about
  this) is now deprecated.</p>
</li>
<li>
<p>The "--decorate" option to "git log" and its family learned to
  highlight grafted and replaced commits.</p>
</li>
<li>
<p>"git rebase master topci" no longer spews usage hints after giving
  the "fatal: no such branch: topci" error message.</p>
</li>
<li>
<p>The recursive merge strategy implementation got a fairly large
  fix for many corner cases that may rarely happen in real world
  projects (it has been verified that none of the 16000+ merges in
  the Linux kernel history back to v2.6.12 is affected with the
  corner case bugs this update fixes).</p>
</li>
<li>
<p>"git stash" learned an "--include-untracked option".</p>
</li>
<li>
<p>"git submodule update" used to stop at the first error updating a
  submodule; it now goes on to update other submodules that can be
  updated, and reports the ones with errors at the end.</p>
</li>
<li>
<p>"git push" can be told with the "--recurse-submodules=check" option to
  refuse pushing of the supermodule, if any of its submodules'
  commits hasn't been pushed out to their remotes.</p>
</li>
<li>
<p>"git upload-pack" and "git receive-pack" learned to pretend that only a
  subset of the refs exist in a repository. This may help a site to
  put many tiny repositories into one repository (this would not be
  useful for larger repositories as repacking would be problematic).</p>
</li>
<li>
<p>"git verify-pack" has been rewritten to use the "index-pack" machinery
  that is more efficient in reading objects in packfiles.</p>
</li>
<li>
<p>test scripts for gitweb tried to run even when CGI-related perl modules
  are not installed; they now exit early when the latter are unavailable.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Git 1.7.6.1 publiée</title>
      <link>http://www.gitfr.net/blog/2011/08/29/git-1.7.6.1-publiee</link>
      <pubDate>Mon, 29 Aug 2011 00:34:00 CEST</pubDate>
      <category><![CDATA[release]]></category>
      <category><![CDATA[git]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/08/29/git-1.7.6.1-publiee</guid>
      <description>Git 1.7.6.1 publiée</description>
      <content:encoded><![CDATA[<p>La première version de maintenance de la branche 1.7.6.x est sortie le 24 août,
avec 88 corrections.</p>
<h2>Le changelog</h2>
<ul>
<li>
<p>Various codepaths that invoked zlib deflate/inflate assumed that these
   functions can compress or uncompress more than 4GB data in one call on
   platforms with 64-bit long, which has been corrected.</p>
</li>
<li>
<p>"git unexecutable" reported that "unexecutable" was not found, even
   though the actual error was that "unexecutable" was found but did
   not have a proper she-bang line to be executed.</p>
</li>
<li>
<p>Error exits from $PAGER were silently ignored.</p>
</li>
<li>
<p>"git checkout -b <branch>" was confused when attempting to create a
   branch whose name ends with "-g" followed by hexadecimal digits,
   and refused to work.</p>
</li>
<li>
<p>"git checkout -b <branch>" sometimes wrote a bogus reflog entry,
   causing later "git checkout -" to fail.</p>
</li>
<li>
<p>"git diff --cc" learned to correctly ignore binary files.</p>
</li>
<li>
<p>"git diff -c/--cc" mishandled a deletion that resolves a conflict, and
   looked in the working tree instead.</p>
</li>
<li>
<p>"git fast-export" forgot to quote pathnames with unsafe characters
   in its output.</p>
</li>
<li>
<p>"git fetch" over smart-http transport used to abort when the
   repository was updated between the initial connection and the
   subsequent object transfer.</p>
</li>
<li>
<p>"git fetch" did not recurse into submodules in subdirectories.</p>
</li>
<li>
<p>"git ls-tree" did not error out when asked to show a corrupt tree.</p>
</li>
<li>
<p>"git pull" without any argument left an extra whitespace after the
   command name in its reflog.</p>
</li>
<li>
<p>"git push --quiet" was not really quiet.</p>
</li>
<li>
<p>"git rebase -i -p" incorrectly dropped commits from side branches.</p>
</li>
<li>
<p>"git reset [<commit>] paths..." did not reset the index entry correctly
   for unmerged paths.</p>
</li>
<li>
<p>"git submodule add" did not allow a relative repository path when
   the superproject did not have any default remote url.</p>
</li>
<li>
<p>"git submodule foreach" failed to correctly give the standard input to
   the user-supplied command it invoked.</p>
</li>
<li>
<p>submodules that the user has never showed interest in by running
   "git submodule init" was incorrectly marked as interesting by "git
   submodule sync".</p>
</li>
<li>
<p>"git submodule update --quiet" was not really quiet.</p>
</li>
<li>
<p>"git tag -l <glob>..." did not take multiple glob patterns from the
   command line.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Le commit initial vide</title>
      <link>http://www.gitfr.net/blog/2011/07/31/le-commit-initial-vide</link>
      <pubDate>Sun, 31 Jul 2011 04:13:00 CEST</pubDate>
      <category><![CDATA[git]]></category>
      <category><![CDATA[astuce]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/07/31/le-commit-initial-vide</guid>
      <description>Le commit initial vide</description>
      <content:encoded><![CDATA[<p>Nous instaurons la rubrique astuce avec le <strong>commit initial vide</strong>. Le commit
initial a un statut particulier puisque c'est... le premier, l'ancêtre de tous
les commits. C'est pourquoi je commence <strong>toujours</strong> un dépôt par un commit
initial vide avec la commande :</p>
<pre><code>$git commit --allow-empty -m "Initial commit."
</code></pre>
<p>C'est seulement ensuite que j'ajoute du contenu. A quoi ça sert ? Tout
simplement à <strong>jouer avec tous les commits de contenu</strong>.</p>
<p>Examinons deux exemples.</p>
<h2>rebase -i</h2>
<p>Un rebase -i demande une limite basse, un commit de référence en sommes. Si
mon graphe est composé des commits c1, c2, c3 et c4, je peux jouer sur c2 à
c4, mais pas c1, ce dernier étant la référence. Si j'ai du contenu dans c1,
je l'ai dans le baba ! Inversement, si c1 est un commit vide, alors tout mon
contenu est accessible.</p>
<h2>Travailler directement dans une branche</h2>
<p>Une bonne pratique est de ne pas travailler dans master, mais uniquement dans
des branches (de fonctionnalités, d'intégration ou de correction de bugs) et de
merger ensuite (avec sans <em>fast forward</em> selon le <em>workflow</em> que vous avez
choisi). Mais comme mon commit initial est obligatoirement dans master, c'est
raté. Encore une fois, si ce commit ne contient pas de contenu, le problème
disparait de lui-même : mon premier commit de contenu (le deuxième dans le
graphe donc) sera lui, dans une branche.</p>
<h2>Conclusion</h2>
<p>N'oubliez pas que la puissance de Git vient dans la capacité à manipuler votre
graphe dans tous les sens, et même si vous ne voyez pas l'intérêt de modifier
vos premiers commits, vous en verrez l'utilité plusieurs semaines aprés.
Voir des mois après :).</p>]]></content:encoded>
    </item>
    <item>
      <title>La différence entre Hg et Git</title>
      <link>http://www.gitfr.net/blog/2011/07/18/la-difference-entre-hg-et-git</link>
      <pubDate>Mon, 18 Jul 2011 00:40:00 CEST</pubDate>
      <category><![CDATA[git]]></category>
      <category><![CDATA[hg]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/07/18/la-difference-entre-hg-et-git</guid>
      <description>La différence entre Hg et Git</description>
      <content:encoded><![CDATA[<p>J'aime beaucoup ce <a href="http://blog.daemon.com.au/blog-post/know-subversion-git-or-mercurial">billet</a>,
il résume parfaitement à mes yeux la différence majeure entre Hg et Git quand
on vient de SVN : il est possible d'utiliser Hg (Mercurial) comme un <em>SVN qui
marche</em>, ce n'est pas du tout le cas avec Git car très vite, on se retrouve à
faire des grosses bêtises si on n'a pas compris les concepts importants.</p>
<h2>Hg, un SVN qui marche</h2>
<p>Ce n'est pas une attaque contre Hg, bien au contraire, c'est une choix
réfléchi de se comporter comme tel :</p>
<ul>
<li>C'est un outil de gestion de source.</li>
<li>Chaque commit sait dans quelle branche il se trouve.</li>
<li>Les possibilités de manipulation des branches sont assez réduites quand
  on n'ajoute pas d'extensions.</li>
</ul>
<p>La volonté du fondateur de Mercurial est de toujours sacrifier les
fonctionnalités au profit d'une conception claire, là ou Linus Torvalds
avait en tête dés le départ un certain nombre de fonctionnalités. La vitesse
étant le seul objectif qui autorise à sacrifier des fonctionnalités.</p>
<p>Hg est un outil puissant, qui autorise ce que SVN ne permettait
pas (pour être précis, il le faisait tellement mal qu'on <strong>ne se permettait
pas</strong> de le faire) : une gestion plus fine des branches. Avec Hg, créer des
branches et <em>merger</em> ne pose plus de soucis particulier. Comme le dit 
l'article :</p>
<blockquote>
<p>For Hg, the instructor goes through the Hg primer with the student. The
student is then left to use Hg with the instructor watching. Every time
the student begins to think about branching or merging, the instructor hits
the student over the head with the bat. This provides a negative
reinforcement for the student's SVN branching and merging habits.</p>
</blockquote>
<p>Une fois assimilées la gestion des branches et la notion de distribué, on se
débrouille relativement bien. Je connais d'ailleurs peu d'utilisateurs
de Mercurial qui ont étudiés le DAG, ou les possiblités avancées des 
branches (rebase, cherry-pick...).</p>
<h2>Git, un outil de gestion de contenu</h2>
<p>C'est une notion importante à saisir, Git n'est <strong>pas</strong> un outil de gestion de
source (VCS). Comme avec n'importe quel outil de contenu, il est possible de
modifier ou de supprimer ce que l'on veut : Git permet de <strong>modifier
l'historique</strong>, ce qui n'est pas le cas d'un VCS, comme CVS, SVN ou Hg. De
ce postulat simple découle une autre philosophie, et donc une utilisation
sensiblement différente : une distinction entre <em>branche du DAG</em> et <em>branche
utilisateur</em>.</p>
<p>Une branche du <strong>DAG</strong> (<em>directed Acyclic Graph</em> ou <em>graphe orienté acyclique</em>)
est manipulée par Git et permet de suivre les modifications du code : qui est
le descendant de qui ? Avec ce graphe, il est simple pour un DVCS de savoir
quoi faire lors d'une opération comme une fusion (un merge). Mais chaque
branche est <strong>anonyme</strong>, elle ne porte pas de nom. Les noms de branches
sont dans un <strong>espace différent</strong>, distinct, qui permet de les manipuler
indifféremment du DAG. Ou inversement de manipuler le DAG sans toucher aux noms.
Cet espace utilisateur est appelé <strong>référence</strong>.</p>
<p><strong>Note</strong> : Je reviendrai la dessus dans un prochain billet, il est temps
maintenant de transformer la conférence #gitfr en billet.</p>
<p>Cette distinction est source de confusion, d'erreur et de déception. Mais c'est
ce qui rend Git si <strong>puissant</strong> !</p>
<p>C'est ce que dit la suite du billet :</p>
<blockquote>
<p>At the very beginning, the instructor bashes the student repeatedly over the
head with the bat until all brain cells containing any memory of SVN are
destroyed. The instructor then teaches the student the Git primer.</p>
</blockquote>
<p>J'aime beaucoup cette image :). Il ne faut surtout pas utiliser Git comme on
utilise SVN, ni de prêt ni de loin, il faut <strong>ré-apprendre</strong> ce qu'est le
contrôle de version. Je ne dit pas que cela est facile, c'est même la raison
première de la création de #gitfr.</p>
<p>Mais ce travail est valorisé au centuple une fois Git maitrisé, et vous ouvre
un champ des possibles inimaginable quand on vient de SVN...</p>]]></content:encoded>
    </item>
    <item>
      <title>Google Code supporte Git</title>
      <link>http://www.gitfr.net/blog/2011/07/17/google-code-supporte-git</link>
      <pubDate>Sun, 17 Jul 2011 18:35:00 CEST</pubDate>
      <category><![CDATA[github]]></category>
      <category><![CDATA[git]]></category>
      <category><![CDATA[google code]]></category>
      <guid isPermaLink="true">http://www.gitfr.net/blog/2011/07/17/google-code-supporte-git</guid>
      <description>Google Code supporte Git</description>
      <content:encoded><![CDATA[<p>Le ticket <a href="http://code.google.com/p/support/issues/detail?id=2454">2454</a> est
maintenant fermé. Nommé <em>native git support</em>, c'était le ticket le plus 
<strong>demandé</strong> (<em>starred</em>) par les utilisateurs. Un peu plus de 2 ans après le
support de Mercurial, Google Code <strong>supporte</strong> donc Git. Cela signifie que
les 3 plus gros hébergeurs de code (Sourceforge, Google Code et GitHub)
supportent maitenant notre DVCS préféré. Cela signifie aussi que l'avenir
s'assombrie pour Mercurial, qui se retrouve (presque) dans la même
situation que Bzr, avec un seul hébergeur <em>dépendant</em> important. Terme mal
choisi pour désigner un hébergeur qui s'appuie uniquement sur une techno, en
l'occurence <a href="https://bitbucket.org/">Bitbucket</a> (<a href="https://launchpad.net/">Launchpad</a>
pour Bzr).</p>
<p>Pourquoi ce changement alors que rien ne semblait prévu ? Je vois deux
raisons, l'une <strong>technique</strong> et l'autre <strong>marketing</strong>.</p>
<h2>L'argument technique</h2>
<p>Comme le dit très bien Shawn Pearce, développeur Git, mainteneur des projets
<a href="http://code.google.com/p/gerrit/">Gerrit</a> et <a href="http://www.eclipse.org/jgit/">JGit</a> 
(ré-implentation de Git en Java, utilisé par Gerrit et Eclipse notamment),
sur la liste de diffusion, Git supporte depuis la version 1.6.6 le protocole
<strong>smart http</strong>. Ce dernier gère bien mieux le protocole http sur lequel Google
Code s'appuie <strong>massivement</strong>. Ce qui a ouvert la voie, il <em>suffisait</em> (hum)
ensuite de modifier Git pour gérer l'infrastructure Google. Si cela vous
intéresse, jeter un oeil sur la video
<a href="http://www.youtube.com/watch?v=ri796Hx8las">Google I/O 2009 - Mercurial on BigTable</a>
qui explique cette même modification avec Mercurial. Une vidéo similaire
devrait sortir pour Git (chouette !).</p>
<p>Chose étonnante, d'après Dave Borowitz, Google code n'utilise pas JGit mais
<a href="http://www.samba.org/~jelmer/dulwich/">Dulwich</a>, codé en Python. Je suis
curieux de connaitre les raisons de ce choix (Shawn avait averti que ce
n'était pas JGit mais n'étant pas le responsable du projet, il ne voulait
pas en dire plus).</p>
<h2>L'argument marketing</h2>
<p>La montée en puissance de GitHub ne fait aucun doute, cet
<a href="http://www.readwriteweb.com/hack/2011/06/github-has-passed-sourceforge.php">article</a>
le montre fort bien : entre janvier et mai 2011, le nombre de commits sur
GitHub représente le total des commits de Sourceforge, Google Code et
CodePlex <strong>réunis</strong>. Même si ce chiffre est à prendre avec de grosses pincettes,
les DVCS poussent au commit unitaire donc à en produire bien plus, c'est
un chiffre intéressant (le nombre de lignes de code serait lui significatif).</p>
<p>Et chose intéressante, on retrouve le C++ et Java en tête,  cela laisse
entendre que ces communautés ont eux aussi (au moins partiellement) basculées
sur GitHub (après les communautés Ruby, Javascript et Python).</p>
<h2>Pour conclure</h2>
<p>Redmonk dit que <strong>GitHub est le nouveau centre de gravité</strong>, les chiffres le
prouvent, et je trouve cela très bien. D'un coté, les développeurs sont
poussés à ne plus utiliser des <em>hébergements 1.0</em> (et zut, je succombe
moi aussi à cette mode débile). De l'autre, il pousse les hébergeurs à
augmenter drastiquement la qualité. Et on ne va pas s'en plaindre !</p>]]></content:encoded>
    </item>
  </channel>
</rss>

