Git 1.7.10 publiée
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 :
-
gitk a pas mal de petites évolutions.
-
Un éditeur s'ouvre lors d'un
git-commitpour pousser les gens à expliquer les changements. -
On peut cloner qu'un répertoire.
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.
Le changelog
-
various "gitk" updates.
-
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.
-
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.
-
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".
-
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".
-
"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.
-
"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.
-
"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".
-
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.
-
"git diff --stat" learned to adjust the width of the output on wider terminals, and give more columns to pathnames as needed.
-
"diff-highlight" filter (in contrib/) was updated to produce more aesthetically pleasing output.
-
"fsck" learned "--no-dangling" option to omit dangling object information.
-
"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.
-
"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.
-
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.
-
"git push" learned the "--prune" option, similar to "git fetch".
-
The whole directory that houses a top-level superproject managed by "git submodule" can be moved to another place.
-
"git symbolic-ref" learned the "--short" option to abbreviate the refname it shows unambiguously.
-
"git tag --list" can be given "--points-at
-
"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.
-
"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).
-
Project search in "gitweb" shows the substring that matched in the project name and description highlighted.
-
HTTP transport learned to authenticate with a proxy if needed.
-
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.
-
Improved handling of views, labels and branches in "git-p4" (in contrib).
-
"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.
-
Some "git-svn" updates.
-
"vcs-svn"/"svn-fe" learned to read dumps with svn-deltas and support incremental imports.
-
"git difftool/mergetool" learned to drive DeltaWalker.
-
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.
-
Recursive call chains in "git index-pack" to deal with long delta chains have been flattened, to reduce the stack footprint.
-
Use of add_extra_ref() API is now gone, to make it possible to cleanly restructure the overall refs API.
-
The command line parser of "git pack-objects" now uses parse-options API.
-
The test suite supports the new "test_pause" helper function.
-
Parallel to the test suite, there is a beginning of performance benchmarking framework.
-
t/Makefile is adjusted to prevent newer versions of GNU make from running tests in seemingly random order.
-
The code to check if a path points at a file beyond a symbolic link has been restructured to be thread-safe.
-
When pruning directories that has become empty during "git prune" and "git prune-packed", call closedir() that iterates over a directory before rmdir() it.
-
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).
-
"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).
-
"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.
-
zsh port of bash completion script needed another workaround.
-
git-gui updated to 0.16.0.
-
git-p4 (in contrib/) updates.
-
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.
-
The code to handle username/password for HTTP transactions used in "git push" & "git fetch" learned to talk "credential API" to external programs to cache or store them, to allow integration with platform native keychain mechanisms.
-
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.
-
The internals of "revert/cherry-pick" have been tweaked to prepare building more generic "sequencer" on top of the implementation that drives them.
-
"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".
-
"git add" learned to stream large files directly into a packfile instead of writing them into individual loose object files.
-
"git checkout -B
" is a more intuitive way to spell "git reset --keep ". -
"git checkout" and "git merge" learned "--no-overwrite-ignore" option to tell Git that untracked and ignored files are not expendable.
-
"git commit --amend" learned "--no-edit" option to say that the user is amending the tree being recorded, without updating the commit log message.
-
"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.
-
"git commit" detects and rejects an attempt to stuff NUL byte in the commit log message.
-
"git commit" learned "-S" to GPG-sign the commit; this can be shown with the "--show-signature" option to "git log".
-
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.
-
The set of built-in function-header patterns for various languages knows MATLAB.
-
"git log --format='
'" learned new %g[nNeE] specifiers to show information from the reflog entries when walking the reflog (i.e. with "-g"). -
"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.
-
"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".
-
"git branch --edit-description" can be used to add descriptive text to explain what a topic branch is about.
-
"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.
-
"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:
-
the tip of the branch being requested to be merged;
- the branch description describing what the topic is about;
-
the contents of the annotated tag, when requesting to pull a tag.
-
"git pull" learned to notice 'pull.rebase' configuration variable, which serves as a global fallback for setting 'branch.
.rebase' configuration variable per branch. -
"git tag" learned "--cleanup" option to control how the whitespaces and empty lines in tag message are cleaned up.
-
"gitweb" learned to show side-by-side diff.
Git 1.7.9 publiée
La version 1.7.9 est sortie le 27 janvier avec plusieurs évolutions intéressantes :
-
Un meilleur support des gros fichiers (Git n'étant pas réputé pour ça).
-
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.
-
L'internationalisation est maintenant activée (honte à moi, toujours pas démarré le projet de traduction en Français).
-
La possibilité d'ajouter une description à une branche.
-
L'option
--no-editquand on amende un commit.
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.
Le changelog
-
gitk updates accumulated since early 2011.
-
git-gui updated to 0.16.0.
-
git-p4 (in contrib/) updates.
-
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.
-
The code to handle username/password for HTTP transactions used in "git push" & "git fetch" learned to talk "credential API" to external programs to cache or store them, to allow integration with platform native keychain mechanisms.
-
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.
-
The internals of "revert/cherry-pick" have been tweaked to prepare building more generic "sequencer" on top of the implementation that drives them.
-
"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".
-
"git add" learned to stream large files directly into a packfile instead of writing them into individual loose object files.
-
"git checkout -B
" is a more intuitive way to spell "git reset --keep ". -
"git checkout" and "git merge" learned "--no-overwrite-ignore" option to tell Git that untracked and ignored files are not expendable.
-
"git commit --amend" learned "--no-edit" option to say that the user is amending the tree being recorded, without updating the commit log message.
-
"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.
-
"git commit" detects and rejects an attempt to stuff NUL byte in the commit log message.
-
"git commit" learned "-S" to GPG-sign the commit; this can be shown with the "--show-signature" option to "git log".
-
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.
-
The set of built-in function-header patterns for various languages knows MATLAB.
-
"git log --format='
'" learned new %g[nNeE] specifiers to show information from the reflog entries when walking the reflog (i.e. with "-g"). -
"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.
-
"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".
-
"git branch --edit-description" can be used to add descriptive text to explain what a topic branch is about.
-
"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.
-
"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:
-
the tip of the branch being requested to be merged;
- the branch description describing what the topic is about;
-
the contents of the annotated tag, when requesting to pull a tag.
-
"git pull" learned to notice 'pull.rebase' configuration variable, which serves as a global fallback for setting 'branch.
.rebase' configuration variable per branch. -
"git tag" learned "--cleanup" option to control how the whitespaces and empty lines in tag message are cleaned up.
-
"gitweb" learned to show side-by-side diff.
Comportement par défaut du git push
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.
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 :).
Commençons par lire le manuel sur l'option push.default :
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:
- nothing - do not push anything.
- matching - push all matching branches. All branches having the same name in both ends are considered to be matching. This is the default.
- upstream - push the current branch to its upstream branch.
- tracking - deprecated synonym for upstream.
- current - push the current branch to a branch of the same name.
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 git push, 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 git push origin mybranch
pour éviter cela.
C'est pour cette raison que je configure Git avec l'option upstream :
$ git config --global push.default upstream
2 avantages immédiats :
- Il ne pousse que la branche courante.
- Il m'oblige à faire un tracking, ce qui est bien utile.
Maintenant, si vous tentez de pousser la branche test avec la commande
git push sans tracking préalable, Git vous répond :
fatal: The current branch test has no upstream branch. To push the current branch and set the remote as upstream, use
git push --set-upstream origin test
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 u=, qui indique que vos deux branches sont synchronisées.
Rappel sur le tracking
Le tracking consiste à associer une branche locale et une branche distante
(dite upstream dans la terminologie Git), ce qui informe Git de la branche
distante à utiliser lors d'un git pull. 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 :
- Git suit la branche master lors d'un clone.
- Git suit la branche que vous venez de créer si celle ci existe déjà sur le serveur
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.
Git 1.7.8 publiée
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.
Le changelog
-
Some git-svn, git-gui, git-p4 (in contrib) and msysgit updates.
-
Updates to bash completion scripts.
-
The build procedure has been taught to take advantage of computed dependency automatically when the complier supports it.
-
The date parser now accepts timezone designators that lack minutes part and also has a colon between "hh:mm".
-
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.
-
"git am" learned how to read from patches generated by Hg.
-
"git archive" talking with a remote repository can report errors from the remote side in a more informative way.
-
"git branch" learned an explicit --list option to ask for branches listed, optionally with a glob matching pattern to limit its output.
-
"git check-attr" learned "--cached" option to look at .gitattributes files from the index, not from the working tree.
-
Variants of "git cherry-pick" and "git revert" that take multiple commits learned to "--continue" and "--abort".
-
"git daemon" gives more human readble error messages to clients using ERR packets when appropriate.
-
Errors at the network layer is logged by "git daemon".
-
"git diff" learned "--minimal" option to spend extra cycles to come up with a minimal patch output.
-
"git diff" learned "--function-context" option to show the whole function as context that was affected by a change.
-
"git difftool" can be told to skip launching the tool for a path by answering 'n' to its prompt.
-
"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.
-
"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.
-
"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:
" in it. -
"git for-each-ref" learned "%(contents:subject)", "%(contents:body)" and "%(contents:signature)". The last one is useful for signed tags.
-
"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.
-
"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.
-
The recursive merge backend no longer looks for meaningless existing merges in submodules unless in the outermost merge.
-
"git log" and friends learned "--children" option.
-
"git ls-remote" learned to respond to "-h"(elp) requests.
-
"mediawiki" remote helper can interact with (surprise!) MediaWiki with "git fetch" & "git push".
-
"git merge" learned the "--edit" option to allow users to edit the merge commit log message.
-
"git rebase -i" can be told to use special purpose editor suitable only for its insn sheet via sequence.editor configuration variable.
-
"git send-email" learned to respond to "-h"(elp) requests.
-
"git send-email" allows the value given to sendemail.aliasfile to begin with "~/" to refer to the $HOME directory.
-
"git send-email" forces use of Authen::SASL::Perl to work around issues between Authen::SASL::Cyrus and AUTH PLAIN/LOGIN.
-
"git stash" learned "--include-untracked" option to stash away untracked/ignored cruft from the working tree.
-
"git submodule clone" does not leak an error message to the UI level unnecessarily anymore.
-
"git submodule update" learned to honor "none" as the value for submodule.
.update to specify that the named submodule should not be checked out by default. -
When populating a new submodule directory with "git submodule init", the $GIT_DIR metainformation directory for submodules is created inside $GIT_DIR/modules/
/ 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. -
"gitweb" leaked unescaped control characters from syntax hiliter outputs.
-
"gitweb" can be told to give custom string at the end of the HTML HEAD element.
-
"gitweb" now has its own manual pages.
-
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).
-
"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).
-
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).
-
Report from "git commit" on untracked files was confused under core.ignorecase option. (merge 395c7356 jk/name-hash-dirent later to maint).
-
"git merge" did not understand ":/
" as a way to name a commit. -
"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).
-
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).
Comprendre le refspec
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 origin (dans le cas d'un clone) ou le nom que
vous lui donnez si vous l'avez ajouter avec la commande git-remote add.
Mais pourquoi Git a t'il ce comportement ?
La réponse se trouve dans le refspec, 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.
Petit rappel
Il est impossible 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.
C'est là que le refspec rentre en jeu, il permet de définir les branches concernées au moment de la synchronisation.
Clonage
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 git-clone.
Ce dernier génère un refspec générique suffisant. Editez le fichier
.git/config et vous verrez ces lignes :
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = /path/to/repos
Une explication rapide : le dépôt distant qui se trouve à l'url spécifié s'appelle en local origin 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 origin.
Mais un deuxième rappel avant d'aller plus loin.
Structure des références
La gestion des références est d'une simplicité affligeante. Tout est contenu
dans le répertoire .git/refs. 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 :
-
heads pour stocker les références locales de type branche.
-
tags pour stocker les références locales de type tag.
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.
Explication
Si je vous dis qu'un refspec s'écrit toujours source:destination, la ligne
suivante ne doit pas vous poser trop de soucis. Examinons la de plus prêt :
fetch = +refs/heads/:refs/remotes/origin/
-
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).
-
Le symbole
+signifie qu'on autorise les récuparation non fast-forword. -
le reste de la ligne est assez explicite. Pour toutes les références se trouvant dans le chemin
refs/heads/dans le dépôt distant, on associe une référence dans le cheminrefs/remotes/origin/dans le dépot local.
Si par exemple le dépôt distant a 3 branches qui se nomment riri, fifi et
loulou, vous aurez donc en local 3 branches origin/riri, origin/fifi et
origin/loulou.
Importance du refspec
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.
Ajout d'un dépôt distant
La commande git-remote permet de manipuler les dépôts distants, avec
notamment la commande git-remote add pour en ajouter. Ce dernier se comporte
comme la commande git-clone, en configurant le refspec au plus
large (toutes les références donc).
refspec en ligne de commande
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.
Quelques exemples :
git fetch origin +pu:tmp
Récupére la référence pu et les objets associés et appeles la tmp en local.
git push HEAD:master
Pousse la branche actuelle sur la branche distante master.
git push origin master:refs/heads/qa/experimental
Pousse la branche master sur la branche distante expérimental. Nous utilisons ici le nom complet de la référence.
Le refspec :
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.
Effacer une référence distante
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 :
git push :test
Autrement dit, je pousse une référence vide sur la référence test.
Associer branche locale / branche distante
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
.git/config du dépôt local :
[branch "master"]
remote = origin
merge = refs/heads/master
Qui veut dire : associe la branche master du dépôt origin à ma référence
locale master. Et oh surprise, la ligne est utilisée pour la commande
merge, ce qui est tout à faire logique. la commande git-fetch 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.
Petite remarque, c'est uniquement quand vous avez spécifiée une branche distante (upstream 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.
pull = fetch + merge
Vous devez maintenant comprendre pourquoi on dit que la commande git-pull
n'est en fait qu'un raccouri pour :
- git-fetch
- git-merge origin/master
A quoi sert le fetch ?
La commande git-pull 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.
Notez qu'il existe l'option --rebase pour rebaser automatiquement votre
branche locale sur la branche distante (ce qui est la aussi un scénario de
base).
Conclusion
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).
Git 1.7.7 publiée
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.
Le changelog
-
The scripting part of the codebase is getting prepared for i18n/l10n.
-
Interix, Cygwin and Minix ports got updated.
-
Various updates to git-p4 (in contrib/), fast-import, and git-svn.
-
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).
-
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.
-
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.
-
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.
-
"git am" learned to pass the "--exclude=
" option through to underlying "git apply". -
You can now feed many empty lines before feeding an mbox file to "git am".
-
"git archive" can be told to pass the output to gzip compression and produce "archive.tar.gz".
-
"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).
-
The length of abbreviated object names in "git branch -v" output now honors the core.abbrev configuration variable.
-
"git check-attr" can take relative paths from the command line.
-
"git check-attr" learned an "--all" option to list the attributes for a given path.
-
"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.
-
"git clone" can now take a "--config key=value" option to set the repository configuration options that affect the initial checkout.
-
"git commit
..." now lets you feed relative pathspecs that refer to outside your current subdirectory. -
"git diff --stat" learned a --stat-count option to limit the output of a diffstat report.
-
"git diff" learned a "--histogram" option to use a different diff generation machinery stolen from jgit, which might give better performance.
-
"git diff" had a weird worst case behaviour that can be triggered when comparing files with potentially many places that could match.
-
"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).
-
"git grep" learned "--break" and "--heading" options, to let users mimic the output format of "ack".
-
"git grep" learned a "-W" option that shows wider context using the same logic used by "git diff" to determine the hunk header.
-
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.
-
The "--decorate" option to "git log" and its family learned to highlight grafted and replaced commits.
-
"git rebase master topci" no longer spews usage hints after giving the "fatal: no such branch: topci" error message.
-
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).
-
"git stash" learned an "--include-untracked option".
-
"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.
-
"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.
-
"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).
-
"git verify-pack" has been rewritten to use the "index-pack" machinery that is more efficient in reading objects in packfiles.
-
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.
Git 1.7.6.1 publiée
La première version de maintenance de la branche 1.7.6.x est sortie le 24 août, avec 88 corrections.
Le changelog
-
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.
-
"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.
-
Error exits from $PAGER were silently ignored.
-
"git checkout -b
" was confused when attempting to create a branch whose name ends with "-g" followed by hexadecimal digits, and refused to work. -
"git checkout -b
" sometimes wrote a bogus reflog entry, causing later "git checkout -" to fail. -
"git diff --cc" learned to correctly ignore binary files.
-
"git diff -c/--cc" mishandled a deletion that resolves a conflict, and looked in the working tree instead.
-
"git fast-export" forgot to quote pathnames with unsafe characters in its output.
-
"git fetch" over smart-http transport used to abort when the repository was updated between the initial connection and the subsequent object transfer.
-
"git fetch" did not recurse into submodules in subdirectories.
-
"git ls-tree" did not error out when asked to show a corrupt tree.
-
"git pull" without any argument left an extra whitespace after the command name in its reflog.
-
"git push --quiet" was not really quiet.
-
"git rebase -i -p" incorrectly dropped commits from side branches.
-
"git reset [
] paths..." did not reset the index entry correctly for unmerged paths. -
"git submodule add" did not allow a relative repository path when the superproject did not have any default remote url.
-
"git submodule foreach" failed to correctly give the standard input to the user-supplied command it invoked.
-
submodules that the user has never showed interest in by running "git submodule init" was incorrectly marked as interesting by "git submodule sync".
-
"git submodule update --quiet" was not really quiet.
-
"git tag -l
..." did not take multiple glob patterns from the command line.
Le commit initial vide
Nous instaurons la rubrique astuce avec le commit initial vide. Le commit initial a un statut particulier puisque c'est... le premier, l'ancêtre de tous les commits. C'est pourquoi je commence toujours un dépôt par un commit initial vide avec la commande :
$git commit --allow-empty -m "Initial commit."
C'est seulement ensuite que j'ajoute du contenu. A quoi ça sert ? Tout simplement à jouer avec tous les commits de contenu.
Examinons deux exemples.
rebase -i
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.
Travailler directement dans une branche
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 fast forward selon le workflow 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.
Conclusion
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 :).
Articles précédents »