From 3f45af4f2902de5f826f92c8abaa81b9d2db95b0 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Sat, 17 Dec 2016 21:06:03 +0100 Subject: [PATCH] Add HowtoGit --- HowtoGit.md | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 HowtoGit.md diff --git a/HowtoGit.md b/HowtoGit.md new file mode 100644 index 00000000..5668b0d5 --- /dev/null +++ b/HowtoGit.md @@ -0,0 +1,394 @@ +--- +categories: git +title: Howto Git +... + +* Documentation: +* À lire : +* À voir : + +Git est un logiciel de gestion de code source, créé en 2005 par Linux Torvalds. + +## Installation + +~~~ +# apt install git +~~~ + +Configuration minimum via `~/.gitconfig` : + +~~~ +[user] + name = Prenom Nom + email = jdoe+git@example.com +[pull] + rebase = true +[push] + default = simple +~~~ + +## Commandes de base + +### Créer un dépôt + +~~~{.bash} +$ mkdir foo +$ cd foo +$ git init +~~~ + +### Cloner un dépôt + +Plusieurs méthodes d'accès pour récupérer un dépôt : HTTP(S), Git, file. + +~~~{.bash} +$ git clone https://git.example.com/path/projet +$ git clone git://git.example.com/path/projet.git +$ git clone file:///path/projet +~~~ + +### Travailler sur un dépôt local + +Ajouter un nouveau fichier : + +~~~{.bash} +$ touch main.c +$ git add main.c +$ git commit -v +~~~ + +Modification d'un fichier existant : + +~~~{.bash} +$ vi main.c +$ git add main.c +$ git commit -v +~~~ + +*Note* : on peut éviter de faire `git add` et faire uniquement `git commit -a` si l'on est sûr qu'aucun autre fichier n'a été modifié (mais c'est une mauvaise habitude que l'on déconseille). + +Voir l'état du dépôt local (fichiers non commités, etc.) : + +~~~{.bash} +$ git status +~~~ + +Voir les derniers commits du dépôt local : + +~~~{.bash} +$ git log +~~~ + +### pull/pusher avec un dépôt distant + +Si l'on a cloné un dépôt existant, un lien est automatiquement créé entre le dépôt local créé et le dépôt distant (référencé comme *origin*). + +Pour récupérer en local les derniers changements du dépôt distant : + +~~~{.bash} +$ git pull --rebase origin +~~~ + +*Note* : l'option `--rebase` est désormais le défaut mais par pédagogie on conseille de la mettre explicitement. + +Pour envoyer ses modifications locales vers le dépôt référencé comme distant : + +~~~{.bash} +$ git push origin +~~~ + +### Gestion des branches + +Par défaut, certains outils utilisent une branche nommée *master*. +Cette branche existe donc souvent au sein d'un dépôt, mais il faut +garder en tête que c'est une convention, rien n'oblige en avoir une. + +Lister les branches existantes et connaître sa branche courante : + +~~~{.bash} +$ git branch -a +~~~ + +Créer une branche *myfeature* à partir de la branche *master* : + +~~~{.bash} +$ git checkout -b myfeature master +~~~ + +Pour passer d'une branche à une autre dans son dépôt local : + +~~~{.bash} +$ git checkout myfeature +$ git checkout master +~~~ + +Travailler sur la branche *myfeature* puis merger son travail dans *master* : + +~~~{.bash} +$ git checkout master +$ git merge --no-ff myfeature +~~~ + +Pousser une branche locale vers le dépôt référencé comme distant : + +~~~{.bash} +$ git push origin myfeature +~~~ + +Supprimer une branche locale et distante : + +~~~{.bash} +$ git branch -d myfeature +$ git push origin :myfeature +~~~ + + +## Commandes avancées + +### Modifier l'historique + +/!\\ Les modifications de l'historique ne doivent avoir lieu que si il n'a pas déjà été pushé vers un dépôt partagé ! + +Modifier son dernier message de commit : + +~~~{.bash} +$ git commit --amend +~~~ + +Modifier son dernier commit : + +~~~{.bash} +$ vi main.c +$ git add main.c +$ git commit --amend +~~~ + +Modifier son avant-dernier commit : + +~~~{.bash} +$ git rebase -i HEAD^^ +… remplacer "pick" par "edit" pour le commit à modifier +$ vi main.c +$ git add main.c +$ git commit --amend +$ git rebase --continue +~~~ + +*Note* : On peut remonter au Nième commit en utilisant *HEAD~N* + +### Piquer un commit dans une autre branche + +~~~{.bash} +$ git cherry-pick +~~~ + +### gitignore + +Créer un fichier `.gitignore` à la racine pour ignorer certains fichiers/chemins : + +~~~ +$ cat .gitignore + +test.php +htdocs/foo/bar +toto/titi* +~~~ + +*Note* : le fichier .gitignore se commit dans le dépôt + +### Ranger temporairement son travail (git stash) + +Cela permet d'avoir un buffer pour mettre "en pause" des modifications non commitées : + +~~~{.bash} +…hack…hack… +$ git stash save +~~~ + +On peut lister ce buffer : + +~~~{.bash} +$ git stash list +stash@{0}: WIP on dev: fb1fa70… m +stash@{1}: WIP on dev: fb1fa70… m +~~~ + +Et ré-appliquer les modifications stockées : + +~~~{.bash} +$ git stash apply stash@{0} +~~~ + +Pour purger le buffer sans l'appliquer : + +~~~{.bash} +$ git stash clear +~~~ + +### Echanger des commits sous forme de patchs Git + +Pour transmettre ses 3 derniers commits, on peut générer 3 patches qui contiendront les diffs ainsi que les messages de commit : + +~~~{.bash} +$ git format-patch -3 +~~~ + +Si l'on a ces 3 patches, on peut les appliquer sur son dépôt local ainsi : + +~~~{.bash} +$ git am 000*.patch +~~~ + +## Workflow de travail + +Il existe plusieurs workflows possibles en travaillant avec Git. + +### Le modèle Git branching + +Voir + +L'idée est de ne jamais toucher à *master*, sauf hotfixes. +Pour le reste on le fait dans *dev*. +Et pour les grosses features on le fait dans une branche, nommée avec le nom de la feature. + +## Astuces diverses + +### Partager un dépôt avec plusieurs utilisateurs + +Avec un dépôt *foo* existant, on autorisera les utilisateurs que si ils appartiennent au groupe *git* : + +~~~ +# cd foo +# git config core.sharedRepository group +# addgroup git +# chgrp -R git . +# chmod g=rwXs,o= -R . +# chmod g=rwX -R . # astuce pour garder le +s sur les répertoires +~~~ + +### Importer un dépôt SVN dans GIT + +Ce script permet de récupérer la liste des auteurs SVN, modifiez la comme voulu. + +~~~{.bash} +#!/usr/bin/env bash +authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq) +for author in ${authors}; do +echo "${author} = Prenom Nom "; +done +~~~ + +On lance ensuite la commande suivante : + +~~~{.bash} +$ git svn --authors-file=path/to/authors_file clone svn+ssh://svn.example.com/path/to/repo +~~~ + +### Importer un dépôt CVS dans GIT + +Lancer la commande suivante : + +~~~{.bash} +$ git cvsimport -C repo_git -r cvs -k -vA path/to/authors_file -d user@hostname:/path/to/cvsroot repo +~~~ + +### Convertir un dépôt en utf8 + +Créer un fichier exécutable dans `/tmp/recode-all-files` : + +~~~{.bash} +#!/bin/sh +find . -type f -print | while read f; do + mv -i "$f" "$f.recode.$$" + iconv -f iso-8859-1 -t utf-8 < "$f.recode.$$" > "$f" + rm -f "$f.recode.$$" +done +~~~ + +Puis exécuter la commande suivante dans votre dépôt : + +~~~{.bash} +$ git filter-branch --tree-filter /tmp/recode-all-files HEAD +~~~ + +Exécuter ensuite la commande suivante pour convertir les messages de commit : + +~~~{.bash} +$ git filter-branch --msg-filter 'iconv -f iso-8859-1 -t utf-8' -- --all +~~~ + +### Push vers un non-bare repository + +Ceci est évidemment déconseillé, car cela mettra aussi à jour les fichiers, ce qui nécessite +de faire un `git reset --hard`. Mais si l'on veut tout de même le forcer : + +~~~ +$ git push +Counting objects: 7, done. +Delta compression using up to 4 threads. +Compressing objects: 100% (4/4), done. +Writing objects: 100% (4/4), 618 bytes, done. +Total 4 (delta 3), reused 0 (delta 0) +Unpacking objects: 100% (4/4), done. +remote: error: refusing to update checked out branch: refs/heads/master +remote: error: By default, updating the current branch in a non-bare repository +remote: error: is denied, because it will make the index and work tree inconsistent +remote: error: with what you pushed, and will require 'git reset --hard' to match +remote: error: the work tree to HEAD. +remote: error: +remote: error: You can set 'receive.denyCurrentBranch' configuration variable to +remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into +remote: error: its current branch; however, this is not recommended unless you +remote: error: arranged to update its work tree to match what you pushed in some +remote: error: other way. +remote: error: +remote: error: To squelch this message and still keep the default behaviour, set +remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'. + ! [remote rejected] master -> master (branch is currently checked out) +~~~ + +Il faut ajouter dans la config du repository "distant" : + +~~~ +[receive] + denyCurrentBranch = warn +~~~ + +### Transformer un non-bare repository en bare repository + +Il suffit de supprimer tous les fichiers sauf le .git, par exemple : + +~~~{.bash} +$ rm -rf * +~~~ + +Puis d'indiquer dans la config du repository : + +~~~ +bare = true +~~~ + +### Mettre en place des notifications de push + +Sous Debian, pour envoyer des notifications par email à git@example.com : + +~~~ +# chmod a+x /usr/share/doc/git-core/contrib/hooks/post-receive-email +$ cd /path/path/to/your/repository.git +$ ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive +$ git hooks.mailinglist git@example.com +~~~ + +Pour recevoir les patches : + +~~~{.bash} +$ git config hooks.showrev "git show -C %s; echo +~~~ + +### Ignorer les vérifications SSL + +~~~{.basb} +$ git config --global http.sslverify "false" +~~~ + +