Licence
Licence
Introduction
Programme
Programme
Contenu de la formation
- connaître les principaux workflows de développement
- utiliser git avec un dépôt local
- utiliser git avec un dépôt distant
- utiliser gitlab pour mettre en place son workflow
Source du contenu
- man git (gittutorial, gitworkflows)
- Pro Git 2
- Tower Git Cheat Sheet
- Git Internals Vimeo
- Pygit2
- Gitlab documentation
- StackOverflow
- Mon expérience
Mon expérience
Mon expérience
- Taille des projets : de 1 à 12 personnes (professionel) ou contribution épisodique à de gros projets open-source (professionel ou amateur)
- Ingénieurs / Chercheurs / Utilisateurs
- Culture Calcul Scientifique et Web
Structure de la journée
Structure de la journée
Feedback
Feedback
- Est-ce qu’il y a un point dans de ce qui a été évoqué qui vous intéresse particulièrement (workflow, commandes locale, distante, gitlab, aucun)
- Est-ce qu’il y a un point qui n’a pas été évoqué et pour lequel vous êtes spécialement venu ?
Avertissement
Avertissement
- N’hésitez pas à m’interrompre si un terme, une commande, un processus n’est pas clair !
Concepts et premières commandes
Gestion de Version
Principes
- enregistre l’évolution d’un fichier ou d’un ensemble de fichiers afin de :
- suivre l’évolution
- rappeler une version antérieure
- diffuser les changements auprès des autres développeurs
Historique
0eme |
À l’Arrache |
cp -r data/ data.old/ |
1ere |
Modèle Local |
RCS (1982) - SCSS - … |
2eme |
Modèle Centralisé |
CVS (1990) - SVN (2000) - … |
3eme |
Modèle Distribué |
GIT (2005) - Mercurial - … |
source : http://ericsink.com/vcbe/html/history_of_version_control.html
Modèle Local
Modèle Centralisé
Modèle Distribué
Démonstration du modèle décentralisé
cd /tmp
mkdir code
cd code
git init
echo "Hello World !" > README.txt
git add README.txt
git commit -m "first commit"
cd ~
git clone /tmp/code/
cd code
pwd
Git
Introduction
- git est un logiciel :
fin-2005 |
git 1.0 |
2008 |
création github |
2010 |
git flow (nvie) |
2011 |
création gitlab |
2012 |
déploiement gitlab @digiplante |
début-2014 |
git 2.0 |
mi-2014 |
déploiement gitlab.ecp.fr |
présent |
git 2.4.1 |
- qui est découpé en plusieurs sous-programme (git-add, git-commit, …)
- qui se configure
- qui établit un certain nombre de concepts afin de manipuler plus facilement l’ensemble
- qui fonctionne presque entièrement de manière locale (à l’exception de clone, fetch, push, pull notamment)
Sous-Programmes et Aide
- Toutes les commandes ont un man très bien fait.
- Il y a en plus des man relatifs à l’utilisation :
- man gittutorial
- man gittutorial2
- man giteveryday
- man gitworkflows
- man gitglossary
- disponible sur le net
- grande communauté
- en règle générale on trouve toujours une réponse sur stackoverflow par rapport à son utilisation
Concepts
Contenu
- La notion de contenu est importante car si dans les anciens gestionnaires de version il y a une identification entre contenu et fichier, ce n’est plus le cas avec git. Ce dernier permet de descendre au niveau de la ligne de texte et faire des mix entre des lignes de textes présentes dans des fichiers différents.
Lieux
- le dossier .git (.git repository)
- le dossier de travail (working tree)
- l’index (index - staging area)
États
- validé (stocké dans la base locale)
- modifié (pas encore validé)
- indexé (en attente dans l’index pour le prochain commit)
Exemple de cycle classique
Petit Lexique
- master le nom de la branche créée par défaut son nom n’a aucune importance et peut être changée dès le début
- branche un pointeur vers un commit
- commit un sha1 qui permet d’accéder à des donnés que git sait extraire dans le répertoire de travail
- sha1 un identifiant unique au sein d’un projet
- HEAD un pointeur sur la branche en cours
Premières Commandes
git-config
git-init
- initialise le dépôt git dans le dossier en cours si aucun nom sinon crée un dossier
- on aura donc :
- un dossier .git
- un répertoire de travail (working directory)
- un moyen de passer de l’un à l’autre grâce à la manipulation de la zone d’indexation visible avec git-status
- options intéressantes
- –bare (on décrira cette option au moment des pull/push)
git-add
- il faut bien garder à l’esprit que git versionne des instantanés du contenu et non pas des fichiers
- add rajoute du contenu dans le prochain commit
- options intéressantes
- -u mettre dans l’index les fichiers déjà validé une fois (mieux que git add .)
- –patch (-p) pour commiter de super commits
git-commit
- options intéressantes
- -m <message> permet de passer le message de commit dans la ligne de commande au lieu d’ouvrir un éditeur
- -a permet de mettre dans l’index les fichiers déjà validé une fois automatiquement s’utilise bien avec -am <message>
- –dry-run
git-log
- git-log
- options intéressantes
- –graph
- –decorate
- –since/after
- –extended-regexp –regexp-ignore-case –grep <pattern> (en plus court -E -i –grep)
- –author=<email>
- –patch
- –stat
Marqueurs
- sha1^ veut dire un commit avant sha1
- sha1^^ veut dire 2 commits avant sha1
- sha1~N veut dire N commits avant sha1
double dot
- A..B signifie “atteignable par B mais pas par A”
git log master..experiment
git log experiment --not master
D
C
git log experiment..master
git log experiment --not master
F
E
triple dot
- … signifie “atteignable par A et B mais pas les deux”
git log master...experiment
F
E
D
C
git-diff
- options intéressantes
- -b, –ignore-space-change
- -w, –ignore-all-space
- –ignore-blank-lines
- stat
git-status
- status permet d’avoir un aperçu des différents états en cours et de comprendre ce que l’on a dans l’index
- options intéressantes
.gitignore
- .gitignore est un fichier spécial dans lequel vous pouvez mettre des patterns qui seront exclus du versionnement
- peut être surchargé par –ignored sur git status
Branch - Checkout
git-branch
git-branch
- une branche est un pointeur sur un commit
- cette commande permet de créer une branche mais est souvent surchargée par git checkout -b
- options intéressantes:
- -a affiche toutes les branches
- -D supprime une branche
cd depot
git checkout -b iss53
git commit
git checkout master && git checkout -b hotfix && git commit
git checkout master && git merge hotfix
git branch -D hotfix
git-checkout
git-checkout
- permet de changer le HEAD sur un commit en particulier
- ce commit peut être donné par son sha1 ou alors le nom de la branche
- si c’est un commit on passe alors en “detached state”
- sinon on est sur une branche
git-stash
git-stash
- la stash est un lieu où l’on peut mettre temporairement du travail afin de ne pas créer un commit spécialement pour lui
- exemple
- vous travaillez sur une branche
- un rapport de bug arrive
- vous stashez votre travail et changer pour la master
- vous faites une branche pour corriger le bug
- vous merger
- vous revenez sur votre branche de départ
- vous réappliquez la stash
git-reset
git-reset
- permet de remettre la branche en cours sur un commit en particulier
- reset possède 3 modes : soft, mixed (par défaut), hard
- soft : revient à l’état “changes to be commited”
- ça peut s’appliquer à une situation “ah mince j’ai oublié d’ajouter ce fichier dans le commit”
- mixed : reset l’index (il n’y a plus rien) mais ne touche pas au working tree
- ça peut s’appliquer à une situation “mince je viens de compiler et tester ça tourne pas car j’ai oublié de préciser ce petit truc”
- hard : reset l’index et le working tree
- ça peut s’appliquer à une situation “bon je devais pas être bien réveiller”
git-reset soft
git-reset mixed
git-reset hard
git-reflog
git-reflog
- Garde en mémoire les évènement git
- Permet par exemple de retrouve un commit perdu à cause d’un git-reset trop vite fait
git-revert
git-revert
- annule un commit en un créant un autre
- les + deviennent des - et inversement
- s’applique surtout pour des commits déjà partagés (pusher)
git-tag
git-tag
- permet de tagger une version en particulier avec un nom spéficique
- cela ne rentre pas dans le namespace des branches
- idéal pour gérer des versions de type X.Y.Z
- idéal pour tagger une version d’un logiciel qui a servi à produire un papier scientifique
Merge - Rebase
git-merge
git-merge
- un merge se fait sur une branche et la fussione avec une autre en ajoutant un commit de merge
- de temps en temps ce merge sera fast-forward (sans commit de merge) car la branche hôte n’a pas évolué depuis la bifurcation
- c’est le mécanisme le plus répandu
- c’est sécurisé comme méthode
- la seule contrainte c’est les conflits mais c’est normal :)
Précautions
- Un merge c’est prendre le travail d’une branche et le fusionner avec la branche en cours
- Merger quand tout est bien validé dans les différentes branches.
- Ne pas laisser des choses en état modifié en attente cela peut causer des ennuis difficiles à réparer
Avant le merge
Après le merge
git checkout master
git merge iss53
Cas particulier
- evil merge introduire des changements qui n’ont aucun parent (ex: ajout de modifications alors que –no-commit)
- octopus plusieurs merge en même temps
- conflits
- 1:file ancetre commun
- 2:file nos modifications
- 3:file modifications de la branche mergée
–abort
- fast-forward
- ne produit pas de commit de tête car l’ancetre commun est toujours le HEAD de la branche qui attend la branche à merger.
Options intéressantes
- –dry-run simulation
- –abort annule merge en cours si ce n’est pas un fast-forward (pratique en cas de conflit)
- –squash squash tous les commits de la branche en un
- –no-commit ne crée pas le commit de merge
- –no-ff n’accepte pas le fast-forward automatiquement
Conflits
- git show 1:file
- git show 2:file
- git show 3:file
- git checkout –theirs file
- git checkout –ours file
- git add & git commit
git-cherry-pick
git cherry-pick
- le cherry-pick est une sorte de mini-merge puisque l’on descend au niveau du commit
- on peut donc prendre un commit de n’importe quelle branche et le réappliquer sur une autre
- il faut que le commit soit “cohérent” bien évidemment
git-rebase
git-rebase
- le rebase permet de prendre une branche et de la dérouler à partir d’un point donné plus haut
- cela permet notamment de faire des fast-forward plus facilement et donc d’éviter les commits de merge
- cela rend plus lisible l’historique MAIS cela a des inconvénients
- ON NE REBASE JAMAIS UN CODE DÉJA PUSHÉ
- tous les sha1 de la branche changent dans un rebase
- s’il y a des conflits on les corrige au fur et à mesure du rebase
- options intéressantes
- –abort annule le rebase
- –continue continue le rebase après résolution des conflits
- -i permet de faire un rebase interactif
Clone - Fetch - Push - Pull
git-clone
git-clone
- Jusqu’à présent nous n’avons travaillé qu’en local
- Supposons que quelqu’un nous donne son adresse de dépôt
- Nous en obtenons une copie locale avec : git clone git@git.site.tld:/projet.git
- options intéressantes : – single-branch
git-remote
git-remote
- remote permet de gérer les dépots distants et notamment d’en ajouter ou d’en supprimer
- git remote add benoit git@git.site.com:/projet.git
- git remote rename origin public
- git remote rename benoit private
git-fetch
git-fetch
- fetch est une commande absolument indispensable à comprendre quand on travaille avec des dépôts distants
- elle télécharge l’historique distants des branches et les places dans le dossier .git/objects avec des pointeurs dans .git/refs/remotes
- options intéressantes
git-push
git-push
- envoie les nouveaux historiques sur les dépots distants
- git push -u origin master:master
- git push origin master:master
- git push origin master
- git push origin master:toto
- git push origin :toto
git-pull
git-pull
- pull est une commande qui effectue un fetch et un merge automatiquement
- c’est une commande très utilisée mais avec le temps je lui préfère un pull et un merge à la main
- je prèfère apprendre aux personnes le fetch + merge plutôt que le pull qui est un peu “illusoire”
- git pull origin master
Workflow et Gitlab
Workflow
Workflow
- Un workflow ou flux de travail est le processus décrivant les interactions entre les différentes entités permettant la mise au point d’un code et son déploiement.
- Un workflow est un modèle de travail idéal. La plupart des activités de développement tombent dans le cadre d’un workflow.
- Workflow types
- développeur isolé
- équipe de développeurs avec un seul dépôt
- équipe de développeurs avec plusieurs dépôt
- équipe de développeurs avec plusieurs dépôt et un dépot officiel d’intégration
- Savoir reconnaître un workflow est très important MAIS savoir reconnaître quand ne pas l’appliquer ou le transformer est encore plus important.
- Faire la distinction entre faire la chose correcte et faire correctement la chose.
- Il y a une notion de masse critique dans l’utilisation d’un workflow.
- Il faut aussi connaître les gens avec qui vous travaillerez avant de l’appliquer lorsque vous êtes sur des petites tailles (compétences, inertie et résistance au changement, …)
Vision globale
- Workflow Idéal :
- Sélection des nouveaux éléments à developper (Scrum // Kanban)
- Écriture des tests d’acceptation en groupe avec le responsable architecture (Boost.Test)
- Écriture du code avec en parallèle écriture de tests unitaire et commits (C++ / Boost.Test / Git)
- Publication sur un dépôt distant (Git // Gitlab)
- Récupération du code par automate (Gitlab CI // Jenkins)
- Compilation et passage des tests
- Si ok déploiement sinon refus (Ansible // Docker)
- Dans l’idéal le flux de travail va de l’écriture du code à sa livraison sous forme de programme testé et validé.
- On distingue différents outils pour arriver à cette fin :
- Gestion de version
- Intégration continue
- Déploiement Continu
- Script
- Docker / Vagrant
- Ansible / Chef / Puppet
Exemple :
Cycle général
Centralisé
Moyen Projet
Gros Projet
Gitlab
Présentation Générale
- Gitlab est un logiciel orienté web qui permet de stocker et manipuler des dépôts git sur un serveur
- Il y a en plus des outils de communication comme un wiki, la possibilité de mettre des snippets, de le connecter à d’autres services.
Utilisation
- se logger
- créer un dépôt
- README
- cloner le dépôt
- pusher
- forker
- merge request
- issue
Comparaison à Github
- Pourquoi choisir Gitlab plutôt que Github, ou l’inverse ?
- Github est un logiciel de type Saas qui est gratuit pour du code publié à tous et payant pour avoir des dépôts privés. L’ensemble des données est hébergé chez Rackspace. On peut avoir un github au sein d’un réseau privé à travers leur offre github entreprise.
- Gitlab est logiciel libre de type Saas qui est gratuit du moment que l’on installe sur une instance en privé L’ensemble des données est hébergé sur vos serveurs. On peut héberger les données chez eux à travers une offre.
- Je pense que pour un projet libre et afin de garantir sa diffusion github est une très bonne plateforme. Néanmoins si l’on travaille sur des codes “internes” ou du moins dont on ne connait pas encore le type de diffusion ou qui fait intervenir des données privés ou sensibles, Il est important d’héberger l’ensemble sur une plateforme permettant de rester “maître” de ce qui se passe. Du coup Gitlab est une bonne alternative du fait de son faible cout mais github le permet aussi à travers Github Entreprise. Bien sur cela est à mettre en regard de la qualité de service du réseau interne en terme d’infrastructure (aide aux utilisateurs, sauvegarde automatique, …)
Aller plus loin
Alias
Hooks
- Un hook est un script écrit en bash, python, perl, … qui est déclenché à certains moments dans le flux git. Il peut être déclenché sur le dépôt local, ou sur le dépôt distant.
Submodule
- Les submodules sont un moyen d’intégrer des éléments de tierce-partie étant nécessaire au projet mais n’étant pas dans le cadre du projet i.e les développeurs utilisent la chose mais ne la développe pas.
Annexes
- Comment sauvegarder de grands jeu de données (souvent binaires) comme les images, les BDs, … qui doivent accompagné le projet dans son développement ?
- On ne veut pas les versionner de la même façon car sinon cela fait exploser la taille du dépôt.
- Exemples :
- données HDF5 d’une expérience de mécanique des fluides
- données excel
Gitlab Plugins
- Comment ajouter de nouveaux services ?
Gitlab CI
- Gitlab CI est un logiciel fait pour l’intégration continue
Gitlab API
- interrogation du serveur à distance pour rapatrier, modifier, ou ajouter des données avec une API REST
curl \
--header "PRIVATE-TOKEN: dfldfkdlgkdlgkdfl" \
https://gitlab.ecp.fr/api/v3/projects/261/issues
curl \
-H "Content-Type: application/json" \
--header "PRIVATE-TOKEN: dfldfkdlgkdlgkdfl" \
-X POST \
--data '{"title":"parser does not work with csv","description":"when using file x.csv I can not have any result"}' \
https://gitlab.ecp.fr/api/v3/projects/261/issues
Récapitulatif
Création
Création
- Cloner un répertoire existant
git clone ssh://user@domain.tld/repo.git
- Cloner un répertoire existant avec ses sous-modules
git clone --recursive ssh://user@domain.tld/repo.git
- Créer un nouveau dépôt local
Changement locaux
Changement locaux
- List changed files in your working directory
- List changes to tracked files
- Add all current changes to the next commit
- Add some changes to the next commit
- Commit all local changes in tracked files
- Commit previously staged changes
- Note: You shouldn’t amend published commits!
Historique des commits
Historique des commits
- Show changes over time for a specific file
- Show changes over time for a specific committer
git log --author=<committer name>
Note: <committer name> is a pattern, so Ed will match Edward Smith. Quotes are optional if the pattern doesn’t contain spaces.
- Who changed what and when in file
- Store changes temporarily
- Remove and apply stashed changes
- List all existing branches
- Create a new branch based on your current HEAD
- Create a new tracking branch based on a remote branch
git branch --track <new-branch> <remote-branch>
git push origin --delete <branch>
Mise à jour & Publication
Mise à jour & Publication
- List all currently configured remotes
- Show information about a remote
- Add new remote repository
git remote add <remote> <url>
- Download all changes from remote, but don’t merge into HEAD
- Download all changes from remote, but don’t merge into HEAD and clean up deleted branches from origin
- Download changes and directly merge into HEAD
git pull <remote> <branch>
- Publish local changes on a remote
git push <remote> <branch>
- Track a remote repository
git remote add --track <remote-branch> <remote> <url>
Merge & Rebase
Merge & Rebase
- Merge branch into your current HEAD
- Rebase your current HEAD onto branch
Note: You shouldn’t rebase published commits!
- Continue a rebase after resolving conflicts
- Resolve conflicts using your configured merge tool
- Manually resolve conflicts using your editor and mark file as resolved
Annuler
Annuler
- Discard all local changes in your working directory
- Discard local changes in a specific file
- Revert a commit by providing a new commit with contrary changes
- Restore a specific file from a previous commit
git checkout <commit> <file>
- Reset your HEAD pointer to a previous commit
- Discarding local changes:
git reset --hard <commit>
- Preserving all changes as unstaged changes:
- Preserving uncommitted local changes
git reset --keep <commit>
Glossaire
checkout
The action of updating all or part of the working tree with a tree object or blob from the object database, and updating the index and HEAD if the whole working tree has been pointed at a new branch.
commit
As a noun: A single point in the Git history; the entire history of a project is represented as a set of interrelated commits. The word “commit” is often used by Git in the same places other revision control systems use the words “revision” or “version”. Also used as a short hand for commit object.
As a verb: The action of storing a new snapshot of the project’s state in the Git history, by creating a new commit representing the current state of the index and advancing HEAD to point at the new commit.
evil merge
An evil merge is a merge that introduces changes that do not appear in any parent.
fast-forward
A fast-forward is a special type of merge where you have a revision and you are “merging” another branch’s changes that happen to be a descendant of what you have. In such these cases, you do not make a new mergecommit but instead just update to his revision. This will happen frequently on a remote-tracking branch of a remote repository.
merge
As a verb: To bring the contents of another branch (possibly from an external repository) into the current branch. In the case where the merged-in branch is from a different repository, this is done by first fetching the remote branch and then merging the result into the current branch. This combination of fetch and merge operations is called a pull. Merging is performed by an automatic process that identifies changes made since the branches diverged, and then applies all those changes together. In cases where changes conflict, manual intervention may be required to complete the merge.
As a noun: unless it is a fast-forward, a successful merge results in the creation of a new commit representing the result of the merge, and having as parents the tips of the merged branches. This commit is referred to as a “merge commit”, or sometimes just a “merge”.
origin
The default upstream repository. Most projects have at least one upstream project which they track. By default origin is used for that purpose. New upstream updates will be fetched into remote- tracking branches named origin/name-of-upstream-branch, which you can see using git branch -r.
push
Pushing a branch means to get the branch’s head ref from a remote repository, find out if it is a direct ancestor to the branch’s local head ref, and in that case, putting all objects, which are reachable from the local head ref, and which are missing from the remote repository, into the remote object database, and updating the remote head ref. If the remote head is not an ancestor to the local head, the push fails.
rebase
To reapply a series of changes from a branch to a different base, and reset the head of that branch to the result.
ref
A name that begins with refs/ (e.g. refs/heads/master) that points to an object name or another ref (the latter is called a symbolic ref). For convenience, a ref can sometimes be abbreviated when used as an argument to a Git command; see gitrevisions(7) for details. Refs are stored in the repository.
The ref namespace is hierarchical. Different subhierarchies are used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches).
There are a few special-purpose refs that do not begin with refs/. The most notable example is HEAD
reflog
A reflog shows the local “history” of a ref. In other words, it can tell you what the 3rd last revision in this repository was, and what was the current state in this repository, yesterday 9:14pm.
remote-tracking branch
A ref that is used to follow changes from another repository. It typically looks like refs/remotes/foo/bar (indicating that it tracks a branch named bar in a remote named foo), and matches the right-hand-side of a configured fetch refspec. A remote-tracking branch should not contain direct modifications or have local commits made to it.
tag
A ref under refs/tags/ namespace that points to an object of an arbitrary type (typically a tag points to either a tag or a commit object). In contrast to a head, a tag is not updated by the commit command. A Git tag has nothing to do with a Lisp tag (which would be called an object type in Git’s context). A tag is most typically used to mark a particular point in the commit ancestry chain.
working tree
The tree of actual checked out files. The working tree normally contains the contents of the HEAD commit’s tree, plus any local changes that you have made but not yet committed.