Blog

Dupliquer un dépôt git sur github et réécrire l'histoire

Écrit le 06 02 2017 par Kévin MET _

Aujourd’hui on va partir sur un sujet « deux en un », dans un premier temps, on va voir comment dupliquer un dépôt git sur github et dans un deuxième temps, on va voir comment réécrire l’histoire, à savoir comment changer les utilisateurs et les adresses mails des commit.

Dupliquer un dépôt git

Dans le titre et l’introduction je fais référence à github mais cela peut être fait sur n’importe quel autre dépôt git. Maintenant qu’on a fait cette mise au point, je vais vous expliquer précisément ce que j’entends par la duplication d’un dépôt git vers github. En fait, je voulais que mes dépôts git disponible sur mon gitlist le soient également sur github sans que je ne change rien à mes habitudes. C’est à dire que je fais mes commit et mes push comme d’habitude et toutes mes modification sont mirrorées sur github. Je pensais que ça serait compliqué à mettre en place mais en fouillant un peu la doc de git j’ai vu que ce n’était pas si compliqué, il suffit d’ajouter un remote de type mirror dans mon dépôt et d’ajouter un hook post-update qui fait le push sur github.

Mais avant de partir dans les détails techniques on va commencer par le commencement. Déjà il faut un compte github, ça vous l’auriez deviné mais ce n’est pas tout, il faut pouvoir faire des push avec une paire de clé SSH sur ses dépôts github. Pour cela, on commence par générer une paire de clé avec notre utilisateur git sur le serveur qui contient les dépôts :


nierdz@web1:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/nierdz/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/nierdz/.ssh/id_rsa.
Your public key has been saved in /home/nierdz/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:HPf5dVzZkfP5JTsGY5BD0tCSRkOHO5lt1doeQ10il9Y nierdz@web1.mnt-tech.fr
The key's randomart image is:
+---[RSA 2048]----+
|       o*Bo...o=+|
|        =+* .o=+E|
|       ..*.+ = .*|
|       .=oo.=.=o+|
|        So .o+ =*|
|             .=.o|
|             ... |
|                 |
|                 |
+----[SHA256]-----+

On peut ensuite ajouter la clé dans son compte github, c’est dans le menu « Settings » -> « SSH and GPG keys » Ou directement via ce lien

Dans mon cas la clé est associée à l’utilisateur git qui fait les push, en l’occurence nierdz, mais dans le cas ou vous utiliseriez un groupe ou différents utilisateurs sur le même dépôt il faudra faire en sorte qu’ils utilisent chacun une clé différente. Il faudra donc faire plusieurs clés et les ajouter sur github. Il existe une alternative à cela que je n’ai pas essayé mais qui devrait fonctionner. Faire un /etc/ssh/ssh_config qui reprend les infos concernant l’utilisateur qui détient une clé valide sur github. Un exemple :


Host github.com
	HostName github.com
	Port 22
	User git
	IdentityFile /path/to/id_rsa

Après il faut sûrement que les utilisateurs soient dans le même groupe car sinon SSH va faire chier avec les droits sur la clé privée. Je suis même pas sur que ça passe avec un chmod 660 sur id_rsa. Bref, à essayer mais c’est pas gagné et je pense que la gestion avec une clé par utilisateur est plus fine même si un peu plus chiante à gérer car cela fait quand même deux paires de clés par user...

Bon, maintenant qu’on peut push sur github avec notre clé, il suffit d’ajouter un miroir de type push sur notre dépôt. Pour cela, on se connecte avec notre user git sur le serveur qui contient le dépôt et on l’ajoute avec la commande suivante. Exemple avec mon dépôt admintools et user nierdz :


nierdz@web1:~$ cd git/admintools.git/
nierdz@web1:~/git/admintools.git$ git remote add --mirror=push github git@github.com:nierdz/admintools.git

Et voilà, tout simplement ! On peut faire un cat sur le fichier config pour voir que ce que ça a ajouté (la partie [remote "github"] ) :


nierdz@web1:~/git/admintools.git$ cat config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = true
[remote "github"]
	url = git@github.com:nierdz/admintools.git
	mirror = true

On a bien un nouveau remote qui se nomme github qu’on va pouvoir push sur github. On peut faire un premier essai en faisant un push depuis le dépôt git :


nierdz@web1:~/git/admintools.git$ git push github 
The authenticity of host 'github.com (192.30.253.113)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.253.113' (RSA) to the list of known hosts.
Counting objects: 131, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (119/119), done.
Writing objects: 100% (131/131), 91.08 KiB | 0 bytes/s, done.
Total 131 (delta 47), reused 0 (delta 0)
remote: Resolving deltas: 100% (47/47), done.
To git@github.com:nierdz/admintools.git
* [new branch]      master -> master

Et voilà, tout mon historique est sur github mais dans l’état c’est un peu chiant car cela signifie qu’à chaque push on doit se connecter sur le serveur et refaire un push ce qui n’est pas très pratique. Heureusement, il existe les hooks de git et on va utiliser le hook post-update pour déclencher le deuxième push vers github. Les hooks sont situés dans le dossiers hooks de votre dépôt et il faut qu’il soient exécutables par l’user qui push. Voici à quoi ressemble le fichier post-update :


nierdz@web1:~/git/admintools.git$ cat hooks/post-update 
#!/bin/sh

echo "### Push sur Github ###"
git push github

Tout simplement ! Votre dépôt est maintenant synchronisé sur github :)

Si vous avez besoin de synchroniser dans l’autre sens car vous avez merge une PR sur github par exemple, il suffit de faire un fetch :


nierdz@web1:~/git/admintools.git$ git fetch github 
From github.com:nierdz/admintools
 * branch            HEAD       -> FETCH_HEAD

Réécriture de l’histoire

Lorsque j’ai push pour la première fois mon dépôt admintools sur github je me suis rendu compte que j’avais plein de commit avec des mails et des users différents et ça faisait dégueulasse dans la timeline des commits. J’ai donc eu envie de changer ça pour tout remettre sur le même utilisateur et la même adresse email et je suis tombé sur cette article : https://help.github.com/articles/changing-author-info/

En gros, il faut commencer par cloner votre dépôt et rentrer dedans :


git clone nierdz@git.mnt-tech.fr:nierdz/admintools.git
cd admintools

il faut ensuite télécharger le script (attention, il faut ajouter l’option -f si on veut faire plus qu’une seule modification, se référer à la version sur mon github : https://github.com/nierdz/admintools/blob/master/scripts/change_history.sh) et l’ajouter dans votre dépôt en changeant les variables OLD_EMAIL, CORRECT_NAME et CORRECT_EMAIL.

Il ne reste plus qu’à le lancer :


bash change_history.sh

Et enfin on push le merdier sur le dépôt :


git push --force --tags origin 'refs/heads/*'

Elle est pas belle la vie ? :)

♥ Partage sur tes réseaux sociaux ♥
Kévin MET
Kévin MET

Auteur de ce blog et gérant de la société MNT-TECH, je publie sur ce blog lorsque le temps me le permet et lorsqu'un sujet qui me parait intéressant n'a pas encore été abordé en français. Toutes les informations techniques présentes sur cette page peuvent être réutilisées moyennant le fait de citer la source.