Esta biblioteca permite utilizar Amazon S3 como servidor git remoto y LFS.
Proporciona una implementación de un asistente remoto de git para usar S3 como un servidor Git sin servidor.
También proporciona una implementación de la transferencia personalizada git-lfs para permitir enviar archivos administrados por LFS al mismo depósito S3 utilizado como remoto.
git-remote-s3
es un script de Python y funciona con cualquier versión de Python >= 3.9.
Correr:
pip install git-remote-s3
Antes de poder usar git-remote-s3
, debes:
Configuración inicial completa:
Cree un depósito de AWS S3 (o ya tenga uno) en su cuenta de AWS.
Adjunte una política mínima a ese usuario/rol que le permita acceder al depósito S3:
{
"Sid" : " S3Access " ,
"Effect" : " Allow " ,
"Action" : [ " s3:PutObject " , " s3:GetObject " , " s3:ListBucket " ],
"Resource" : [ " arn:aws:s3:::<BUCKET> " , " arn:aws:s3:::*/* " ]
}
Opcional (pero recomendado): use claves de depósito SSE-KMS para cifrar el contenido del depósito, asegúrese de que el usuario/rol creado anteriormente tenga permiso para acceder y usar la clave.
{
"Sid" : " KMSAccess " ,
"Effect" : " Allow " ,
"Action" : [ " kms:Decrypt " , " kms:GenerateDataKey " ],
"Resource" : [ " arn:aws:kms:<REGION>:<ACCOUNT>:key/<KEY_ID> " ]
}
Todos los datos se cifran en reposo y en tránsito de forma predeterminada. Para agregar una capa adicional de seguridad, puede utilizar claves KMS administradas por el cliente para cifrar los datos en reposo en el depósito S3. Recomendamos utilizar claves de Bucket para minimizar los costos de KMS.
El control de acceso al control remoto se garantiza mediante permisos IAM y se puede controlar en:
Los controles remotos S3 se identifican con el prefijo s3://
y, como mínimo, especifican el nombre del depósito. También puede proporcionar un prefijo de clave como en s3://my-git-bucket/my-repo
y un perfil 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
Luego puede agregar un archivo, confirmar y enviar los cambios al control remoto:
echo " Hello " > hello.txt
git add -A
git commit -a -m " hello "
git push --set-upstream origin main
El HEAD remoto está configurado para rastrear la rama que se envió primero al repositorio remoto. Para cambiar la rama HEAD remota, elimine el objeto HEAD s3://<bucket>/<prefix>/HEAD
y luego ejecute git-remote-s3 doctor s3://<bucket>/<prefix>
.
Para clonar el repositorio en otra carpeta, simplemente use la sintaxis normal de git usando el URI s3 como remoto:
git clone s3://my-git-bucket/my-repo my-repo-clone
Crear ramas y empujarlas funciona normalmente:
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
Todas las operaciones de git que no dependen de la comunicación con el servidor deberían funcionar como de costumbre (por ejemplo, git merge
).
Para usar LFS primero necesitas instalar git-lfs. Puede consultar la documentación oficial sobre cómo hacer esto en su sistema.
A continuación, debe habilitar la integración de S3 ejecutando el siguiente comando en la carpeta del repositorio:
lfs-s3-py install
que es un atajo para:
git config --add lfs.customtransfer.lfs-s3-py.path lfs-s3-py
git config --add lfs.standalonetransferagent lfs-s3-py
Supongamos que queremos almacenar un archivo TIFF en 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
Se considera válido un URI de Amazon S3 para un depósito válido y un prefijo arbitrario que no contiene la estructura correcta.
git ls-remote
devuelve una lista vacía y git clone
clona un repositorio vacío para el cual el URI de S3 está configurado como origen remoto.
% 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)
Consejo : este comportamiento se puede utilizar para crear rápidamente un nuevo repositorio de Git.
Debido a la naturaleza distribuida de git
, puede haber casos (aunque raros) en los que diferentes usuarios ejecuten 2 o más git push
al mismo tiempo con su propia modificación de la misma rama.
El comando git ejecuta el push en 2 pasos:
git-remote-s3
que escribe el paquete en el depósito S3 en la ruta refs/heads/<branch>
En caso de que se ejecuten dos (o más) comandos git push
al mismo tiempo desde diferentes clientes, en el paso 1 se obtiene la misma referencia válida, por lo tanto, ambos clientes continúan con el paso 2, lo que da como resultado que se almacenen varios paquetes en S3.
La rama ahora tiene múltiples referencias principales y cualquier git push
posterior falla con el error:
error: dst refspec refs/heads/<branch>> matches more than one
error: failed to push some refs to 's3://<bucket>/<prefix>'
Para solucionar este problema, ejecute el comando git-remote-s3 doctor <s3-uri>
. De forma predeterminada, creará una nueva rama para cada paquete que no deba conservarse. Luego, el usuario puede verificar la sucursal localmente y fusionarla con la sucursal original. Si, en cambio, desea eliminar el paquete, especifique --delete-bundle
.
Al clonar un repositorio usando el control remoto S3 para LFS, git-lfs
no puede saber cómo recuperar los archivos ya que aún tenemos que agregar la configuración.
Implica 2 pasos adicionales.
% 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
...
Para arreglar:
cd lfs-repo-clone
lfs-s3-py install
git reset --hard main
Para eliminar ramas remotas que ya no se usan, puede usar el comando git-s3 delete-branch <s3uri> -b <branch_name>
. Este comando elimina los objetos del paquete de Amazon S3 en la ruta de la rama.
Para proteger/desproteger una rama, ejecute git s3 protect <remote> <branch-name>
respectivamente git s3 unprotect <remote> <branch-name>
.
Los paquetes se almacenan en el depósito de S3 como <prefix>/<ref>/<sha>.bundle
.
Al enumerar la referencia remota (por ejemplo, explícitamente a través de git ls-remote
), enumeramos todas las claves presentes en el archivo dado.
Al enviar una nueva referencia (por ejemplo, una confirmación), obtenemos el sha de la referencia, agrupamos la referencia a través de git bundle create <sha>.bundle <ref>
y la almacenamos en S3 de acuerdo con el esquema anterior.
Si la inserción tiene éxito, el código elimina el paquete anterior asociado a la referencia.
Si dos usuarios envían simultáneamente una confirmación basada en el mismo encabezado de rama actual al control remoto, ambos paquetes se escribirán en el repositorio y el paquete actual se eliminará. No se pierden datos, pero no será posible realizar más envíos hasta que se eliminen todos los paquetes menos uno. Para esto puedes usar el comando git s3 doctor <remote>
.
La integración LFS almacena el archivo en el depósito definido por el URI remoto, bajo una clave <prefix>/lfs/<oid>
, donde oid es el identificador único asignado por git-lfs al archivo.
Si ya existe un objeto con la misma clave, git-lfs-s3 no lo vuelve a cargar.
Utilice el indicador --verbose
para imprimir información de depuración al realizar operaciones de git. Los registros se pondrán en stderr.
Para operaciones LFS, puede habilitar y deshabilitar el registro de depuración mediante git-lfs-s3 enable-debug
y git-lfs-s3 disable-debug
respectivamente. Los registros se colocan en .git/lfs/tmp/git-lfs-s3.log
en el repositorio.
La integración de git S3 se inspiró en el trabajo de Bryan Gahagan en git-remote-s3.
La implementación de LFS se benefició de lfs-s3 de @nicolas-graves. Si no necesita utilizar el transporte git-remote-s3, debe utilizar ese proyecto.