GitLab → GitHub Contributions Sync
janvier 2026 → janvier 2026
Quand on travaille sur un GitLab d'entreprise, le graphe de contributions GitHub reste vide. Des mois de travail invisibles sur le profil que les gens regardent. Cet outil récupère l'activité de commits depuis GitLab et la reporte sur un dépôt GitHub dédié.
La contrainte qui définit le projet
Rien de l'entreprise ne doit sortir. C'est une ligne rouge, pas une préférence. Un outil qui clonerait les dépôts pour rejouer les commits ferait sortir du code appartenant à l'employeur, ce qui est exclu quelle que soit la commodité.
Le programme ne clone donc rien. Il interroge l'API GitLab avec un jeton en lecture seule (portée read_api) et ne récupère que des métadonnées de commits. À partir de là, il crée sur le dépôt GitHub des commits vides qui ne portent qu'une date : pas de code, pas de message d'origine, pas d'empreinte, pas de nom de projet. Chaque commit affiche le même message générique.
C'est le point sur lequel j'ai le plus insisté après coup. Une première version reprenait le titre du commit d'origine et le nom du projet interne dans le message. Techniquement ce ne sont pas des lignes de code, mais un dépôt GitHub public qui afficherait [acme/facturation] correction du calcul de TVA laisse quand même fuiter des noms de projets et des intentions. La version actuelle ne reproduit que la date. Le graphe se remplit, et un observateur ne peut rien en déduire.
Comment l'activité est reconstituée
Découverte automatique des projets accessibles avec le jeton : l'outil parcourt l'API page par page, sans liste à maintenir à la main. Un nouveau dépôt apparaît de lui-même à la synchronisation suivante.
Filtrage par adresse de l'auteur, pour ne reporter que ses propres commits et pas ceux des collègues sur les mêmes dépôts. Toutes les branches sont parcourues, pas seulement la principale.
Récupération en parallèle : les commits de tous les projets sont interrogés en même temps, avec une limite de cinq requêtes simultanées pour ne pas saturer l'API. Sur une organisation qui compte des dizaines de dépôts, la différence est nette.
Préservation des dates d'origine, sans quoi tout apparaîtrait au jour de la synchronisation et le graphe ne voudrait rien dire. La date de l'auteur du commit GitLab devient celle du commit GitHub.
Reprise après interruption
Synchroniser des centaines de commits prend du temps, et un script long finit toujours par être coupé au mauvais moment. L'outil tient un registre des commits déjà traités, identifiés par leur empreinte, et il le sauvegarde toutes les cinquante opérations. Une exécution interrompue reprend là où elle s'était arrêtée, sans recréer de doublon.
Ce registre reste sur ma machine, il n'est pas poussé sur GitHub : les empreintes des commits d'entreprise ne sortent pas non plus. C'est aussi ce qui rend l'outil rejouable à volonté : on peut le relancer autant de fois qu'on veut, il ne traite que ce qui est nouveau.
Pensé pour les GitLab d'entreprise
Les instances d'entreprise sont rarement sur gitlab.com. L'URL de l'instance est donc configurable, et une option permet d'accepter un certificat interne quand le GitLab est derrière une autorité de certification maison. Sans ça, l'outil serait inutilisable là où il sert justement, en entreprise.
Fait pour tourner tout seul
Un outil de ce genre n'a d'intérêt que si on l'oublie : il doit se lancer seul, régulièrement. Comme il est rejouable sans risque de doublon, on le branche sur une tâche planifiée et on n'y pense plus.
C'est exactement ce que je fais avec CronLab, mon propre planificateur de tâches pour Windows, qui exécute la synchronisation chaque jour et me notifie en cas d'échec. Les deux projets se complètent : l'un produit une commande à lancer régulièrement, l'autre la lance.
Ce que j'en retire
Un outil conçu pour être relancé sans conséquence est bien plus agréable à utiliser qu'un script qu'on n'ose exécuter qu'une fois. La reprise après interruption et l'absence de doublon sont ce qui permet de le brancher sur un planning et de l'oublier.
L'autre point est une question de mesure. La mécanique côté GitHub s'appuie sur simple-git : créer le dépôt local, poser les commits aux bonnes dates, pousser. Ce que je me suis interdit, c'est de cloner les dépôts GitLab, et j'ai réduit au strict minimum ce qui atterrit sur GitHub. Il aurait été plus simple de tout recopier ; s'en tenir à une date par commit a demandé un peu plus de réflexion, et c'est ce qui rend l'outil défendable vis-à-vis de l'employeur.