Partager du code en ligne est plutôt facile ces temps-ci.
Par contre garder synchronisés tous ses dépôts entre différents services, c'est une autre histoire. Alors oui, vous trouverez des commandes et scripts assez facilement pour importer/exporter vos dépôts. Idem pour mettre en place des miroirs en lecture seule. Mais avoir un système transparent pour être à même de pousser son code sur différentes plateformes, c'est un peu moins facile. Mais bon c'est pas difficile pour autant.
Souvent on utilise GitHub, qui est la solution la plus répandue à ce jour, mais en cas de grosse coupure (coucou les DDoS) ou juste car vous n'avez pas envie d'être trop lié à GitHub (le rachat de GitHub par Microsoft vous rappelle le syndrome Skype ?) vous aimeriez bien avoir des miroirs accessibles en écriture.
Voici donc une petite astuce pour garder vos dépôts synchro entre plusieurs plateformes comme GitLab et Bitbucket, où vous pourrez pousser et récupérer du code sans effort particulier, après un petit coup d'init. Donc pas de miroir en lecture seule hein. De vrais dépôts. Et ça juste en utilisant les fonctionnalités de git (push et pull).
Rappel : pour rester sécurisé, mettez en place SSH et l'authentification à deux facteurs (2FA) sur les plateformes que vous utilisez (sauf Bitbucket, car ça ne marche pas avec leur outil CLI).
Pour rendre le tout facile, on va s'installer quelques outils vite fait.
On va utiliser hub.
Pour macOS
brew install hub
Voir les instructions d'installation hub pour les autres OS.
Il vous faudra un token GitHub.
Mettez-le dans votre dossier home (~) dans un fichier .github_token
, et
chargez-le dans votre .bash/zshrc
comme ça :
if [[ -f $HOME/.github_token ]]
then
export GITHUB_TOKEN=$(cat $HOME/.github_token)
fi
GitLab CLI est disponible en rubygem :
gem install gitlab
(Vous aurez peut-être besoin de sudo gem install
si vous utilisez la version
macOS de ruby.)
Please set an endpoint to API
GitLab nécessite un token ainsi qu'un endpoint (car GitLab peut être déployé n'importe où).
Pour le token, récupérez le votre et
faites comme pour GitHub. Voici un example avec l'instance GitLab.com que vous
pouvez placer dans votre .bash/zshrc
:
if [[ -f $HOME/.gitlab_token ]]
then
export GITLAB_API_PRIVATE_TOKEN=$(cat $HOME/.gitlab_token)
fi
export GITLAB_API_ENDPOINT="https://gitlab.com/api/v3"
Le CLI Bitbucket est disponible via pip :
pip install bitbucket-cli
(Vous aurez peut-être besoin de sudo pip install
si vous utilisez la version
macOS de Python.)
BitBucket ne fonctionne pas bien avec un token et la 2FA n'est pas pratique (et accessoirement est impossible à utiliser en ssh). Il faudra faire avec login/mot de passe à chaque fois, à moins que vous mettiez en clair votre mot de passe dans un fichier.
Maintenant qu'on a les outils, on va créér des dépôts sur chaque plateforme.
Les commandes ci-dessous assument que votre nom d'utilisateur est le même sur chaque service. Si ce n'est pas le cas, pensez à ajuster les commandes.
Nous allons créer/réutiliser un dossier, initialiser un dépôt si ce n'est pas le cas, et le mettre en ligne sur chaque service.
On va partir du principe que le nom du dossier est le nom du projet.
Ouvrez un terminal et faites :
export GIT_USER_NAME=$USER
export GIT_REPO_NAME=$(basename $(pwd))
Ajustez les variables si cela ne correspond pas à ce que nous assumons ici.
export GIT_USER_NAME=$USER
export GIT_REPO_NAME="your-repo"
mkdir $GIT_REPO_NAME && cd $GIT_REPO_NAME
git init
hub create
Cette commande va créer le dépôt et initialiser les remotes.
gitlab create_project $GIT_REPO_NAME "{visibility_level: 20}"
(Visibilité publique). Source
Nous ajouterons la remote plus tard, cela fait partie de l'astuce. ;)
bb create --protocol=ssh --scm=git --public $GIT_REPO_NAME
En fonction de ce que vous voulez, vous pouvez configurer votre dépôt de plusieurs manières.
Pour un dépôt principal et des miroirs, vous pouvez commencer par
git remote set-url origin --add https://gitlab.com/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote set-url origin --add https://bitbucket.org/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
Vérifiez que les commandes sont bonnes en faisant :
git remote -v
Ça devrait vous donner un truc du genre :
origin https://github.com/YOU/YOUR-REPO.git (fetch)
origin https://github.com/YOU/YOUR-REPO.git (push)
origin https://gitlab.com/YOU/YOUR-REPO.git (push)
origin https://bitbucket.org/YOU/YOUR-REPO.git (push)
Et maintenant vous pouvez faire git push
et ça poussera sur tous les dépôts
🙂.
⚠️ Note : pour forcer SSH à la place de HTTPS, petite astuce :
git config --global url.ssh://git@github.com/.insteadOf https://github.com/
git config --global url.ssh://git@gitlab.com/.insteadOf https://gitlab.com/
git config --global url.ssh://git@bitbucket.org/.insteadOf https://bitbucket.org/
git pull
ne va prendre que les commits sur la first remote.Il y a même une incohérence entre git push --all
(pousser toutes les branches
sur toutes les remotes) et git pull --all
(récupérer toutes les branches
depuis la première remote).
en gros : on va ajouter d'autres remotes pour pouvoir pull facilement.
git remote add origin-gitlab https://gitlab.com/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote add origin-bitbucket https://bitbucket.org/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
Vérifiez que les commandes sont bonnes en faisant :
git remote -v
Cela devrait vous donner un truc du genre :
origin ssh://git@github.com/YOU/YOUR-REPO.git (fetch)
origin ssh://git@github.com/YOU/YOUR-REPO.git (push)
origin ssh://git@gitlab.com/YOU/YOUR-REPO.git (push)
origin ssh://git@bitbucket.org/YOU/YOUR-REPO.git (push)
origin-gitlab ssh://git@gitlab.com/YOU/YOUR-REPO.git (fetch)
origin-gitlab ssh://git@gitlab.com/YOU/YOUR-REPO.git (push)
origin-bitbucket ssh://git@bitbucket.org/YOU/YOUR-REPO.git (fetch)
origin-bitbucket ssh://git@bitbucket.org/YOU/YOUR-REPO.git (push)
Maintenant vous pourrez git push
pour pousser sur toutes les remotes, puis
faire git pull --all
pour récupérer de toutes les remotes.
L'astuce à 2 centimes : faites un alias pour pull --all
.
Si vous n'avez qu'une remote sur un projet, ça ne changera rien, mais ça fonctionnera si vous en avez plus d'une.
Dans votre .gitconfig
:
g = pull --all
p = push
Et maintenant vous pouvez utiliser git g
pour pull et git p
pour push.
Un petit edge case peut se révéler problématique : une PR mergée sur GitHub et une
sur GitLab, à peu près en même temps. Vous allez pouvoir récupérer tout ça
facilement (pour peu que vous utilisiez
pull --rebase
par défaut)
mais quand vous allez vouloir pousser, sans force push, ça va avoir du mal.
C'est le seul petit cas problématique. Si vous faites attention quand vous acceptez des PR/MR, vous ne devriez pas le rencontrer souvent.
Si vous rencontrez ce cas et que vous voulez force push pour arranger le tout, faites attention que votre branche (coucou master) ne soit pas protégée durant cette manipulation.
https://github.com/${GIT_USER_NAME}/${GIT_REPO_NAME}/settings/branches
https://gitlab.com/${GIT_USER_NAME}/${GIT_REPO_NAME}/protected_branches
GitLab protège la branche master par défaut. Donc si vous ne changez rien, vous ne pourrez pas force push.
Souvent quand je commence un projet j'ai tendance à faire un petit force push sur le premier commit, le temps de faire passer la CI par exemple. Ne me jugez pas. Vous voilà prévenus.
Je n'ai pas trouvé de moyen automatisé d'appliquer cette technique pour tous mes dêpots d'un coup. Du coup je fais ça petit à petit quand je bosse sur un projet qui n'est pas encore "redondé". J'utilise cette article en guise de mémo.
Vous pourrez éventuellement être intéressés par ces posts
Je n'ai pas de silver-bullet pour ça. Pour l'instant j'utilise un dépôt, souvent GitHub en principal, et les autres ne sont que des copies sans issues… Mais bon, en cas de licorne rose (GitHub down), j'ai l'air moins con ! C'est toute l'idée de cette approche, même si elle est perfectible : ne pas être bloqué par un service.
Pas un soucis, faut juste y penser. Et la prochaine fois que vous avez votre CLI en main, pull + push et tout sera en ordre.
La première fois installez quelques dépendances :
brew install hub
gem install gitlab
pip install bitbucket-cli
Note : soyez sûrs d'avoir les bons tokens en tant que variable d'environnement ; voir au début de ce post pour les détails.
(Pensez aussi à configurer un alias git pour pull --all
si vous voulez pull
toutes les remotes par défaut.)
export GIT_USER_NAME=$USER
export GIT_REPO_NAME=your-repo
mkdir $GIT_REPO_NAME && cd $GIT_REPO_NAME
git init
hub create
export GIT_REPO_NAME=$(basename $(pwd))
gitlab create_project $GIT_REPO_NAME "{visibility_level: 20}"
bb create --protocol=ssh --scm=git --public $GIT_REPO_NAME
Ensuite, on ajoute les remotes
git remote set-url origin --add https://gitlab.com/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote set-url origin --add https://bitbucket.org/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote add origin-gitlab https://gitlab.com/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote add origin-bitbucket https://bitbucket.org/${GIT_USER_NAME}/${GIT_REPO_NAME}.git
git remote -v
Vous devriez avoir un truc du genre
origin ssh://git@github.com/YOU/YOUR-REPO.git (fetch)
origin ssh://git@github.com/YOU/YOUR-REPO.git (push)
origin ssh://git@gitlab.com/YOU/YOUR-REPO.git (push)
origin ssh://git@bitbucket.org/YOU/YOUR-REPO.git (push)
origin-bitbucket ssh://git@bitbucket.org/YOU/YOUR-REPO.git (push)
origin-bitbucket ssh://git@bitbucket.org/YOU/YOUR-REPO.git (fetch)
origin-gitlab ssh://git@gitlab.com/YOU/YOUR-REPO.git (fetch)
origin-gitlab ssh://git@gitlab.com/YOU/YOUR-REPO.git (push)
😇 Maintenant vous n'avez plus qu'à git push
et git pull --all
!
Vous pouvez ajouter des petits badges pour exposer la redondance sur la documentation de votre projet.
[![Repo on GitHub](https://img.shields.io/badge/repo-GitHub-3D76C2.svg)](https://github.com/YOU/YOUR-REPO)
[![Repo on GitLab](https://img.shields.io/badge/repo-GitLab-6C488A.svg)](https://gitlab.com/YOU/YOUR-REPO)
[![Repo on Bitbucket](https://img.shields.io/badge/repo-BitBucket-1F5081.svg)](https://bitbucket.org/YOU/YOUR-REPO)
Ajustez YOU/YOUR-REPO
à votre besoin.
Ça ressemblera à ça
J'ai mis en ligne ces instructions résumées sur un dépôt, peut-être en ferais-je un script, qui sait… 😄. Enfin trois dépôts !