Projet

Général

Profil

GitBonnesPratiques » Historique » Version 35

Version 34 (Bruno Boiget, 01/12/2011 16:30) → Version 35/90 (Daniel Dehennin, 02/12/2011 16:53)

{{toc}}

h1. À faire sur cette documentation Présentation

* TODO Mettre au clair « sur une branche » et « dans une branche » Site officiel : http://git-scm.com/

Tutoriaux intéressants :
* TODO Clarifier « on »/« nous »

http://team.gcu.info/~ange/git_article/
* TODO Expliquer =git merge-base=

* TODO Lister les prérequis

h1. Pas taper !

Je vais essayer de décrire ici une méthodologie de travail basé sur
le tutorial des man pages http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html
système de gestion de version décentralisé "git":https://fr.wikipedia.org/wiki/Git.

Ce document ne représente en rien _LA_ bonne méthode de travail, il
* http://gitready.com/
s’agit juste, dans un premier temps, de mon opinion personnelle, * http://progit.org/book/
appuyée par l’expérience d’autres personnes que l’on trouve un peu * http://www.unixgarden.com/index.php/administration-systeme/git-pour-les-futurs-barbus
partout sur Internet. * http://yannesposito.com/Scratch/fr/blog/2010-03-22-Git-Tips/

Il est tout à fait possible de trouver autant, voir plus, de références Articles intéressants :
prônant un point de vue opposé ou orthogonal au mien.

Ce document n’est pas une référence git, je ne vais pas réécrire le
* "Avoiding Git Disasters: A Gory Story":http://randyfay.com/node/89
"progit book":http://progit.org/book/fr/, ni les autres références que l’on trouve sur Internet.

h1. De la méthode agile
* "A Rebase Workflow for Git":http://randyfay.com/node/91
* "Simpler Rebasing (avoiding unintentional merge commits)":http://randyfay.com/node/103
* "A Git Workflow for Agile Teams":http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html


Comme il est défini dans le "manifeste agile":https://fr.wikipedia.org/wiki/Manifeste_agile#Les_4_valeurs, Les manpages des commandes sont accessibles avec la première valeur est commande help directement,
par exemple :
<pre>

« Les individus et leurs interactions ». git help log
</pre>


Afin de travailler correctement en équipe, il *remarque* : Il faut communiquer, et
l’outil de gestion de
utiliser une version "git":https://fr.wikipedia.org/wiki/Git, utilisé à EOLE, peut-être un excellent
outil
récente de communication.

git-core (>1.6.3) pour pouvoir travailler avec les dépôts.

h1. De l’écriture des "ChangeLog":https://fr.wikipedia.org/wiki/ChangeLog Paramétrage global

Afin Il est nécessaire de communiquer avec les autres membres d’une équipe sur le déclarer vos noms et emails dans votre configuration git globale
travail que chacun effectue, l’écriture d’un ChangeLog, ou plus <pre>
précisément d’un « commit message » dans la littérature en anglaise git config --global user.name "Prénom NOM"
(qui pourrait être traduit par « message de consignation ») se doit git config --global user.email "prenom.nom@ac-acad.fr"
d’être fait correctement(sic). </pre>

Que penser d’un message comme « "typo":http://dev-eole.ac-dijon.fr/projects/eole-sso/repository/revisions/f2e5c52482c896b84e57333ba61654286b856f02 » ou encore « "correction d'une coquille":http://dev-eole.ac-dijon.fr/projects/cdc/repository/revisions/0dc6d59ca9c5294790ae1ebe0b035d8a3296ed22 » ?

Nous pouvons établir une règle simple et souple, par exemple :

Un message de commit comprend :

* Une première ligne résumant
Afin que le pourquoi du patch ;

* Une description longue optionnelle permettant d’expliciter
@git push@ fonctionne, il faut renseigner le
contexte du résumé donné en première ligne ;

* Une liste de
fichier et leur modification.

Une ligne vide sépare les différentes parties
@~/.netrc@ : la première est
obligatoire <pre>
machine dev-eole.ac-dijon.fr
login monlogin
password monmotdepasse
</pre>
et la troisième est optionnelle pour paramétrer les changements triviaux

Par exemple :

<pre>
Le répertoire /usr/share/eole/noyau/ est nécessaire (Fixes: #2405).

* debian/dirs: Création
droits du répertoire. fichier :
</pre>

<pre>
Simplification de la gestion des noyaux (ref: #2406).

* creole/fonctionseole.py: Suppression du code effectué par
eole-kernel-version depuis sa version 2.3-eole37~2.
Renommage de la variable 'boot_ok' en 'need_boot'.

chmod 600 ~/.netrc
</pre>

Cela impose la règle suivante :

« Ne jamais utiliser l’option "-m" de la commande "git commit" »

h1. De la cohérence de l’histoire du monde Premiers pas

Un système de gestion de version permet avant tout de conserver * Démarrer un
livre d’histoire d’un
nouveau projet.

Dans les premiers systèmes Demandez à l’administrateur Eole la création de gestion de version, cette histoire était
centralisée. Il fallait avoir le droit d’écrire
votre projet dans le « livre des
comptes et légendes » afin d’y ajouter un morceau, impossible donc de
réécrire l’histoire sans être tout puissant sur le registre.
RedMine.

Grâce aux systèmes décentralisés comme "git":https://fr.wikipedia.org/wiki/Git, tout * Premier Commit du projet.

d'abord récupérer
le monde peut avoir projet :
une copie privée de l’histoire publique d’un projet, pour cela il <pre>
suffit de « cloner » l’histoire originale :

<pre>
moi@work:~/src$
git clone git://far-far.away.example.net/bidule.git http://login@dev-eole.ac-dijon.fr/git/nom_projet
</pre>

À partir de là il remarquons bien que le projet initialisé est possible de vouloir y ajouter ses propres
morceaux, et cela sans rien demander à personne.
*vide*

On modifie ensuite, aller dans le projet et on consigne les nouveaux événements dans
notre copie locale de l’histoire
dossier du projet :

nom_projet, ajouter au moins un fichier,
puis

<pre>
moi@work:~/src/bidule(master)$ $EDITOR src/bidule.c # On modifie un fichier du projet
moi@work:~/src/bidule(master)$

git add src/bidule.c # On ajoute un événement à enregistrer dans le livre d’histoire
moi@work:~/src/bidule(master)$ git commit # On consigne ce nouvel événement
fichier1 fichier2 fichier3
</pre>

Mais l’histoire, c’est un sujet sensible. On ne badine pas avec <pre>
l’histoire et on ne la réécrit sous aucun prétexte.

Peu importe si la vérité est ailleurs, l’important c’est que tout le
git commit -m"permière version"
monde soit d’accord sur la même version des faits. </pre>

Si un plaisantin modifie l’histoire et maintenant la publie à tout vent, il branche master doit être apparue (puisqu'il y
aura conflit.

Nous allons
a des fichiers dans le projet), donc édicter la règle suivante :

« On ne réécrit pas l’histoire connue »

Cela sous entend donc que nous pouvons réécrire comme il nous plaît
<pre>
toute l’histoire qui nous est privée, c’est à dire inconnue de tous git branch
les autres. </pre>
doit lister la branche @master@


Mais dès qu’un événement est rendu public, ça n'est plus possible.

h1. Trop de pull, c’est trop chaud !

Que se passe-t-il si
pour finir , faire un jour nous souhaitons apprendre "push" pour envoyer les nouvelles fichiers sur le dépot de code :
<pre>

histoires git push -u http://login@dev-eole.ac-dijon.fr/git/nom_projet master
</pre>

L'option -u (upstream) permet
de par créer automatiquement le monde ? lien entre la branche locale et la branche créée sur le serveur.

Que ce passe-t-il si h1. Récupérer un jour nous souhaitons partager nos petites
histoires avec le reste du monde ?
projet existant.

La plupart du temps, la réponse donnée à ces questions commence par <pre>
quelque chose comme « fais-toi donc git clone http://login@dev-eole.ac-dijon.fr/git/nom_projet
</pre>
Cela va créer
un pull ». répertoire @nom_projet@ contenant un répertoire @.git@.

Cela se traduit, en terme git, par :

* Ajouter/retirer des fichiers :
<pre>
moi@work:~/src/bidule(master)$

git pull add file1 file2 ...
git remove file1 file2 ...
</pre>

Cela * Pour savoir quel est strictement équivalent aux deux commandes suivantes :

l'état des modifications :
<pre>
moi@work:~/src/bidule(master)$

git fetch origin
moi@work:~/src/bidule(master)$ git merge origin/master
status
</pre>

Mais il existe quelques soucis * Enregistrer les modifications localement :
<pre>
git commit -a -m"premiere version
avec cette méthode, la première étant le scm git"
« qu’une histoire entre en conflit avec l’une des vôtres ». </pre>

Un autre problème est que cette méthode « mélange » littéralement * Enregistrer les changements sur le serveur :
<pre>

l’histoire publique avec git push
</pre>

*remarque* : Avant d'enregistrer les changements sur le serveur, pensez à éditer
vos histoires privées, même s’il n’y a pas messages de
conflit,
commit, il peut-être difficile est possible de savoir si le résultat aura un sens
ou non.
les fusionner (Voir "Messages de commit").

Dans git, chaque commit a une généalogie, le parent * Récupérer les modifications du commit que je serveur et les fusionner localement :
m’apprête à faire est le dernier commit enregistré dans le dépôt.

Lors d’un
<pre>
git
pull
</pre>

Notre serveur GIT a plusieurs branches "branch".
* Pour afficher les branches disponibles
sur un dépôt contenant des modifications, le serveur :
<pre>
git créé un branch -a
commit ayant deux parents dont le seul but est de mélanger la
généalogie.
</pre>

Il est donc préférable d’utiliser * Pour paramétrer la méthode décomposée prise en deux compte d'une branche :
commandes, afin de pouvoir vérifier au préalable si des changements <pre>
sont à intégrer, et lesquels. git config branch.2.2.remote origin
git config branch.2.2.merge refs/heads/2.2
</pre>


Mais cela n’empêche nullement :

* D’être potentiellement désastreux : chaque « fusion » (merge) et
« consignation » de « fusion » (merge commit) sont à
Pour récupérer la charge de
chaque développeur ;
branche localement (à ne faire que la première fois) :
<pre>
git fetch origin 2.2:2.2
</pre>


* Votre histoire devient illisible. Elle intègre tout un tas de
« fusion » inexplicables ;
Pour se placer dans la branche :
<pre>
git checkout 2.2
</pre>


* Retrouver à quel moment précis et quel modification a entraîné un
changement de comportement devient impossible
Récupérer les modifications du fait des
« fusions »
serveur :
<pre>
git pull
</pre>


Tout mélanger * Pour se placer dans la même une autre branche, qui devient alors un tronc, pose "master" par exemple :
des soucis quant à la lecture de l’histoire du projet.

<pre>
git checkout master
</pre>

h1. Pour s’y retrouver, il faut s’accrocher aux branches

Une
Branch

* Récupérer une
branche est une ligne d’histoire divergente d’un projet, leur
utilisations dans <pre>
git est très simple et légère.

La création d’une branche peut se faire de deux façons :

#
checkout nomDeBrancheExistant
</pre>

*
Créer une branche
Se placer dans la branche
que j’utiliserais plus tard :
l'on veut copier
<pre>
moi@work:~/src/projet(master)$

git checkout maBrancheABrancher
...
git checkout -b maNouvelleBranche
</pre>

* Ceci peut être décomposé en 2 commandes :
<pre>
git
branch mabranche
moi@work:~/src/projet(master)$

git checkout mabranche
</pre>

* Diffuser la branche sur le serveur

# <pre>
git push http://user@194.167.18.22/git/eolebase mabranche
</pre>
ou, plus simplement :
<pre>
git push --all
</pre>

*
Créer une branche et commencer à travailler dedans :
partir d'un numéro de commit
<pre>
moi@work:~/src/projet(master)$

git checkout -b mabranche
moi@work:~/src/projet(mabranche)$
<numero_de_commit>
</pre>

Chacune de ces commandes permet de définir, en dernier argument, le * Supprimer une branche :
point de départ de la nouvelle branche. <pre>
git branch -D [nom-branche]
</pre>


Par défaut ce point de départ est le dernier commit de la * Supprimer une branche courante.

Tout les commit effectués
sur cette branche sont localisés le dépôt origin
<pre>
git push origin :branche
</pre>
Cela correspond en fait
à cette branche.

Cela permet de se focaliser sur une activité :

commande là : git push REMOTENAME LOCALBRANCHNAME:REMOTEBRANCHNAME sauf que LOCALBRANCHNAME est vide dans notre exemple.

* Sans risquer d’impacter la vision que Voir les autres ont différences entre deux branches
(par exemple avant
de l’histoire ; merger) :
<pre>
git diff-tree -p [nom-de-branche]
</pre>


* Sans se soucier Pour changer de ce qui peut arriver sur les autres branches ; branche :
<pre>
git checkout autrebranche
</pre>


* Sans fusionner les modifications de Pour revenir à la branche principale :
<pre>
git checkout master
</pre>

* Une autre technique consiste à organiser localement une arborescence différente par branche :
<pre>
git/master
/mabranche
</pre>

* Savoir
dans la
quelle branche courante. on se trouve :
<pre>
git branch
</pre>


Il faut travailler ensuite à intégrer cette nouvelle histoire à * Voir la branche courante avec le dernier log :
ligne principale. <pre>
git show-branch
</pre>


h2. Les voies du temps sont interpénétrables

C’est
* Envoyer pour la _première fois_ le principe utilisé par contenu de la branche courante sur le pull, serveur :
<pre>
git push origin HEAD
</pre>

Arrivé à
ce qui est nommé stade il peut être intéressant d'utiliser @git-gui@ (@/usr/lib/git-core/git-gui@) ou @giggle@.

Pour voir l'historique des différentes branches
dans la @guit-gui@, "@menu>dépôt>Voir l'historique de toutes les branches@"

* Autres commandes de base :

littérature <pre>
git log
git log --pretty=oneline --all
git diff
</pre>

h2. Branches distantes

* Si vous avez déjà cloné
le « merge workflow ». master d'un projet, pour visualiser les branches disponibles :
<pre>
git branch -a
</pre>
devrait renvoyer quelque chose comme ceci :
<pre>
* master
remotes/origin/2.2
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/upstream
</pre>


Ce qui est fait lors d’un =git pull= entre une * Pour récupérer la branche locale et une 2.2 :
branche sur un dépôt distant, « remote » en jargon git, est applicable <pre>
entre deux branches d’un dépôt local.

En pratique, on se positionne sur
git co 2.2
</pre>
va récupérer
la branche qui doit intégrer les 2.2 auprès du serveur origin.
modifications d’une autre, par exemple Une autre méthode:
<pre>
git branch --track 2.2 remotes/origin/2.2
</pre>

h1. Merge

Fusion : action consistant à fusionner
une branche publique, et on
fusionne
avec une autre ("mabranche" avec @master@ par exemple)

Exemple : @merge@ de
la branche privée de développement *mabranche* dans cette la branche *master*

* Se placer dans la branche @master@ :

branche publique :

<pre>
moi@work:~/src/projet(master)$

git checkout master
git
merge mabranche
git push
</pre>

Pour ensuite publier ces modifications par =git push=. *remarque* : après un @merge@, il n'y a pas de @commit@ à faire, juste @pull@.

Ceci induit les mêmes inconvénients que l’utilisation des pull.

Lorsque l’on passe
Si vous n'êtes pas satisfait du temps à travailler sur une branche privée, @merge@, il faut revenir en arrière avec un
<pre>

est tentant de « fusionner » régulièrement une branche publique de git reset --hard
référence, afin </pre>

**Résoudre un conflit
de se mettre à jour. @merge@**

Mais cette pratique ne fait Si lors d'un @merge@ il y a eu un problème du type :
<pre>
Auto-merged file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
</pre> et
que rendre illisible l’histoire privée
<pre>
git commit
</pre> répond qu'il reste des fichiers à merger (unresolved merge), *Il n'y a donc pas eu véritablement
de commit*
cette branche.

Cela rend très difficile la relecture
de chaque modification apportée même qu'un
par cette branche car son histoire n’est plus simplement une suite <pre>
logique d’étapes afin d’arriver git status
</pre>

Il faut alors éditer le fichier concerné, résoudre le conflit
à la main et faire un résultat voulu. nouveau un @commit@ :
<pre>
git add [file.txt]
git commit
</pre>


h2. On Le message @fatal: You have not concluded your merge. (MERGE_HEAD exists)@ vous rappelle qu'il ne construit que sur faut pas utiliser l'option "-m" ici ;)

* Pour repérer
les épaules fichiers qui n'ont pas été fusionné :
<pre>
git ls-files --unmerged
</pre>

h1. Stash

*git stash* permet
de géants sauvegarder des modifications locales afin de les appliquer plus tard.

Il existe une autre approche * Sauvegarde des modifications :
<pre>
# git stash save "en attente"
Saved working directory and index state On master: en attente
</pre>
* Liste des modifications sauvegardées :
<pre>
git stash list
stash@{0}: On master: en attente
</pre>
* Revenir
à l'état sauvegardé (_stash@{1}_ pour restaurer la problématique généalogique 2ème sauvegarde) :
<pre>
git stash apply [stash@{0}]
</pre>
* Nettoyer la liste
des sauvegarde :
commits, nommé dans la littérature « rebase workflow ». <pre>
git stash clear
</pre>

h1. Message de commit


Ce principe utilise la réécriture *IMPORTANT* : ne pas effectuer de l’historique, par conséquent,
elle ne peut être utilisée que
modifications sur des commits non publiés.

Le principe est
déjà envoyés sur le même que le greffage en botanique : serveur origin (le dépot).

# On coupe la branche ;
# On la greffe
Avant d'envoyer vos données sur une autre.

En pratique, c’est surtout utiliser pour préparer l’intégration
le serveur, il est possible de nos
modifications dans une branche publique.
modifier/améliorer les messages de commit.

C’est un peu h2. Modifier le miroir du « merge workflow ». dernier message de commit

Dans le « merge workflow », la fusion se fait sur la branche publique <pre>
git commit --amend
</pre>
Modifier, sauvegarder
et quitter.

h2. Modifier
les conflits sont gérés dans l’histoire de la branche publique. trois derniers messages

Dans le « rebase workflow », c’est l’inverse, tout se fait dans la * On lance un rebase
branche que l’on souhaite intégrer <pre>
git rebase -i HEAD~3
</pre>
* Un éditeur de texte s'ouvre avec quelque chose qui ressemble
à la branche publique.

La procédure est décomposée comme suit :

# Mise
ça:
<pre>
pick 6ffa65b update des bases
de côté donnees editable=0 et pas 2
pick 9697740 update des bases vers 2.2.3 : nettoyage et ajout d'un __init__.py (ref #11)
pick e56a7a4 Configuration des bases
de tous les commits de la branche depuis sa création :
on revient dans
donnees pour le tronc de développement (branche privée) à la
passage en version sur laquelle notre branche est basée ; 2.2.3 (fixes #11 : fixé)

# Rebase cd9333c..e56a7a4 onto cd9333c

# Intégration de tous les changements de la branche publique survenus
depuis ;

# Application de tous Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
</pre>
* Changer pick en edit sur
les commits mis lignes correspondantes aux commit à modifier, par exemple :
<pre>
edit 6ffa65b update des bases
de côté, il faut gérer les
éventuels conflits.

Avant la procédure, la branche privée était basée sur la branche
donnees editable=0 et pas 2
publique à un certains instant dans pick 9697740 update des bases vers 2.2.3 : nettoyage et ajout d'un __init__.py (ref #11)
pick e56a7a4 Configuration des bases de donnees pour
le passé.

Après
passage en version 2.2.3 (fixes #11 : fixé)
</pre>
* Sauver et quitter.
* Lancer
la procédure, la branche privée est basée sur le dernier commande :
<pre>
git
commit --amend
</pre>
* Modifier les messages
de la branche publique.

On a donc changé la base
commit, par ex :
<pre>
update des bases
de donnees editable=0 et pas 2 (ref #11)
</pre>
* Sauvegarder et quitter
* Lancer
la branche, d’où le nom de cette méthode.

Tout cela se fait simplement par :

commande :
<pre>
moi@work:~/src/projet(mabranche)$

git rebase master --continue
</pre>
* Vérifier les messages de commit
<pre>
git log
</pre>

h2. Fusionner des commits


Il est possible de faire fréquemment fusionner des rebases commit afin d'éviter des branches privées commits multiples pour des modifications mineures.
par rapport à la branche publique où seront intégrés les * Lancer un git rebase
modifications.

On minimise ainsi les conflits ou, plus précisément, on les dilue dans
<pre>
le temps.

Ce principe de
git rebase est à utiliser, au moins avant l’intégration à -i HEAD~3
la branche publique, afin d'avoir une histoire plus propre de la </pre>
branche <pre>
pick 16098ec Ajout d'icône gepi
et ce en fusionnant certains commits. cdt (ref #51)
pick f244e89 Deplacement d'icone
pick 7c8670c Deplacement des icones sources


Dans ce cas on ne # Rebase 5f5bfee..7c8670c onto 5f5bfee
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the
rebase par par rapport à une branche publique, mais will be aborted.
par rapport à un #
</pre>

* Changer pick en squash fusionne votre
commit de avec la branche privée.

Par exemple, ne pas avoir un commit ajoutant une fonctionnalité
ligne au-dessus
<pre>
pick 16098ec Ajout d'icône gepi
et les cdt (ref #51)
30 suivants qui corrigent les inévitables erreurs typographiques.

h1. TODO
squash f244e89 Deplacement d'icone
squash 7c8670c Deplacement des icones sources
</pre>
* Sauver et quitter,
Un arbre ou un arbrisseau, mais où est le tronc ? éditeur s'ouvre:
<pre>
# This is a combination of 3 commits.
# The first commit's message is:
Ajout d'icône gepi et cdt (ref #51)


h2. TODO Branches de développement # This is the 2nd commit message:

* Tag portant la version à publier Deplacement d'icone

h2. TODO Branches de packaging # This is the 3rd commit message:

* Mapping entre une branche de packaging et une branche de
développement
Deplacement des icones sources

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: eole/tmpls/update_creole_posh.sql
# renamed: plugins/plugin_desktop/icones/old/Corbeille.png -> plugins/plugin_desktop/icones/Corbeille.png
# renamed: plugins/plugin_desktop/icones/old/Courrier.png -> plugins/plugin_desktop/icones/Courrier.png
# renamed: plugins/plugin_desktop/icones/old/agenda.png -> plugins/plugin_desktop/icones/agenda.png
# new file: plugins/plugin_desktop/icones/cdt.png
# modified: plugins/plugin_desktop/icones/dir.png
# modified: plugins/plugin_desktop/icones/gepi.png
# renamed: plugins/plugin_desktop/icones/old/mail.jpg -> plugins/plugin_desktop/icones/mail.jpg
# modified: plugins/plugin_desktop/icones/mail.png
# new file: sources-desktop/icones/cdt.xcf
# renamed: plugins/plugin_desktop/icones/grand/moodle.gif -> sources-desktop/icones/moodle.gif
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# databases/bdd/scribe-posh.sql.sav
</pre>
* Mapping de la version sur Éditer les tag de dév : release/%(version)s messages (un message suffit)
<pre>
# The first commit's message is:
Ajout d'icône pour les applications scribe (ref #51)
# This is the 2nd commit message:


# This is the 3rd commit message:

# Please enter the commit message for your changes. Lines starting
</pre>
* Génération du =debian/changelog= sur une branche Sauver et quitter
* Vérifier que cela ressemble bien
à part afin de ne
pas générer de conflit
ce que vous voulez
<pre>
git log
</pre>


h2. TODO Configuration git-buildpackage

Suppression d'un commit

git rebase --onto ANCIENIDCOMMIT NOUVEAUIDCOMMIT

h1. « Le blabla c’est bien, mais en pratique ? » par moi©®™ Trucs et astuces

h2. Puisque je vous dis que les branches ça ne coûte rien !

Dans git, une branche est simplement
* Résoudre un fichier dans l’arborescence signalement avec l'ajout de "fixes #<numéro du signalement>"
répertoire =.git/refs/heads/=.

Ce fichier contient l’identifiant du dernier
<pre>
git
commit de cette branche,
c’est le "SHA1":http://fr.wikipedia.org/wiki/SHA1
-m"La nouvelle feature fixes #<numéro du contenu de l’objet (les détails sont accessibles dans signalement>"
"Les tripes de Git":http://progit.org/book/fr/ch9-0.html). git push ....
</pre>


L’identifiant de commit * Faire référence à un fichier dans l’arborescence signalement
<pre>
git commit -m"bla bla bal
du bug #<numéro du signalement>"
répertoire =.git/objects/=, avec : </pre>

* Activer la coloration syntaxique
<pre>
git config --global color.ui true
</pre>

* Pour controler
les deux premiers caractères (1 octet noté fichiers à ne JAMAIS prendre en hexadécimal) sont compte (@commit@), utiliser le
nom d’un sous répertoire ;

*
fichier @~/.gitignore@. Exemple d'un fichier @~/.gitignore@ :
<pre>
# ignorer
le reste des caractères sont le nom du fichier.

Connaître l’identifiant du dernier commit est suffisant pour remonter
fichier lui même
l’arbre généalogique. .gitignore
# les fichiers de sauvegarde VIM
*~
# ignorer les fichiers html générés
*.html
# sauf mon_fichier.html que je veux prendre en compte
!mon_fichier.html
# ignorer les dossiers @.svn@
.svn
# ignore documentation buid html files
.build
</pre>


Faire une nouvelle branche se résume donc à créer un * Le fichier ne @~/.gitconfig@ peut permettre d'éviter de taper trop au clavier :
contenant qu’un identifiant. <pre>
[alias]
st = status
di = diff
co = checkout
ci = commit
br = branch
sta = stash
</pre>


On créé une branche dédiée pour le développement * Pour éviter de taper l'URL et son mot de passe à faire : chaque @push@ et @pull@, il faut :

* configurer l'URL du projet

<pre>
moi@work:~/src/projet(master)$

git checkout -b issue/42 master config remote.origin.url http://194.167.18.22/git/projet/
git config remote.origin.mirror false
</pre>

h2. Le clonage déontologiquement correcte

Afin de tester nos modifications avant publication, nous pouvons

* renseigner le fichier @~/.netrc@ :

copier les fichiers sur une <pre>
machine de test, par quelque moyen que ce dev-eole.ac-dijon.fr
soit.

Un
login monlogin
password monmotdepasse
</pre>
* paramétrer les droits du fichier @~/.netrc@ :
<pre>
chmod 600 ~/.netrc
</pre>
Ensuite @git push@ et @git pull@ ne posent plus
de ces moyens, et questions.

* Pour faire
le plus simple dans notre cas, est d’utiliser ménage :
git. <pre>
git repack
git prune
</pre>


Étant donné que :

* Nous souhaitons tester les modifications apportées par le
développement enregistré
Pour repérer des @commit@ dans une des branches qui n'ont pas été fusionnés (@merge@) dans la branche non publiée ;

principale :
* Nous ne souhaitons pas publier cette Pour voir les @commit@ dans la branche privée tant que tout ne
sera
*ma_branche* qui n'ont pas propre ;

Nous allons créer une copie conforme de notre dépôt, sur la machine de test.

Le fonctionnement est simple, un dépôt git, qu’il soit sur un serveur
été fusionnés (@merge@) dans *master* :
<pre>

http ou dans notre répertoire, peut servir de base à un clone. git cherry -v master ma_branche
</pre>


Et un clone, ça peut se faire par "SSH":http://fr.wikipedia.org/wiki/SSH.

Nous avons besoin :

* D’une machine de test ;

*
h1. De l’outil subversion vers git installé sur cette machine ;

* D’un accès "SSH":http://fr.wikipedia.org/wiki/SSH sur cette machine.

Aucun
Il n'existe pas de commande *@update@*. Lorsqu'un fichier ne sera éditer sur cette machine, cela évite de
s’éparpiller.

Nous mettrons à jour ce dépôt
a été modifié localement par des pull, ce qui ne posera aucun erreur et qu'on veut récupérer l'original, les habitudes étaient :
soucis comme expliqué plus haut du fait qu’il n’y aura aucune <pre>
modification locale à rm mon_fichier
svn update
</pre>

A
la machine de test.

place, il faut faire
<pre>
moi@work:~/src/projet(master)$ ssh user@test-machine
user@test-machine:~$

git clone ssh://moi@work/home/moi/src/projet && cd projet
user@test-machine:~/projet(master)$ git
checkout -b issue/42 origin/issue/42
user@test-machine:~/projet(issue/42)$ # On est prêt
mon_fichier
</pre>

Pour revenir à un checkout frais dans le projet entier, utiliser *@reset@*. On garde peut annuler un shell sur la machine de test, on y reviendra souvent, à commit en faisant :

<pre>

moins d’être très fort et de tout réussir du premier coup. git reset --hard HEAD
</pre>


h2. Les commits, c’est radioactif ? h1. De bazaar vers git

Un commit, c’est Il est possible de suivre un instantané du code projet [[bzr depuis git]] grâce à un instant « T ». plugin.

Si nous souhaitons tester l’impact de chaque commit sur Certains logiciels sont ainsi suivi au sein du projet EOLE.

h1. Créer
un projet, il
est préférable que chacun d’eux soit fonctionnel.
patch et l'intégrer

Par exemple, si Dans un projet (Ex.: conf-horus) on modifie le nom d’une fonction ou d’une variable, a créé une branche "ma_branche" dans laquelle on
doit, dans le même commit, modifier tous
a fait des modifications (par rapport à "master").

On veut récupérer un fichier recensant
les utilisations de l’ancien différences entre la branche *master* et la branche *ma_branche* (un fichier @diff@) :
nom. <pre>
git diff master [nom-de-branche] > file.patch
</pre>


Chaque commit se doit d’être * Une fois le plus « atomique » possible. patch récupéré, pour l'inclure dans la branche *master* :

h2. Cycle de développement et tests

# On code :
<pre>
moi@work:~/src/projet(issue/42)$ ${EDITOR} src/bidule.py
moi@work:~/src/projet(issue/42)$

git add src/bidule.py
moi@work:~/src/projet(issue/42)$
apply --stat file.patch
git commit
apply --check file.patch
</pre> permet de tester le patch, et :
# On nettoie la machine de test :
<pre>
user@test-machine:~/projet(issue/42)$ make uninstall
</pre>

# On met à jour le dépôt de la machine de test :
<pre>
user@test-machine:~/projet(issue/42)$
git pull origin
</pre>
apply file.patch
# On met en place la nouvelle version du code à tester :
<pre>
user@test-machine:~/projet(issue/42)$ make install
</pre>
# On test, si
permet de l'appliquer

h1. Tags

*git* fait une différence entre les branches et les tags, cela se voit bien avec *git-gui* (vue de l'historique
des problèmes persistent, on boucle sur 1. branches).

h2. Publication Une branche est modifiable, un tag ne l'est pas.

* Création
du développement

# On nettoie notre histoire privée :
@tag@ :
<pre>
moi@work:~/src/projet(issue/42)$

git rebase -i $(git merge-base master HEAD)
tag mon-premier-tag
</pre>

* Liste des tags :

# On rebase sur la dernière version de la branche publique :
<pre>
moi@work:~/src/projet(issue/42)$

git fetch origin
moi@work:~/src/projet(issue/42)$ git rebase origin/master
tag
</pre>

* Commit d'un @tag@ :

# On intègre à la branche publique :
<pre>
moi@work:~/src/projet(issue/42)$

git checkout master
moi@work:~/src/projet(master)$ git merge issue/42
push --tags http://login@dev-eole.ac-dijon.fr/git/sandbox
</pre>

* ou bien :

# On tag un numéro de version :
<pre>
moi@work:~/src/projet(master)$

git tag -s -m "release/$(date +%Y%m%d.%H%M)" release/$(date +%Y%m%d.%H%M)
push http://login@dev-eole.ac-dijon.fr/git/sandbox <nom_tag>
</pre>

* ou encore :

# On publie :
<pre>
moi@work:~/src/projet(master)$

git push origin
http://login@dev-eole.ac-dijon.fr/git/sandbox <nom_branche> <nom_tag>
</pre>

h1. TODO Bonnes pratiques de packaging, par moi©®™


h2. Une branche pour tester

h2. Merci git-buildpackage pbuilder

h2. Publication du packaging

h1. Webographie

* "Avoiding Git Disasters: A Gory Story":www.randyfay.com/node/89 Recupérer un @tag@ :
* "A rebase workflow":http://www.randyfay.com/node/91 <pre>
* "Simpler Rebasing (avoiding unintentional merge commits)":http://randyfay.com/node/103
* "A
git workflow for agile teams":http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html checkout tags/<nom_tag>
</pre>

* "The case for git rebase":http://darwinweb.net/articles/the-case-for-git-rebase Pour voir quel @commit@ exactement a été taggé :
* "Pro <pre>
git book":http://progit.org/book/ch5-3.html show <nom_tag>
* "Maintaining a project":http://progit.org/book/ch5-3.html
* "Packaging software using Git":http://www.golden-gryphon.com/software/misc/packaging.html
* "Packaging with git":http://wiki.debian.org/PackagingWithGit/
</pre>