Git pour Ops, par un Ops

Git est un logiciel de contrôle de code source déjà très utilisé dans le monde des dev. Lorsque l'on fait de l'Infra as Code, nous pouvons aussi utiliser git, je pense même que cela va devenir une vraie nécessité. Pour nous les Ops, ce n'est pas nécessairement naturel et j'ai donc décidé de démystifier git dans un contexte Cloud comme Azure.

Afin de suivre ce billet, vous devez installer quelques outils sur votre poste de travail afin de pouvoir tester par vous-même.

Je vous invite également à lire ces articles :

Sur le poste de travail

Sur un poste Windows vous devez installer à minima :

  • Visual Studio Code
  • Git-SCM

Vous pouvez utiliser chocolatey :

Write-Output "Installation of Chocolatey"
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1’))
$packages = ('
VisualStudioCode', 'vscode-powershell', 'vscode-markdownlint', 'vscode-azurerm-tools', 'vscode-gitlens', 'azure-cli', 'AzurePowerShell', 'git', 'terraform')
Choco upgrade $packages -y

Sur macOs :

  • Visual Studio Code
  • git

Un serveur Git

Vous pouvez utiliser VSTS ou GitHub.

Repo sur GitHub

Une fois votre compte actif, créez un repository Git via le bouton vert "Create Repository"

Repo sur Vsts

J'ai déjà publié un article concernant vsts ici

Git en SSH

Afin d'avoir accès à VSTS ou à GitHub depuis un bash Windows ou Linux, il faut générer une clé SSH :

Je vous recommande vivement l'utilisation de bash pour git et la suite de cet article. Si vous n'avez pas encore installer bash sur votre Windows, installer le puis suivez cet article : Open Source + Windows = Vs Code + Bash + Git

mkdir -p ~/.ssh
ssh-keygen -f ~/.ssh/vsts
cat vsts.pub

Ouvrez VSTS ou Git puis :

Cliquez sur "Add" et collez la clé publique.

Ensuite ajoutez la clé dans l'agent ssh :

ssh-agent bash
ssh-add ~/.ssh/vsts

Where to start

Lorsqu'on commence à travailler avec git, il est possible d'utiliser deux méthodes, soit on clone le repo distant, soit on ajoute le repo distant comme source.

Les commandes de Git

Clone ou Remote

Pour faire un clone ou ajouter un repository distant, il suffit de récupérer l'url disponible dans l'interface de GitHub ou de VSTS puis avec cette url :

  • Clone
git clone https://xxxx/git.git
# ou avec la belle cle ssh :
git clone ssh://

Le clone est utilisable lorsque notre projet est vide, ou qu'il n'est pas encore present dans la machine de travail (reinstallation, pc fixe de la maison...)

  • Remote

Cette méthode est plus complexe et pas forcément nécessaire, il est juste intéressant de la connaitre.

git remote add origin url
git commit . -m "inital commit"
git push origin master
git add --all
git commit . -m "add exisiting file in the remote repo"
git push origin master

Le remote est utilisable si le projet est déjà sur la machine et que le repository distant n'existe pas encore.
Je vous conseille de bien faire un premier commit "vide" puis d'ajouter les fichiers (git add --all) puis à nouveau d'envoyer les fichiers.

Ajouter/Supprimer des fichiers à l'index

Avec Git, quand on créer un nouveau fichier, par défaut il n'est pas forcément ajouté à l'index, c'est à dire qu'il ne sera pas envoyé au server lors d'un git push.

  • Ajout de fichiers
git add ./monchemin/monfichier
# ou un dossier complet :
git add ./mondossier/

Attention, git ne prendra jamais un dossier vide, il ne le prendra que si un fichier meme vide est present.

  • Suppression de fichiers

Je ne suis pas responsable de vos fichiers perdus ;)
Lorsqu'on supprime un fichier du repertoire local, il n'est pas supprimé de l'index de git sans faire la commande :

git rm ./monchemin/monfichier --cached

Commit

Afin d'ajouter nos fichier dans l'index en attente, il est nécessaire de valider ces fichiers, un peu comme en base de données Commit, Execute, Rollback, en cas de soucis.

git commit -m "le message du commit en fonction de votre travail... (pensez à vos collègues !"

Pull ou Fetch

Avant de valider ce commit sur le server, il est important de vérifier si on est bien raccord avec le canal "upstream", c'est à dire le serveur distant.

  • Pull

    git pull

    Git pull en réalité, c'est un git fetch puis un git merge FETCH_HEAD, pour gagner du temps.

  • Fetch

    git fetch

Git fetch permet de récupérer les commits distants qui on eu lieu de puis le dernier fetch. En effet, sans faire de pull ou de fetch, le server distant et local on des versions différentes des index (et donc des fichiers).

Git push

Afin de partager votre travail avec vos collègues, vous devez envoyer vos modifications sur le server (si, si, si).
Il y a plusieurs façons de travailler avec git, mais lorsqu'on est dans une branche de travail (et pas de prod!) nous pouvons faire un push :

git push

Git branch

Avec git, l'idéal c'est de créer des branches pour le travail et pour la production, a minima.
Pour avoir un idée de ce qui existe, regader Git Flow, GitHub Flow

  • la premiere branche :

    git checkout -b v0
  • puis les autres :

    ##support d'aws
    git checkout -b v0-aws
    ##support d'azure
    git checkout -b v0-azure

Git checkout

La commande git checkout permet de se changer de branche de travail. C'est à dire que si nous faisons la commande git checkout masuperfeature, les fichiers et les dossiers seront ceux de la branche en question. Faisons donc un petit exercice pour bien comprendre comment cela fonctionne :

Vous pouvez créer un repository git local sans server pour cet exercice, c'est que j'ai fais moi même et par conséquent je n'utilise pas les commande git push et git pull pour simplifier cet exercice.

# on se place dans la branche master
git checkout master
# on creer un fichier vide :
touch monfichier.txt
# on l'ajoute au "stage" :
git add monfichier.txt
# puis on commit :
git commit -m "mon commit dans master"
# puis on change de branch, le -b permet de créer la branche si elle n'existe pas encore
git checkout -b manouvellebranche
# on valide qu'elle est bien a jour par rapport au serveur
ls
# qui nous retourne :
monfichier.txt

Maintenant, ajoutons un fichier dans cette nouvelle branche :

touch monfichier2.txt
git add monfichier2.txt && git commit -m "mon commit dans manouvellebranche"

Retournons dans la branche "master" :

# on change vers master
git checkout master
# on creer un nouveau fichier :
touch monfichiermaster.txt
git add monfichiermaster.txt && git commit -m "ajout du fichier dans master"
ls
# nous retourne :
monfichier.txt monfichiermaster.txt
# si nous retournons dans la branche manouvellebranche :
git checkout manouvellebranche
ls
monfichier2.txt monfichier.txt

Conclusion: les branches permettent d'isoler le travail sans se mélanger entre collègues ou entre features.

Git rebase

Il est assez fréquent de travailler sur plusieurs branches en parallèle et qui nous oblige lors de modification importante dans la branche principale de faire "redescendre" les modifications de la branche "master" (ou celle qui a servi de base à la création). Nous allons voir comment récupérer ces modifications dans notre branche "manouvellebranche" :

git checkout manouvellebranch
ls
git rebase master
git checkout manouvellebranch
First, rewinding head to replay your work on top of it...
Applying: mon commit dans manouvellebranche

Git Merge

Une fois que notre feature est prête, il peut être intéressant de migrer le travail dans la branche "mère". Dès lors nous allons pouvoir "merger", il existe plusieurs façon de merger, soit on merge tout avec l'historique de chaque commit dans la branche "mère", soit on merge sans l'historique, rassembler dans un seul commit, je préfère cette option afin de ne pas polluer l'historique de la branche de "production" :

# ajoutons quelques fichiers dans la branche manouvellebranche
touch toto{0..9}{0..9}.txt
git add toto*
git commit -m "adding 100 files"

Ensuite, changeons de branche puis effectuons un merge, simple (le moins bien):

git checkout master
git merge manouvellebranch

Et si je me suis trompé ?

# d'abord on vérifie l'id du commit : (-B permets de récupéré 6 lignes de avant le contexte, -A la meme chose mais apres le contexte)
git log | grep -B 6 -A 6 adding

commit 126d0fe758ebb8b7c155d58968063edec996a673
Author: Etienne Deneuve <etienne.deneuve@cellenza.com>
Date: Thu Jun 28 13:07:27 2018 +0200

adding 100 file

commit c9323cb10debb1a0a028f9e7db65a622fb8906a1
Author: Etienne Deneuve <etienne.deneuve@cellenza.com>
Date: Thu Jun 28 12:27:02 2018 +0200

mon commit dans manouvellebranche
# puis on annule notre commit en prenant celui juste avant notre erreur :
git reset c9323cb10debb1a0a028f9e7db65a622fb8906a1
git status
On branch master
nothing to commit, working tree clean

Cela tombe, bien nous allons pouvoir faire le deuxième merge (le mieux):

git checkout master
git merge --squash manouvellebranch
git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)

new file: toto00.txt

new file: toto99.txt
# dès lors, nous devons commiter:
git commit -m "oui, c'est bon on y va !"

Voilà, vous savez maintenant utiliser les bases de git, je vous invite à poursuivre avec Open Source + Windows = VS Code + Bash + Git.