---
# System prepended metadata

title: Git workflow
tags: [ironhack]

---

---
tags: ironhack
---

<style>
img {background-color:transparent!important;}
</style>

Git workflow
===

Voir dans quelle branche on se trouve
---
```shell
$ git branch
  christmas-feature
* master
  easter-egg
```

> :point_right: Nous sommes ici dans la branche `master`, repérée par l'`*`

:::info
:bulb: La branche `master` est la branche par défaut sur tous les repositories
:::


Créer une nouvelle branche `masuperfeature`
---
```shell
$ git checkout -b masuperfeature --track origin/master
```

Une nouvelle branche du nom de `masuperfeature` est créée et nous nous retrouvons maintenant dedans.

Changer de branche
---

Pour aller dans la branche `coolfeature` (déjà créée) :

```shell
$ git checkout coolfeature
```

:::info
:bulb: Dans le prompt de notre terminal, on peut afficher la branche courante dans laquelle on se trouve, comme par ex :

```
(master) $ git checkout coolfeature
(coolfeature) $ 
```
Voir [cet article](https://coderwall.com/p/fasnya/add-git-branch-name-to-bash-prompt).
:::

Faire un commit
---

Pour voir où on en est localement, ie :
 - les fichiers modifiés/supprimés
 - les nouveaux fichiers, dits `untracked`

```shell
$ git status
On branch masuperfeature
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   app.js
	deleted:    old.js

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	README
```

On `add` ensuite tous les fichiers (nouveaux ou modifiés) que l'on veut inclure à notre commit et l'on `rm` tous ceux que l'on veut supprimer du répo :

```shell
$ git add README app.js
$ git rm old.js
```

Un ultime `git status` avant de faire notre commit histoire de s'assurer que tout est bon (en vert), puis:

```shell
$ git commit -m "Ajout de la doc et cleaning"
```

:::info
:bulb: `git status` donne beaucoup d'info y compris certaines commandes comme par ex pour annuler un changement sur un fichier : `git checkout -- <file>`
:::

Pousser une branche
---

Pour envoyer nos commits locaux vers le serveur distant (Github) :

```shell
$ git push origin masuperfeature
```

:::warning
:point_up: On doit *forcément* être dans la branche locale `masuperfeature` pour pousser vers la branche distance `masuperfeature` (**même nom**).
:::

:::success
:bulb: Si la branche distante n'existait pas encore, elle sera créée automatiquement.
:::

:::info
Pousser une branche permet :
- [x] à d'autres devs de récupérer mon travail
- [x] de faire une sauvegarde de son travail ailleurs (si jamais on perdait son laptop dans le métro)
:::

Merger une branche dans une autre
---

Si je veux récupérer le code d'un collègue bossant sur la branche `api`.

Dans ma propre branche :
```shell
$ git pull origin api
```

:::warning
:point_up: AVANT de faire le `pull`, je m'assure par un `git status` de **n'avoir aucune modification en cours**.

Si c'est le cas, je prends le temps de **faire un commit AVANT**.
:::

Resoudre des conflits (méthode de base)
---

### 💥Boom

Lors d'un [merge](#Merger-une-branche-dans-une-autre), si 2 développeurs ont modifié la même ligne de code, git ne saura pas quelle version prendre... Il mettra alors le merge *en pause*, et vous demandera de résoudre les conflits, avant de pouvoir finaliser le merge :

```shell
$ git pull origin api
From https://github.com/abernier/ironme
Auto-merging public/stylesheets/style.scss
CONFLICT (content): Merge conflict in public/stylesheets/style.scss
Automatic merge failed; fix conflicts and then commit the result.
```

:::success
Vous pourrez retrouver la liste des fichiers en conflit par un `git status` :

```shell
$ git status
On branch features/about
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   public/stylesheets/style.scss

no changes added to commit (use "git add" and/or "git commit -a")
```

NB : Notez le `Unmerged paths`

---

<div style="font-size:120%;text-align:center;">
<code>git status</code> est vraiment notre meilleur ami, il nous donne toujours de bons conseils 🧚🏼‍♂️</div>
:::

### 💏Résolution

Si l'on inspecte le fichier en conflit :
![](https://i.imgur.com/9RIV7R1.png)


:::info
:bulb: Le conflit est délimité par des chevrons entre les lignes 4 et 10 :
```
<<<<<<< HEAD
v1
=======
v2
>>>>>>> 6b7380c886e0906f6a5efd2b600be8fcf390fa4d
```
:::

Il nous faut réconcilier `v1` et `v2` ensemble, tout simplement **en éditant le fichier et en enlevant les signes bizarres** :
![](https://i.imgur.com/7tUCMl2.png)

:::info
🤝Souvent lors de la résolution d'un conflit, on contactera l'auteur avec lequel notre version conflicte pour se mettre d'accord sur la résolution.
:::

### ✅ commit de merge

Une fois le fichier édité et le conflit résolu, il nous faut marquer le fichier comme mergé et faire un commit de merge (sans message) :

```shell
$ git add public/stylesheets/style.scss
```

:::success
Un petit `git status` vous dira maintenant qu'il n'y a plus de conflit :
```shell
$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:
	modified:   public/stylesheets/style.scss
```

NB : Notez le message : `use "git commit" to conclude merge`
:::

La commande `git commit` sans message de commit, ouvre un éditeur de texte `Vim` avec un message de commit pré-rempli :

```shell
$ git commit
```

```
Merge branch 'master' of https://github.com/abernier/ironme into features/about

# Conflicts:
#	public/stylesheets/style.scss
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#	.git/MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch features/about
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#	modified:   public/stylesheets/style.scss
#
```

Pour sauvegarder le message de commit et quitter Vim, nous appuyons sur les touches <kbd>:wq</kbd>

:::info
Si l'on aime pas Vim, on peut aussi définir VScode comme éditeur de texte par défaut :

```shell
$ echo "export EDITOR=\"code -w\"" >>~/.profile
```
:::

**And voilà, le conflit est maintenant résolu 🙌**

On oublie pas de pousser le commit de merge, avec que la résolution du conflit puisse profiter à d'autres (et qu'ils n'aient pas à la refaire eux-même) :

```shell
$ git push origin master
```

Résoudre des conflits (avec `git mergetool`)
---

Le principe reste le même, on des conflits, mais pour la résolution, on va cette fois-ci s'aider d'un outil graphique pour mieux visualiser les 2 versions côte-à-côte...

### Configuration

:::info
Pour les utilisateurs sous Windows et Ubuntu, vous devrez installer le logiciel **[Meld](http://meldmerge.org)** et le **[configurer](https://stackoverflow.com/a/43868889/133327)** sur votre machine.
:::

:::info
Pour les utilisateurs sous mac, je vous recommande d'utiliser plutôt **Filemerge**, dont voici **[les instructions pour le configurer](https://gist.github.com/kylefox/4512777)**.

---

NB: Dans les préférences de Filemerge, cochez l'option `Compress white space`:
![](https://i.imgur.com/CQ2hkeQ.png)

:::

### Utilisation

La commande `git mergetool` va pour chacun des fichiers en conflit, démarrer l'interface graphique (Meld ou Filemerge) :

```shell
$ git mergetool
Merging:
public/stylesheets/style.scss

Normal merge conflict for 'public/stylesheets/style.scss':
  {local}: modified file
  {remote}: modified file
```
qui lancera alors une interface graphique pour résoudre le conflit :
![](https://i.imgur.com/Gd98Sd3.png)
> :broken_heart: A gauche et droite : les 2 versions en conflits.
> :green_heart:En bas : notre version "réconciliée" (et éditable !)

:::warning
☝️Occupez-vous seulement des blocks en rouge ! Les autres ne sont pas en conflit.
:::

Une fois le conflit résolu, ne pas oublier de <kbd>+s</kbd> `sauver` le fichier du milieu avant de <kbd>+q</kbd>`quitter` l'interface.

:::warning
Si plusieurs fichiers en conflit, il vous faudra quitter entre chaque. `git mergetool` relancera l'interface pour chaque fichier en conflit.
:::

---

👉Idem, on oublie pas ensuite de faire le ✅commit de merge !
