Table des matières

Git

La base de la base, en gros et en français ;) ⇒ http://rogerdudler.github.io/git-guide/index.fr.html

Un tuto en français qui va bien ⇒ https://www.miximum.fr/blog/enfin-comprendre-git/

Installation

apt-get install git-core

Interface graphique si besoin

apt-get install gitk

Configuration

Première chose à faire, s’identifier.

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Toute la config global est stocké dans votre répertoire utilisateur dans le fichier .gitconfig

Pour avoir un peu de couleur

git config --global color.ui true

Pour définir un éditeur de texte spécifique

git config --global core.editor vi

Pour avoir un historique plus sympathique, tapez cette ligne pour avoir un aperçu

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

Perso je me suis fait celui la car je fait des commit sur plusieurs lignes et c’est donc plus lisible comme ça

git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d %Cgreen(%ci - %cr) %C(bold blue)<%an>%Creset %n%B%Creset' --all

Sauvegardez cette commande dans un alias

git config --global alias.hist "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d %Cgreen(%ci - %cr) %C(bold blue)<%an>%Creset %n%B%Creset' --all" 

Ainsi vous n’aurez qu’a taper pour avoir tout l’histoire / ou l’historique d’un fichier

git hist
git hist nom_du_fichier

Et pour avoir le détails des modifications / ou des modifications d’un fichier

git hist -p
git hist -p nom_du_fichier

Pour voir les fichiers ajoutés, modifiés, supprimés

git hist --name-status

Pour voir les fichiers avec les + et -

git hist --stat

Plus de personnalisation sur ⇒ http://git-scm.com/book/fr/Personnalisation-de-Git-Configuration-de-Git

et, très important, forcer le rebase lorsque l’on fait un pull pour éviter les merge et avoir un historique propre

git config --global pull.rebase true

Pour avoir un prompt sympa qui affiche votre branche et l’état de votre dépôt.

Interface graphique

gitg ou giggle semble correcte.

Une liste complète

Un outils à installer avec npm, ungit

Le principe git

FIXME

Un modèle de branche pour le dev ⇒ http://nvie.com/posts/a-successful-git-branching-model/

Le même modèle traduit en français ⇒ https://www.occitech.fr/blog/2014/12/un-modele-de-branches-git-efficace/

Quelques commandes utiles

L’essentiel ⇒ http://wiki.spheredev.org/Git_for_the_lazy

Voir ou on en est

git status

Voir les différences entre le dernier commit et les modifications en cours

git diff

Voir les différences entre 2 branches

git diff branch1..branch2

Voir les différences d’un fichier entre 2 branches

git diff branch1..origin/master fichier

Ou si vous êtes sur la branch1 et que vous voulez comparer votre fichier avec le origin/master (le master du dépôt)

git diff ..origin/master fichier

Voir les modifications faites par le dernier commit

git show

ou par un commit spécifique

git show euioeoe

Faire un commit vite fait

git commit -a -m 'vite fait'

Ajouter au commit tous les fichiers modifiés suivi et non suivi ‘untracked’

git add .

Ajouter au commit seulement les fichiers suivi

git add -u

Le git reset

Revenir à l’état d’un commit tout en gardant vos modification local en unstage

git reset <commit>
git reset <commit> --mixed

Revenir à l’état d’un commit tout en gardant vos modification local en stage

git reset <commit> --soft

Revenir à l’état d’un commit en supprimant toutes vos modifications en local !! (pas de retour possible !!!)

git reset <commit> --hard

Enlever un fichier du commit ou plutot, désindexer un fichier

git reset lefichier

équivalent de

git reset --mixed HEAD lefichier

Annuler le dernier commit non encore propagé (n’affecte pas le contenu des fichiers, fait comme si vous n’aviez pas fait git commit)

git reset HEAD^

Annuler votre dernier commit non propagé (supprime vos modifications et le dernier commit).

git reset --hard HEAD^

Le git revert (pas de perte d’historique)

Pour annuler un commit en particulier. Crée un nouveau commit

git revert <commit>

Pour annuler un commit sur un fichier en particulier

git revert <commit> <nom du fichier>

Plus d’info sur git reset ⇒ https://git-scm.com/book/fr/v2/Utilitaires-Git-Reset-d%C3%A9mystifi%C3%A9

Supprimer les modifications faite sur un fichier

git checkout -- nom_du_fichier

Modifier le message du dernier commit

git commit --amend

Si vous avez déjà pushé votre commit sur origin/master

git commit --amend
git push -f

Sauf que maintenant sur la prod vous avez un message du style

$ git status
Sur la branche master
Votre branche et 'origin/master' ont divergé,
et ont 1 et 1 commits différents chacune respectivement.
  (utilisez "git pull" pour fusionner la branche distante dans la vôtre)
rien à valider, la copie de travail est propre

Utilisez alors la commande

git reset --hard origin/master

Les branches

Voir les branches

git branch

Création

Créer une branche

git checkout -b nom_de_la_nouvelle_branche
  ou 
git branch nom_de_la_nouvelle_branche
git checkout nom_de_la_nouvelle_branche

Note : si vous avez des modifications en cours avant de créer une branche, elles seront dispo sur les 2 branches (master et la nouvelle). Commité vos modifs sur la nouvelle branche supprimera vos modifs sur master.

Si vous avez plusieurs branch, vous pouvez spécifier à partir de quelle branche créer la nouvelle branche

git branch nouvelle_branche depuis_cette_branche

Changer de branche

git checkout nom_dune_branche

Renommer une branche

git branch -m ancien_nom nouveau_nom

Pour pousser votre branche sur le dépôt afin qu’elle soit accessible à tout le monde

git branch --set-upstream nom_dune_branche origin/nom_dune_branche

Modification

Pour fusionner votre nouvelle branche sur la branche master, faites vos commit, placez-vous sur la branche master puis fusionner une autre branche sur celle-ci

git commit -a
git checkout master
git merge nom_de_la_branche_a_fusionner_avec_master

Pour garder l’historique de votre branche sans mélanger vos commits avec la branche de destination, spécifiez l’option –no-ff no fast forward

git merge --no-ff branche_a_fusionner

Pour copier un fichier d’une autre branche sur la branche en cours

$ git checkout master
$ git branch
* master
  twitter_integration
$ git checkout twitter_integration fichier1 fichier2

Si vous avez une branche feature et que vous voulez intégrer les derniers commit de master sur cette branche

$ git checkout feature
$ git pull origin master

Suppression de branches

Pour supprimer la branche qui ne sert plus à rien et vérifier qu’elle a été mergé

git branch -d nom_branche_qui_sert_plus

Pour supprimer une branche qui n’a pas été mergé

git branch -D nom_branche_obsolète

Après avoir supprimé votre branch, il est possible qu’en utilisant git checkout + tab vous voyez encore de vieille branch dans l’autocompletion. Utilisez la commande suivante pour purger ces restes

$ git remote prune origin

Pour supprimer la branch sur origin

git push origin --delete nom_branche_qui_sert_plus

tester un merge

git checkout master
git merge --no-commit --no-ff branche_a_merger

Pour voir ce qui a changé

git diff --cached

Pour abandonner le merge

git merge --abort

Pour valider le merge

git commit
Méthode alternative à l'ancienne

Pour tester votre merge, faite un test sur une branche temporaire

git checkout master
git checkout -b temp_merge
git merge feature_branch

Après avoir réglé les conflits ou autre problème, vous pouvez comparer les différences avec le master

git diff master

Quand c’est fait, supprimez votre banche temporaire

git checkout master
git branch -D temp_merge

appliquer un commit d'une autre branche

On est sur notre branche v2

git checkout v2

On veut appliquer notre commit a2a2a2 sur notre branche master

git checkout master
git cherry-pick a2a2a2

Si vous rencontrez des conflits, tout est bien expliqué

$ git cherry-pick 19c0c1d
error: impossible d'appliquer 19c0c1d... commentaire du commit
astuce: après résolution des conflits, marquez les chemins corrigés
astuce: avec 'git add <chemins>' ou 'git rm <chemins>'
astuce: puis validez le résultat avec 'git commit'

$ git status
Sur la branche v2
Vous êtes actuellement en train de picorer le commit 19c0c1d.
  (réglez les conflits puis lancez "git cherry-pick --continue")
  (utilisez "git cherry-pick --abort" pour annuler le picorage)

Modifications qui seront validées :

	modifié :         mon-fichier.php
	modifié :         mon-fichier2.php

Chemins non fusionnés :
  (utilisez "git add <fichier>..." pour marquer comme résolu)

	modifié des deux côtés :  mon-fichier-en-conflit.php

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)

	mon-fichier-non-suivi.php

Gestion de conflit

Si il y a un conflit

CONFLICT (content): Merge conflict in app/controllers/AdminController.php
Automatic merge failed; fix conflicts and then commit the result.

Un git status listera les fichiers en conflit par un both modified

# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#	both modified:      app/controllers/AdminController.php
#

Pour voir le conflit

git diff

Le conflit sera présenté comme ça

++<<<<<<< HEAD
 +              mon code sur le master
++=======
+               mon code sur la branche à merger
++>>>>>>> branche_a_merger

Vous pouvez utiliser un outils graphique tel que vimdiff pour corriger le problème avec la commande

git mergetool

Pour passer d’un conflit à un autre utilisez cette séquence ]c ou [c
Une fois placé sur un conflit, utilisez la commande :diffget LO pour remplacer le conflit par ce qu’il y a dans la fenêtre LOCAL. ( BA pour BASE, RE pour REMOTE)
Sauvegardez et quittez toutes les fenêtres par :xa, votre fichier sera automatiquement ajouté dans votre prochain commit.
Supprimez le copie de sauvegarde laissez par vimdiff

rm fichier_en_conflit.orig

Sinon corrigez à la main le fichier et ajoutez le

git add fichier_en_conflit

Checkout

Liste des fichiers modifiés

git checkout

Permet une interactivité sur la modification d’un fichier

git checkout -p
Discard this hunk from worktree [y,n,q,a,d,/,s,e,?]? ?
y - discard this hunk from worktree
n - do not discard this hunk from worktree
q - quit; do not discard this hunk nor any of the remaining ones
a - discard this hunk and all later hunks in the file
d - do not discard this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
git pull = git fetch + git merge

Supprimer un fichier de l’arborescence et le supprimer de l’index

git rm fichier

Supprimer un fichier uniquement de l’index sans le supprimer physiquement

git rm --cached fichier

Pour supprimer le fichier de tout l’historique

git filter-branch --index-filter 'git rm --cached (file)' HEAD

Supprimer tous les fichiers pourris de iOS (échapper l’astérisk est important sinon le shell l’interprètera et seul les fichiers de 1er niveau seront supprimés)

git rm \*/.DS_Store

Supprimer un dossier

git rm -r dossier

Récupérer un fichier supprimé

git checkout HEAD fichier

Récupérer un fichier d’un ancien commit

git checkout hashDuCommit fichier

Remet dans l’état précédent tous les fichiers

git reset --hard HEAD

Remet dans l’état d’un commit précédent

git reset --hard hashDuCommit

Abandonner le suivi de fichiers pour les fichiers de config par exemple

git update-index --assume-unchanged config.php

Si c’est un répertoire, terminé par un /

git update-index --assume-unchanged app/config/

Pour revenir en arrière

git update-index --no-assume-unchanged config.php

Pour afficher les fichiers qui ont été marqué avec un –assume-unchanged

git ls-files -v | grep -e "^[hsmrck]"

Pour annuler les modifications d’un commit spécifique

git revert b12caf55

Pour annuler les 3 derniers commits

git revert HEAD~3..HEAD�

Tag

Créer un tag léger (pour les versions mineures, git crée un pointeur)

git tag v1.0.1

ou un tag lourd avec un message (pour les releases, git crée un objet avec des metadatas)

git tag -a v1.0 -m 'blabla'

Pousser ses tags sur le remote

git push --tags

Lister les tag

git tag

Supprimer un tag (en local)

git tag -d v1.0

Supprimer un tag en remote après l’avoir supprimé en local

git push origin :refs/tags/v1.0

Switcher sur un tag

git checkout v1.0

Switcher sur un commit (pour par exemple revoir un vieux fichier qu’on aurait supprimé…)

git checkout 2e6bc6f

Revenir sur l’état courant

git checkout master

Stash

Si on a fait une modification qu’on ne veut pas commiter, on peut la mettre de côté, faire par exemple un git pull et réappliquer la modif

git stash

Pour mettre en stash uniquement un fichier

git stash push -- path/to/file.txt

pour voir les modifs en stash

git stash list

Pour voir quelles sont les fichiers modifiés par un stash

git stash show

ou

git stash show stash@{0}

Pour appliquer vos modifs stockées dans le stash et les supprimer du stash

git stash pop

Pour appliquer vos modifs stockées dans le stash et les laisser dans le stash

git stash apply

Le reste dans

git stash help

Faire un dépôt git vite fait

Créer un répertoire qui contiendra votre projet git. Ex: projet.git

cd /var/git/projet.git

Initialisez le dépôt vide

git init --bare --shared

Allez dans votre projet

cd /var/www/projet

Créez votre projet git

git init

Ajoutez les fichier

git add .

Créez votre 1er commit

git commit -m 'Mon 1er commit'

Spécifiez le dépôt à votre projet

git remote add origin /var/git/projet.git

Poussez tout ça en spécifiant origin et la branche master

git push origin master

Spécifié les infos de suivi…

git branch --set-upstream master origin/master

Ce qui devrait vous faire un fichier de config comme suit

[core]
  repositoryformatversion = 0
  filemode = true
  bare = false
  logallrefupdates = true
[remote "origin"]
  url = /var/git/projet.git/
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
  remote = origin
  merge = refs/heads/master

et voila :)

Si vous avez oubliez l’option –shared qui permet de permettre à d’autres utilisateurs system de pouvoir faire des push, ajoutez ceci dans votre fichier de config du dépôt

[core]
  sharedrepository = 1
[receive]
  denyNonFastforwards = true

et tapez ces quelques commandes dans votre dépôt pour les permissions

chgrp -R votreGroupe .
find . -type d | xargs chmod g+ws
find refs -type f | xargs chmod g+w

Explication git add

git add -A is equivalent to git add .; git add -u.

The important point about git add . is that it looks at the working tree and adds all those paths to the staged changes if they are either changed or are new and not ignored, it does not stage any ‘rm’ actions.

git add -u looks at all the already tracked files and stages the changes to those files if they are different or if they have been removed. It does not add any new files, it only stages changes to already tracked files.

git add -A is a handy shortcut for doing both of those.

You can test the differences out with something like this (note that for Git version 2.x your output for git add . git status will be different):

git init
echo Change me > change-me
echo Delete me > delete-me
git add change-me delete-me
git commit -m initial

echo OK >> change-me
rm delete-me
echo Add me > add-me

git status
# Changed but not updated:
#   modified:   change-me
#   deleted:    delete-me
# Untracked files:
#   add-me

git add .
git status

# Changes to be committed:
#   new file:   add-me
#   modified:   change-me
# Changed but not updated:
#   deleted:    delete-me

git reset

git add -u
git status

# Changes to be committed:
#   modified:   change-me
#   deleted:    delete-me
# Untracked files:
#   add-me

git reset

git add -A
git status

# Changes to be committed:
#   new file:   add-me
#   modified:   change-me
#   deleted:    delete-me

Cas simple

Serveur

Créer un répertoire et tapez la commande

git init

Si le répertoire contient déjà tout un projet, ajoutez les fichiers que vous voulez suivre avec la commande

git add .

Vérifiez l’état avec la commande

git status

Faite un commit pour commencer

git commit

A ce moment là, votre éditeur de texte par défaut s’ouvre pour vous demander un commentaire sur ce commit. Ce commentaire est obligatoire, sinon l’action ne continuera pas.

Client

Récupérez le projet du serveur avec la commande

git clone ssh://user@serveur/var/www/monProjet

ou en notation scp

git clone user@serveur:/var/www/monProjet

Si vous voulez mettre votre projet sur le serveur, assurez-vous de créer un git vide sur le serveur, faite un clone, ajoutez tous vos fichiers, faite un git add. puis un commit.

Cas de dev web

Environnement de dev : placez vous dans votre répertoire de dev /home/toto/dev et taper la commande

[local]$ cd /home/toto/dev
[local:/home/toto/dev]$ git init

Si vous voulez suivre tous vos fichiers dans git tapez

[local:/home/toto/dev]$ git add . 

Sinon spécifiez le fichier à suivre

[local:/home/toto/dev]$ git add test.php

Faites votre 1er commit

[local:/home/toto/dev]$ git commit -m "1er commit"

Place au serveur distant de prod et test

Créer un dépot pour gérer tout ça

[serveur.com]$ mkdir /var/www/hub.git
[serveur.com]$ cd /var/www/hub.git
[serveur.com:/var/www/hub.git]$ git init --bare

Sur la machine de dev

[local:/home/toto/dev]$ git remote add origin ssh://root@serveurProd/var/www/hub.git

Synchroniser la branche master sur votre serveur git origin

[local:/home/toto/dev]$ git push origin master

Vérifier sur le serveur de prod

[serveur.com:/var/www/hub.git]$ git log

Créer sur le serveur de prod un répertoire prod et test

[serveur.com:/var/www/hub.git]$ git clone hub.git prod
[serveur.com:/var/www/hub.git]$ git clone hub.git test
[serveur.com:/var/www/hub.git]$ cd hub.git/hook
[serveur.com:/var/www/hub.git/hook]$ vi post-update
#!/bin/bash
 
echo "***** Mise en production *****"
cd /var/www/prod
unset GIT_DIR
git pull origin master
 
echo "***** Mise en test *****"
cd /var/www/test
unset GIT_DIR
git pull origin dev

Rendre exécutable

[serveur.com:/var/www/hub.git/hook]$ chmod +x post-update

De retour sur la machine de dev, nous allons créer une branche de dev pour différencier la prod de test

[local:/home/toto/dev]$ git branch dev

Pour vérifier sur quelle branche nous nous trouvons

[local:/home/toto/dev]$ git branch
dev
* master

Nous sommes sur la branche master, pour se mettre sur la branche dev

[local:/home/toto/dev]$ git checkout dev

On vérifie

[local:/home/toto/dev]$ git branch
* dev
master

On définie les fichiers à suivre dans cette branche dev

[local:/home/toto/dev]$ git add .

Et on commit

[local:/home/toto/dev]$ git commit -m "1er commit de la branche dev"

La 1ère fois, spécifier la nouvelle branche dev dans la commande push pour la créer sur le serveur git

[local:/home/toto/dev]$ git push origin dev

Fusionner votre branche de dev sur le master.
Mettez vous sur la branche master

[local:/home/toto/dev]$ git checkout master

Fusionner la branche dev avec la branche en cours (master)

[local:/home/toto/dev]$ git merge dev

Faites un push pour mettre à jour le serveur git

[local:/home/toto/dev]$ git push origin

Pour ignorer la mise à jour de certains répertoire, utiliser un fichier .gitignore et placer les dossiers à ignorer

[local:/home/toto/dev]$ vi .gitignore
/repertoire/a/eviter

D’autre exemple de .gitignore

# un commentaire, cette ligne est ignorée
# pas de fichier .a
*.a
# mais suivre lib.a malgré la règle précédente
!lib.a
# ignorer les fichier finissant par ~
*.~
# ignorer les fichier finissant par .a et .o
*.[ao]
# ignorer uniquement le fichier TODO à la racine du projet
/TODO
# ignorer tous les fichiers dans le répertoire build
build/
# ignorer doc/notes.txt, mais pas doc/server/arch.txt
doc/*.txt
# ignorer tous les fichiers .txt sous le répertoire doc/
doc/**/*.txt

Bon dev :)

Pour éviter de taper origin à chaque pull ou push, éditer votre fichier .git/config sur votre machine de dev et adaptez en conséquence
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
        url = user@serveur.com:/var/www/projet.git/
[branch "master"]
        remote = origin
        merge = refs/heads/master

— source : http://www.siteduzero.com/informatique/tutoriels/gerez-vos-codes-source-avec-git/travailler-avec-des-branches

— Doc complète : http://git-scm.com/book/fr/D%C3%A9marrage-rapide

— Doc vidéo sur le cas de dev web : http://www.grafikart.fr/blog/deployer-site-git

— Une autre petite doc : http://www.miximum.fr/tutos/1546-enfin-comprendre-git

http://doc.ubuntu-fr.org/git

— Doc en anglais http://gitimmersion.com

Le cas des fichiers de config

On va supposer un projet web avec plein de fichiers de config dans /app/config/

Créer un fichier .gitignore avec comme contenu

/app/config/

Ce qui aura pour effet d’ignorer le répertoire de config lors d’un push ou d’un pull.

Pushez ce .gitignore sur votre dépôt ou votre git source.

Faite un clone de votre projet

git clone projet.git projet_dev

Spécifiez que vous ne voulez pas indexer les changements de notre dossier de config

git update-index --assume-unchanged app/config/*.*

Modifiez vos fichiers de config, puis vérifions ce qu’il se passe.

# git status
# On branch master
nothing to commit (working directory clean)

Maintenant supposons qu’un utilisateur ait modifié les fichiers de config de base et les aient pushé sur le dépôt..
Dans ce cas la, lorsque vous allez faire un pull, vous pouvez être confronté à divers messages d’erreurs…

git pull
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 4), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From edmc73.com:/var/www/dev/dashboard
   0060f1f..e1f3b16  master     -> origin/master
Updating 0060f1f..e1f3b16
error: Your local changes to 'app/config/app.php' would be overwritten by merge.  Aborting.
Please, commit your changes or stash them before you can merge.
git status
# On branch master
# Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
#
nothing to commit (working directory clean)

Et la, c’est la panique complète !!!

SOLUTION : changer la reférence HEAD à la main…

Récupérer le hash du dernier commit

git log --all -n5 --pretty=format:'%H - %d'
e1f3b16a476415ff1be102beec8643f208996d7b -  (origin/master)
0060f1fbc299e8c6c9bcd123a490edc9446dce44 -  (HEAD, master)
f8136204dd67a8a8336da3fb83ce2cf2b91343dc - 
07cac380a96eba82e1c69f96a616d86b9b545f03 - 
92586834ee358c57ceb01d11875efe672c043c14 - 

On voit ici que dans notre git local, notre HEAD est à la 2eme place alors que celui du dépôt distant est sur la 1ère.

Vous pouvez consulter le contenu du commit avec la commande

git cat-file -p e1f3b16a476415ff1be102beec8643f208996d7b

Si on vérifie le contenu du fichier .git/refs/heads/master on retrouve bien notre hash précédent en 2ème position

cat .git/refs/heads/master 
0060f1fbc299e8c6c9bcd123a490edc9446dce44

Editez le fichier .git/refs/heads/master et placer le 1er hash

echo e1f3b16a476415ff1be102beec8643f208996d7b > .git/refs/heads/master

Notre fichier de config ressort maintenant comme étant modifié

git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   app/config/app.php
#

Désindexer le fichier avec la commande proposé par git

git reset HEAD app/config/app.php
Unstaged changes after reset:
M	app/config/app.php

git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   app/config/app.php
#
no changes added to commit (use "git add" and/or "git commit -a")

Ignorer le changement

git update-index --assume-unchanged app/config/app.php

git status
# On branch master
nothing to commit (working directory clean)

Résultat

git pull 
Already up-to-date.

Configurer Apache

Pour interdire l’accès aux fichiers git depuis le web, ajouter ce bout de code dans votre config apache

<Files ~ "^\.git">
    Order allow,deny
    Deny from all
    Satisfy all
</Files>

Profitez-en pour limiter l’accès à votre fichier README.md

<Files "readme.md">
    Order Deny,Allow
    Deny from all
</Files>

Faire le ménage dans son historique

La docs officiel

Un super article sur git rebase, git reflog

Virer la branch temporaire (supprime le cache du remote et donc vire le pointeur du remote origin dans l’historique des commits)

git update-ref -d refs/original/refs/heads/master

En voir plus dans les logs comme l’autheur et le commiteur

git log --format=fuller

Voir toutes les actions faites dans le moindre détail

git reflog

Modifier l’autheur et le commiteur de tous les commits

git filter-branch --commit-filter \
'if [ "$GIT_AUTHOR_NAME" = "OldAuthor Name" ]; then \
export GIT_AUTHOR_NAME="Author Name";\
export GIT_AUTHOR_EMAIL=authorEmail@example.com;\
export GIT_COMMITTER_NAME="Commmiter Name";\
export GIT_COMMITTER_EMAIL=commiterEmail@example.com;\
fi;\
git commit-tree "$@"'

Reprendre tout depuis le début

git rebase --root -i

Cette commande permet de partir du 1er commit ( –root ) et de tomber sur un mode interactif ( -i ) permettant de bouger, supprimer re éditer des commits

Cette manip peut être long si le début est chaotique avec des branches de merge qui trainent à droite à gauche, dans ce cas, git vous dira de vérifier et valider les commits. Voici quelques commande à faire

git status
git add .
git rebase --continue

Si vous êtes perdu

git rebase --abort

Maintenant, quand on regarde un peu l’historique, on peut voir que toutes les dates de commit on changé, ce qui peut être embêtant. Heureusement, la date de l’autheur est toujours intact, on va donc pouvoir tout mettre à jour avec la commande suivante

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'

Maintenant que notre historique est bon, on va se créer un dépot tout propre et faire encore un peu de ménage sur notre espace de travail.
Supprimer le dépot

git remote remove origin

Supprimer le cache du remote

git update-ref -d refs/original/refs/heads/master

Vider tous les reflog qui ne servent à rien

git reflog expire --expire=now --all
git gc --agressive --prune=now

Pour le grand nettoyage ⇒ http://blog.ostermiller.org/git-remove-from-history

Maintenant, soit on recrée un dépot tout neuf et on push dedans, soit on force

git push --force --all

Rebrancher un depot git sur un dossier de travail sans git

Par exemple, nous avons un dépôt git sur http://git/projet

Notre répertoire de travail ( ~/projet ) contient le même contenu avec des modifications, mais aucune information de git (pas de dossier .git)

Nous voulons connecté ce répertoire de travail avec le dépôt git afin de pouvoir commité nos modifications.

ATTENTION: à faire uniquement si votre répertoire de travail est plus à jour que le dépôt git, sinon vous écraserez les modifs du dépôt git.

$ cd ~/projet
$ git init
Dépôt Git vide initialisé dans ~/projet
 
$ git remote add origin http://git/projet
$ git fetch
remote: Décompte des objets: 33, fait.
remote: Compression des objets: 100% (31/31), fait.
remote: Total 33 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (33/33), done.
Depuis http://git/projet
 * [nouvelle branche] master     -> origin/master
 
# dans mon cas, seul le fichier README.md a été modifié par rapport au dépôt git
$ git reset origin/master
Modifications non indexées après reset :
M	README.md
 
# ajoutez vos fichiers ou commitez vos modifs de fichiers déjà suivi
$ git commit -a
 
$ git push -u origin/master
Counting objects: 5, done.
Writing objects: 100% (3/3), 255 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://git/projet
   217fd11..78c825e  master -> master
La branche master est paramétrée pour suivre la branche distante master depuis origin.

Monter son serveur git

Monter son github perso avec gogs

Features

Alternatives

Installation

On peut installer gogs soit à partir :

J’ai testé via les binaires et ça marche très bien, il faut juste penser à créer un utilisateur git qui servira à stocker les dépôts et les clés ssh pour faire le lien avec les utilisateurs

Sur un serveur de prod je préfère que tout soit intégré comme le reste, je vais donc faire l’installation sur une debian 8 via le paquet deb proposé.

Les commandes sont expliquées sur cette page https://packager.io/gh/pkgr/gogs/install?bid=535#debian-8-gogs

wget -qO - https://deb.packager.io/key | sudo apt-key add -
echo "deb https://deb.packager.io/gh/pkgr/gogs jessie pkgr" | sudo tee /etc/apt/sources.list.d/gogs.list
sudo apt-get update
sudo apt-get install gogs

gogs tourne en local sur le port 3000, nous allons utiliser le module proxy d’apache pour y accéder sur le port HTTP classique

# a2enmod proxy
# a2enmod proxy_http
# service apache2 restart

Ensuite nous allons créer une config apache

<VirtualHost *:80>
  Define HOSTNAME git.edmc73.com
 
  <IfModule mpm_itk_module>
    AssignUserId gogs gogs
  </IfModule>
 
  ServerName ${HOSTNAME}
 
  <Proxy *>
    Order allow,deny
    Allow from all
  </Proxy>
 
  ProxyPass / http://127.0.0.1:3000/
  ProxyPassReverse / http://127.0.0.1:3000/
 
  ErrorLog /var/log/apache2/${HOSTNAME}_error.log
 
  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel warn
 
  CustomLog /var/log/apache2/${HOSTNAME}_access.log combined
 
</VirtualHost>
a2ensite git.edmc73.com.conf
service apache2 reload

et maintenant via votre navigateur vous allez tomber sur la page d’installation de gogs.

Créer au préalable une base de données gogs avec comme interclassement utf8_general_ci

Spécifiez le domaine et le root_url, au pire vous pourrez modifier le fichier /etc/gogs/conf/app.ini

Profitez-en pour changer le HTTP_ADDR pour que gogs ne soit accessible que en local par apache.

[server]
PROTOCOL               = http
DOMAIN                 = git.edmc73.com
ROOT_URL               = https://git.edmc73.com/
HTTP_ADDR              = 127.0.0.1
HTTP_PORT              = 3000

Validez et voila ;)

Maintenant on peut créer un certificat via let’s encrypt

debian:~/letsencrypt# ./certbot-auto certonly --webroot -w /opt/gogs/public/ -d git.edmc73.com

Créer la config apache qui va bien et forcer la redirection vers https

Redirect permanent / https://git.edmc73.com/

Pour la configuration des mails, si vous avez un postfix en smtp en local sans certificat valide, modifier la config en ajoutant true pour SKIP_VERIFY et le HOST = 127.0.0.1:25

[mailer]
ENABLED                 = true
; Buffer length of channel, keep it as it is if you don't know what it is.
SEND_BUFFER_LEN         = 100
; Name displayed in mail title
SUBJECT                 = %(APP_NAME)s
; Mail server
; Gmail: smtp.gmail.com:587
; QQ: smtp.qq.com:465
; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
HOST                    = 127.0.0.1:25
; Disable HELO operation when hostname are different.
DISABLE_HELO            =
; Custom hostname for HELO operation, default is from system.
HELO_HOSTNAME           =
; Do not verify the certificate of the server. Only use this for self-signed certificates
SKIP_VERIFY             = true

N’oubliez pas de redémarrer gogs après des modifs dans le fichier de config

service gogs restart