Git – Memo configuration

Tutoriels divers sur Git

Installation et configuration de Git

Installation de Git

# apt-get install git

 

Arborescence initiale des fichiers

# tree .git
.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

9 directories, 14 files

Dans .git/objects, on trouve un dossier par commit.
Ci-dessus, le dossier est vide (hors info et pack), mais dès le premier commit un dossier est créé avec les 2 premières lettres de l’empreinte SHA-1 de chaque commit. Chacun de ces dossiers contient autant de fichier que ceux présents lors du commit, à la différence qu’ils sont ici renommés en 38 caractères hexadécimaux et que leur contenu est encodé et compressé.

ex :

.git/objects/
├── 07
│   └── ca8c24674a0784463493d436c335d509dcd98d
├── 78
│   ├── 27ca1f48feee8bd725d4fce6c185bd816337ed
│   └── 9fb6f9d3a104feb32fcac22354c4d0e8a182c1
├── 99
│   ├── 7b63544e2ee1d1ca2de8f92c193cb39141ec25
│   ├── 6f374f5b36c6f02fb3e9e922b79044f754d795
│   └── 2e818fd4624de9ace3fc6cec510f1cce0b1ddd
├── info
└── pack

Dans le dossier .git/refs/tags/, on trouve un fichier par tag créé avec la commande git tag et contenant l’empreinte SHA-1 du commit vers lequel il pointe.

Dans le dossier .git/refs/heads/, on trouve un fichier par branche créée avec la commande git branch et contenant l’empreinte SHA-1 du commit vers lequel elle pointe.

Le fichier .git/HEAD contient une référence vers la branche actuellement active (ou le commit en mode détaché).
ex :

$ cat .git/HEAD
ref: refs/heads/master
$ git checkout testing
$ cat .git/HEAD
ref: refs/heads/testing
$ git checkout ec2e818
$ cat .git/HEAD
ec2e818fd4624de9ace3fc6cec510f1cce0b1ddd

 

Configuration de Git

Modification du prompt système pour afficher la branche active :

$ nano ~/.bashrc
parse_git_branch() {
     git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u@\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ "
$ source ~/.bashrc
~/git-workspace/repotest (master) $

Définir l’utilisateur et les fins de lignes (CRLF) :

$ git config --global user.name "John Doe"
$ git config --global user.email "john.doe@example.com"
$ git config --global core.autocrlf input
$ git config --global core.safecrlf true

Définir la gestion des couleurs par l’interpréteur :

$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto

Définir l’outil de gestion des différentiels (ici meld) :

$ git config --global diff.tool meld
$ git config --global difftool.meld.path "/usr/bin/meld"
$ git config --global difftool.prompt false

Définir l’outil de gestion des fusions (ici meld) :

$ git config --global merge.tool meld
$ git config --global mergetool.meld.path "/usr/bin/meld"
$ git config --global mergetool.keepbackup false

Définir l’éditeur de texte par défaut :
Ci-dessous : nano

$ git config --global core.editor /bin/nano
$ git config --global core.editor nano

Ci-dessous : vim

$ git config --global core.editor /usr/bin/vim.tiny
$ git config --global core.editor vim.tiny

Définir éventuellement des alias de commandes :

$ git config --global alias.ciam "commit -am \"Update local repository\""
$ git config --global alias.log1 "log --oneline"
$ git config --global alias.hist "log --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %ad | %s%d [%C(bold blue)%an%Creset]' --graph --date=short"

Connaitre la valeur d’un alias précédemment défini :

$ git config --global --get alias.ciam

Supprimer un alias précédemment défini :

$ git config --global --unset alias.ciam

Garder une connexion active vers les dépôts remote durant 15 min (valeur par défaut) :
(Mise en cache des credentials)

$ git config --global credential.helper cache

Garder une connexion active vers les dépôts remote durant une durée spécifiée :
(Mise en cache des credentials , ci-dessous pendant 1h)

$ git config --global credential.helper 'cache --timeout=3600'

Afficher tous les fichiers non suivis :

$ git config --global status.showUntrackedFiles all

 

Consulter et éditer la configuration

Configurations system, global et local

$ git config --list

Uniquement la configuration system: fichier /etc/gitconfig

$ git config --list --system
$ git config --edit --system

Uniquement la configuration global : fichier ~/.gitconfig

$ git config --list --global
$ git config --edit --global

Uniquement la configuration local : fichier .git/config

$ git config --list --local
$ git config --edit --local

 

Installation de ungit

(sources : GitHub – Installation de Node.js sur Debian et Grafikart – Ungit)

# curl -sL https://deb.nodesource.com/setup_10.x | bash -
# apt-get install -y nodejs
# npm install -g ungit
# exit
$ cd repotest
$ ungit

La page suivante s’ouvre alors (en fonction du chemin absolu du repository) dans le navigateur par défaut :

http://localhost:8448/#/repository?path=/home/adminsys/git-workspace/repotest


Correction d’un bug lié à la langue :

$ nano ~/.bashrc
alias ungit='LANG=en_US.UTF-8 ungit'

Relancer le terminal.
 

Installation de gitk

Gitk est un explorateur de commits, un peu comme un journal d’évènements permettant de parcourir les logs de manière assistée.

# apt-get install gitk

Pour afficher les logs de la branche active :

$ gitk

Pour afficher les logs de toutes les branches :

$ gitk --all


Ce qui équivaut, de manière plus graphique, à l’affichage des logs avec l’option --graph :
 

 

Serveur git SSH : connexion par clef publique et utilisateur local lambda

Ici, le client (gerard) se connecte via SSH au serveur, avec un identifiant local du serveur (adminsys), la connexion pouvant être automatisée par l’import de la clef publique du client (gerard) sur le serveur. Sans import de la clef publique, le mot de passe de l’utilisateur local (adminsys) utilisé pour la connexion est demandé chaque fois. La connexion se fait avec le chemin complet du dépôt sur le serveur.
 
Installation de git et openssh-server sur le serveur cental :

# apt-get install git openssh-server

Installation de git et openssh-client sur le client :

# apt-get install git openssh-client

Générer un couple clefs privée (/home/gerard/.ssh/id_rsa) / publique (/home/gerard/.ssh/id_rsa.pub) RSA de 4096 bits sur le client :

$ ssh-keygen -t rsa -b 4096 -C "gerard.bouchard@example.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/gerard/.ssh/id_rsa): 
Created directory '/home/gerard/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/gerard/.ssh/id_rsa.
Your public key has been saved in /home/gerard/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:A1DBFQCUq7XD3dtLNlEHR+UlR6D150APT0CA/tPoOd4 gerard.bouchard@example.com
The key's randomart image is:
+---[RSA 4096]----+
|   .+=++o. .o+@=*|
|    ...   .  * X.|
|     ..  .  o o *|
|    o  .  .. . o.|
|   + o .S .. o  .|
|  . + . .. .+ .  |
|     .   o+. o   |
|        .o..+.   |
|          .o..E  |
+----[SHA256]-----+

Une passphrase est demandée lors de la génération des clefs (mais elle est optionnelle).
Copie de la clef publique de gerard (source : /home/gerard/.ssh/id_rsa.pub) depuis le client vers le serveur (destination : /home/adminsys/.ssh/authorized_keys) :

$ ssh-copy-id adminsys@gitserver.opensharing.priv
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/gerard/.ssh/id_rsa.pub"
The authenticity of host 'gitserver.opensharing.priv (192.168.1.100)' can't be established.
ECDSA key fingerprint is SHA256:ZHhz/BVn0ZkDLyhFKkaazwmYyo8DDJjy+Exd3nHC/jE.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
adminsys@gitserver.opensharing.priv's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'adminsys@gitserver.opensharing.priv'"
and check to make sure that only the key(s) you wanted were added.

Initialisation de la connexion :

$ ssh adminsys@gitserver.opensharing.priv
Linux gitserver 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Jun 28 14:03:23 2018 from 192.168.1.36
adminsys@gitserver ~ $ exit
déconnexion
Connection to gitserver.opensharing.priv closed.

Création d’un utilisateur et d’un groupe git auquel sera affecté l’utilisateur admnisys utilisé pour la connexion SSH :

# useradd --system --create-home --home-dir /opt/git/ --shell /usr/bin/git-shell git
# usermod adminsys -aG git
# sudo -u git mkdir /opt/git/repositories
# chmod 2775 /opt/git/repositories/

Ci-dessus, l’utilisateur git n’est pas utilisé, seul son groupe l’est. Les dépôts seront créés dans /opt/git/repositories/
Rmq : Pour retirer l’utilisateur adminsys du groupe git :
# deluser adminsys git
Ajout de git-shell (utilisé par l’utilisateur git) parmi les shells autorisés :

# nano /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/git-shell

Option 1 : Création du dépôt distant depuis le client via SSH :

$ ssh adminsys@gitserver.opensharing.priv git init --bare --share /opt/git/repositories/repotest.git
adminsys@gitserver.opensharing.priv's password: 
Dépôt Git vide partagé initialisé dans /opt/git/repositories/repotest.git/

Option 2 : Création du dépôt distant depuis le serveur :

$ sudo -u git git init --bare --share /opt/git/repositories/repotest.git
Dépôt Git vide partagé initialisé dans /opt/git/repositories/repotest.git/

Arborescence du dépôt distant :

$ tree /opt/git/repositories/repotest.git
/opt/git/repositories/repotest.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

9 directories, 14 files

Clonage du dépôt distant nouvellement créé en local sur le client :

$ git clone ssh://adminsys@gitserver.opensharing.priv:/opt/git/repositories/repotest.git
Clonage dans 'repotest'...
warning: Vous semblez avoir cloné un dépôt vide.
$ git remote -v
origin	ssh://adminsys@gitserver.opensharing.priv:/opt/git/repositories/repotest.git (fetch)
origin	ssh://adminsys@gitserver.opensharing.priv:/opt/git/repositories/repotest.git (push)

ou
git clone ssh://adminsys@gitserver.opensharing.priv/home/adminsys/gitrepos/repotest.git
ou
$ git clone adminsys@gitserver.opensharing.priv:/home/adminsys/gitrepos/repotest.git
 
Les écritures distantes sur le serveur se feront avec l’utilisateur (adminsys:git) et les droits (d:775 | f:444)
 
Arborescence du dépôt cloné local :

$ tree repotest/.git/
repotest/.git/
├── branches
├── config
├── description
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

9 directories, 14 files

 

Serveur git SSH : connexion par clef publique et utilisateur local git

(Procédure complémentaire à la précédente, ci-dessus)
Ici, le client (gerard) se connecte via SSH au serveur, avec un identifiant local du serveur nommé git, la connexion étant automatisée par l’import de la clef publique du client (gerard) sur le serveur. Sans import de la clef publique, le mot de passe de l’utilisateur local git est demandé chaque fois, mais n’est généralement pas connu du client.
La connexion se fait avec le chemin complet du dépôt sur le serveur.
 
Enregistrer la clef publique de gerard (client) parmi les clefs autorisées de l’utilisateur git (serveur) utilisé pour la connexion SSH :

# mkdir /opt/git/.ssh/
# chmod 700 /opt/git/.ssh/
# nano /opt/git/.ssh/authorized_keys

Copier la clef publique de gerard située dans le fichier /home/gerard/.ssh/id_rsa.pub du client parmi les clefs autorisées.

# chmod 600 /opt/git/.ssh/authorized_keys
# chown -R git:git /opt/git/

Attention, le dépôt à partager devra appartenir à l’utilisateur git :
# chown -R git:git /opt/git/repositories/repotest.git
# chmod 2775 /opt/git/repositories/repotest.git


Empêcher la connexion SSH en tant que git et limiter les commandes à des commandes git. Pour cela, identifier le chemin vers git-shell avec la commande which sur le serveur. Enregistrer ce shell comme valide et l’attribuer à l’utilisateur git, toujours sur le serveur. Ce shell a déjà été affecté à l’utilisateur git lors de sa création, mais il est toujours bon de comprendre l’intérêt de la procédure ou comment modifier ce shell.

# which git-shell
/usr/bin/git-shell
# nano /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/git-shell
# chsh git
Changing the login shell for git
Enter the new value, or press ENTER for the default
	Login Shell []: /usr/bin/git-shell

La connexion du client vers le serveur se fait maintenant sous la forme suivante :

$ git clone ssh://git@gitserver.opensharing.priv:/opt/git/repositories/repotest.git

ou
$ git clone ssh://git@gitserver.opensharing.priv/opt/git/repositories/repotest.git
ou
$ git clone git@gitserver.opensharing.priv:/opt/git/repositories/repotest.git
 
Les écritures distantes sur le serveur se feront avec l’utilisateur (git:git) et les droits (d:775 | f:444)
 

Serveur git public avec protocole git

Ici, le client (quel qu’il soit) se connecte via le protocole git, sans authentification, dans le cadre d’un serveur public non restreint. Ceci n’est évidemment pas conseillé car absolument pas sécurisé. Privilégier une connexion SSH.
 

# useradd --system --create-home --home-dir /opt/git/ --shell /usr/bin/git-shell git
# sudo -u git mkdir /opt/git/repositories
# chmod 2775 /opt/git/repositories/

 
Créer un fichier git-daemon-export-ok dans chaque dépôt du serveur que l’on souhaite utiliser avec le protocole git :

# touch /opt/git/repositories/git-daemon-export-ok

Puis démarrer le démon git :

# git daemon --reuseaddr --enable=receive-pack --user=git --group=git --base-path=/opt/git/repositories/ /opt/git/repositories/ &

Converse :
killall git daemon
Avec :

    --reuseaddr : permet au serveur de redémarrer sans attendre le timeout des anciennes connexions
    --base-path : permet de définir la racine des dépôts afin de ne pas avoir à préciser le chemin complet lors du clonage
    --enable=receive-pack : permet de pusher, sans quoi le dépôt est en read-only

Le client peut maintenant cloner le dépôt via le protocole git :

$ git clone git://gitserver.opensharing.priv/repotest.git

 
Les écritures distantes sur le serveur se feront avec l’utilisateur (git:git) et les droits (d:775 | f:444)
 
Le démon peut automatiquement être démarré avec le serveur avec un script de démarrage du type (en créant au préalable un utilisateur git) :

# nano /etc/systemd/system/git-daemon.service
[Unit]
Description=Start Git Daemon

[Service]
ExecStart=/usr/bin/git daemon --reuseaddr --enable=receive-pack --base-path=/opt/git/repositories/ /opt/git/repositories/
ExecStop=/bin/systemctl stop git-daemon

Restart=always
RestartSec=500ms

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=git-daemon

User=git
Group=git

[Install]
WantedBy=multi-user.target
# systemctl enable git-daemon
Created symlink /etc/systemd/system/multi-user.target.wants/git-daemon.service → /etc/systemd/system/git-daemon.service.
# systemctl start git-daemon

Attention, le dépôt à partager devra appartenir à l’utilisateur git : # chown -R git:git repotest.git
 
Les écritures distantes sur le serveur se feront avec l’utilisateur (git:git) et les droits (d:775 | f:444)
 

Serveur git privé avec protocole HTTP et authentification

# apt-get install apache2 apache2-utils
# a2enmod cgi alias env
# useradd --system --create-home --home-dir /opt/git/ --shell /usr/bin/git-shell git
# usermod www-data -aG git
# chown -R git:git /opt/git/repositories/
# chmod 2775 /opt/git/repositories/
# nano /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        SetEnv GIT_PROJECT_ROOT /opt/git/repositories/
#        SetEnv GIT_HTTP_EXPORT_ALL
#        ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
        ScriptAlias / /usr/lib/git-core/git-http-backend/

        <Files "git-http-backend">
                AuthType Basic
                AuthName "Git Access"
                AuthUserFile /opt/git/repositories/.htpasswd
                Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
                Require valid-user
        </Files>

</VirtualHost>
# htpasswd -c /opt/git/repositories/.htpasswd gituser
New password: 
Re-type new password: 
Adding password for user gituser
# htpasswd /opt/git/repositories/.htpasswd gituser2
New password: 
Re-type new password: 
Adding password for user gituser2
# cat /opt/git/repositories/.htpasswd
gituser:$apr1$qIBHz2Cq$0tchR.mqzrxhBSixrhpmW/
gituser2:$apr1$bReS7mQ/$ghNBXTiQ2b9vMNnMJuSZI1

Sur le serveur, créer un fichier git-daemon-export-ok dans chaque dépôt que l’on souhaite utiliser avec le protocole http :

# touch /opt/git/repositories/git-daemon-export-ok

Alternativement on peut décommenter l’instruction SetEnv GIT_HTTP_EXPORT_ALL de la configuration Apache et ne pas créer de fichier git-daemon-export-ok afin de rendre accessibles tous les dépôts du répertoire racine.

$ systemctl restart apache2

Le client peut maintenant cloner le dépôt via le protocole http :

$ git clone http://gitserver.opensharing.priv/repotest.git

Les écritures distantes sur le serveur se feront avec l’utilisateur (www-data:git) et les droits (d:775 | f:444)
 

Serveur git web de visualisation avec gitweb

Pour avoir un aperçu, lancer un serveur web léger, normalement déjà installé par défaut, depuis l’un des projets git :

# git instaweb --httpd=webrick

L’interface web se lance alors :

Pour l’arrêter :

# git instaweb --httpd=webrick --stop

 
Mise en place d’un serveur web permanent et plus complet avec Apache. Tout d’abord l’installation :

# apt-get install apache2 apache2-utils
# git clone git://git.kernel.org/pub/scm/git/git.git
Clonage dans 'git'...
remote: Counting objects: 249116, done.
remote: Compressing objects: 100% (60266/60266), done.
remote: Total 249116 (delta 186904), reused 248803 (delta 186661)
Réception d'objets: 100% (249116/249116), 59.12 MiB | 2.41 MiB/s, fait.
Résolution des deltas: 100% (186904/186904), fait.
# cd git/
# make GITWEB_PROJECTROOT="/opt/git/repositories/" prefix=/usr gitweb
GIT_VERSION = 2.18.0.96.ged843436d
    SUBDIR gitweb
    SUBDIR ../
make[2]: « GIT-VERSION-FILE » est à jour.
    GEN gitweb.cgi
    GEN static/gitweb.js
# cp -Rf gitweb /var/www/
# chown -R www-data:www-data /var/www/gitweb/
# nano /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:8080>

    ServerName gitserver.opensharing.priv
    DocumentRoot /var/www/gitweb
    <Directory /var/www/gitweb>
        Options +ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch
        AllowOverride All
        order allow,deny
        Allow from all
        AddHandler cgi-script cgi
        DirectoryIndex gitweb.cgi
    </Directory>

</VirtualHost>
# nano /etc/apache2/ports.conf
Listen 80
Listen 8080
# systemctl restart apache2

 

Afficher les pages de manuels en HTML sur le navigateur par défaut

 
Installer le paquet git-doc :

# apt-get install git-doc

Consulter les pages de manuels :

$ git help -w reset
$ git help -w commit
$ git help -w cherry-pick

 

Définir un prompt personnalisé avancé

$ nano ~/.bashrc
export PROMPT_COMMAND='__git_ps1 "\u@\h:\w" " \\\$ "'
export GIT_PS1_SHOWDIRTYSTATE=1 GIT_PS1_SHOWSTASHSTATE=1 GIT_PS1_SHOWUNTRACKEDFILES=1 GIT_PS1_SHOWUPSTREAM=verbose GIT_PS1_DESCRIBE_STYLE=branch GIT_PS1_SHOWCOLORHINTS=1
$ source ~/.bashrc

Ceci crée un prompt en couleur affichant synthétiquement l’état de la copie de travail :

(master u=) $
(master *+$% u+1-3) $
    master : la branche courante
    * : des fichiers ont été modifiés dans la copie de travail
    + : des fichiers ont été ajoutés à l’index (staging area)
    $ : il existe au minimum un stash en attente
    % : la copie de travail contient des fichiers non suivis
    u+1-3 : la branche locale possède 1 commit d’avance sur la branche distante mais aussi 3 commits de retard sur elle

 

Fermer le menu
%d blogueurs aiment cette page :