Cette bibliothèque permet d'utiliser Amazon S3 comme serveur distant git et LFS.
Il fournit une implémentation d'un assistant distant Git pour utiliser S3 comme serveur Git sans serveur.
Il fournit également une implémentation du transfert personnalisé git-lfs pour permettre de transférer les fichiers gérés LFS vers le même compartiment S3 utilisé comme distant.
git-remote-s3
est un script Python et fonctionne avec n'importe quelle version de Python >= 3.9.
Courir:
pip install git-remote-s3
Avant de pouvoir utiliser git-remote-s3
, vous devez :
Configuration initiale complète :
Créez un compartiment AWS S3 (ou possédez-en déjà un) dans votre compte AWS.
Attachez une stratégie minimale à cet utilisateur/rôle qui autorise l'accès au compartiment S3 :
{
"Sid" : " S3Access " ,
"Effect" : " Allow " ,
"Action" : [ " s3:PutObject " , " s3:GetObject " , " s3:ListBucket " ],
"Resource" : [ " arn:aws:s3:::<BUCKET> " , " arn:aws:s3:::*/* " ]
}
Facultatif (mais recommandé) : utilisez les clés de compartiment SSE-KMS pour chiffrer le contenu du compartiment, assurez-vous que l'utilisateur/le rôle créé au préalable a l'autorisation d'accéder et d'utiliser la clé.
{
"Sid" : " KMSAccess " ,
"Effect" : " Allow " ,
"Action" : [ " kms:Decrypt " , " kms:GenerateDataKey " ],
"Resource" : [ " arn:aws:kms:<REGION>:<ACCOUNT>:key/<KEY_ID> " ]
}
Toutes les données sont chiffrées au repos et en transit par défaut. Pour ajouter une couche de sécurité supplémentaire, vous pouvez utiliser des clés KMS gérées par le client pour chiffrer les données au repos sur le compartiment S3. Nous vous recommandons d'utiliser des clés de compartiment pour minimiser les coûts KMS.
Le contrôle d'accès à la télécommande est assuré via les autorisations IAM et peut être contrôlé depuis :
Les télécommandes S3 sont identifiées par le préfixe s3://
et spécifient au strict minimum le nom du compartiment. Vous pouvez également fournir un préfixe de clé comme dans s3://my-git-bucket/my-repo
et un profil s3://my-profile@my-git-bucket/myrepo
.
mkdir my-repo
cd my-repo
git init
git remote add origin s3://my-git-bucket/my-repo
Vous pouvez ensuite ajouter un fichier, valider et transmettre les modifications à la télécommande :
echo " Hello " > hello.txt
git add -A
git commit -a -m " hello "
git push --set-upstream origin main
Le HEAD distant est configuré pour suivre la branche qui a été poussée en premier vers le dépôt distant. Pour modifier la branche HEAD distante, supprimez l'objet HEAD s3://<bucket>/<prefix>/HEAD
, puis exécutez git-remote-s3 doctor s3://<bucket>/<prefix>
.
Pour cloner le dépôt dans un autre dossier, utilisez simplement la syntaxe git normale en utilisant l'URI s3 comme distant :
git clone s3://my-git-bucket/my-repo my-repo-clone
Créer des branches et les pousser fonctionne normalement :
cd my-repo
git checkout -b new_branch
touch new_file.txt
git add -A
git commit -a -m " new file "
git push origin new_branch
Toutes les opérations git qui ne dépendent pas de la communication avec le serveur devraient fonctionner comme d'habitude (par exemple git merge
)
Pour utiliser LFS, vous devez d'abord installer git-lfs. Vous pouvez vous référer à la documentation officielle pour savoir comment procéder sur votre système.
Ensuite, vous devez activer l'intégration S3 en exécutant la commande suivante dans le dossier repo :
lfs-s3-py install
qui est un raccourci pour :
git config --add lfs.customtransfer.lfs-s3-py.path lfs-s3-py
git config --add lfs.standalonetransferagent lfs-s3-py
Supposons que nous souhaitions stocker le fichier TIFF dans LFS.
mkdir lfs-repo
cd lfs-repo
git init
git lfs install
lfs-s3-py install
git lfs track " *.tiff "
git add .gitattributes
< put file.tiff in the repo >
git add file.tiff
git commit -a -m " my first tiff file "
git remote add origin s3://my-git-bucket/lfs-repo
git push --set-upstream origin main
Un URI Amazon S3 pour un compartiment valide et un préfixe arbitraire qui ne contient pas la bonne structure en dessous sont considérés comme valides.
git ls-remote
renvoie une liste vide et git clone
clone un référentiel vide pour lequel l'URI S3 est défini comme origine distante.
% git clone s3://my-git-bucket/this-is-a-new-repo
Cloning into 'this-is-a-new-repo'...
warning: You appear to have cloned an empty repository.
% cd this-is-a-new-repo
% git remote -v
origin s3://my-git-bucket/this-is-a-new-repo (fetch)
origin s3://my-git-bucket/this-is-a-new-repo (push)
Astuce : Ce comportement peut être utilisé pour créer rapidement un nouveau dépôt git.
En raison de la nature distribuée de git
, il peut y avoir des cas (bien que rares) où 2 git push
ou plus sont exécutés en même temps par différents utilisateurs avec leur propre modification de la même branche.
La commande git exécute le push en 2 étapes :
git-remote-s3
qui écrit le bundle dans le compartiment S3 au chemin refs/heads/<branch>
Dans le cas où deux (ou plus) commandes git push
sont exécutées en même temps à partir de différents clients, à l'étape 1, la même référence valide est récupérée, donc les deux clients passent à l'étape 2, ce qui entraîne le stockage de plusieurs bundles dans S3.
La branche a maintenant plusieurs références head, et tout git push
ultérieur échoue avec l'erreur :
error: dst refspec refs/heads/<branch>> matches more than one
error: failed to push some refs to 's3://<bucket>/<prefix>'
Pour résoudre ce problème, exécutez la commande git-remote-s3 doctor <s3-uri>
. Par défaut, il créera une nouvelle branche pour chaque bundle qui ne doit pas être conservé. L'utilisateur peut ensuite extraire la branche localement et la fusionner avec la branche d'origine. Si vous souhaitez plutôt supprimer le bundle, spécifiez --delete-bundle
.
Lors du clonage d'un dépôt à l'aide de la télécommande S3 pour LFS, git-lfs
ne peut pas savoir comment récupérer les fichiers car nous n'avons pas encore ajouté la configuration.
Cela implique 2 étapes supplémentaires.
% git clone s3://my-git-bucket/lfs-repo lfs-repo-clone
Error downloading object: file.tiff (54238cf): Smudge error: Error downloading file.tiff (54238cfaaaa42dda05da0e12bf8ee3156763fa35296085ccdef63b13a87837c5): batch request: ssh: Could not resolve hostname s3: Name or service not known: exit status 255
...
Pour réparer :
cd lfs-repo-clone
lfs-s3-py install
git reset --hard main
Pour supprimer les branches distantes qui ne sont plus utilisées, vous pouvez utiliser la commande git-s3 delete-branch <s3uri> -b <branch_name>
. Cette commande supprime le ou les objets bundle d'Amazon S3 sous le chemin de branche.
Pour protéger/déprotéger une branche, exécutez git s3 protect <remote> <branch-name>
respectivement git s3 unprotect <remote> <branch-name>
.
Les bundles sont stockés dans le compartiment S3 sous le nom <prefix>/<ref>/<sha>.bundle
.
Lors de la liste des références distantes (par exemple explicitement via git ls-remote
), nous listons toutes les clés présentes sous le fichier .
Lorsque nous poussons une nouvelle référence (par exemple un commit), nous obtenons le sha de la référence, nous regroupons la référence via git bundle create <sha>.bundle <ref>
et la stockons dans S3 selon le schéma ci-dessus.
Si le push réussit, le code supprime le bundle précédent associé à la réf.
Si deux utilisateurs envoient simultanément une validation basée sur la même tête de branche actuelle vers la télécommande, les deux bundles seront écrits dans le référentiel et le bundle actuel sera supprimé. Aucune donnée n'est perdue, mais aucune autre poussée ne sera possible tant que tous les bundles sauf un n'auront pas été supprimés. Pour cela, vous pouvez utiliser la commande git s3 doctor <remote>
.
L'intégration LFS stocke le fichier dans le bucket défini par l'URI distant, sous une clé <prefix>/lfs/<oid>
, où oid est l'identifiant unique attribué par git-lfs au fichier.
Si un objet avec la même clé existe déjà, git-lfs-s3 ne le télécharge pas à nouveau.
Utilisez l'indicateur --verbose
pour imprimer des informations de débogage lors de l'exécution d'opérations git. Les journaux seront placés dans stderr.
Pour les opérations LFS, vous pouvez activer et désactiver la journalisation du débogage via git-lfs-s3 enable-debug
et git-lfs-s3 disable-debug
respectivement. Les journaux sont placés dans .git/lfs/tmp/git-lfs-s3.log
dans le dépôt.
L'intégration de git S3 a été inspirée par le travail de Bryan Gahagan sur git-remote-s3.
L'implémentation LFS a bénéficié de lfs-s3 de @nicolas-graves. Si vous n'avez pas besoin d'utiliser le transport git-remote-s3, vous devez utiliser ce projet.