Subiendo miles y miles de archivos a GitHub fácilmente con Git+Bash

A veces un “git add -A” no es la mejor opción para subir muchísimos archivos y menos cuando son muy pesados, aprende cómo hacerlo de mejor forma con este tutorial

Recientemente estoy trabajando con una empresa que tiene una e-commerce bastante grande y con la finalidad de respaldar y administrar el trabajo entre múltiples desarrolladores que me encuentro dirigiendo se planteó por parte del dueño almacenar todo en un repositorio en GitHub.

La cuestión era, ¿cómo subir carpetas con enorme cantidad de contenidos?, como sabemos después de un rato de subir bastantes archivos Git empieza a tronar por lo que necesitamos ir haciendo un git add archivo uno por uno para que nos empiece a subir los archivos por steps o por carpetas, pero, ¿qué tal si yo tengo una carpeta llamada por ejemplo “img” y esta carpeta, trae digamos 250,000 archivos de entre 200kb y 1mb?.

Es aquí donde venía el problema, el poder subir no era un problema realmente, ya que como menciono se puede ir por carpetas, por archivos, pero el tiempo que consume estar haciendo esto era enorme, así que empecé a pensar en una solución, ¿cómo puedo de forma automatizada y sin tener que estar al pendiente subir tantos archivos?.

Y es aquí donde pensé, ¿por qué no se seccionan los archivos en distintos pesos, así se empiezan a subir los menos pesados hasta los más pesados (máximo 100mb ya que es el pico que acepta GitHub y después de eso se ocupa LSF, sin contar que no había archivos de esta cantidad de peso)?

Aquí es donde di con la solución, ¡Bash!, ¿no tienes Debian/Ubuntu o un ambiente dónde ejecutarlo?, sin problema en Windows 10 puedes correr la bash de Ubuntu y ¡Listo!.

Vamos a ver la solución, lo primero es que necesitamos tener nuestro repositorio ya listo, creamos entonces una carpeta y en ella agregamos un archivo README.md para que esté de archivo inicial.

Después arrancamos el repositorio:

git init
git add README.md
git commit -m "Primer commit"
git remote add origin [email protected]:TU_USUARIO/TU_REPO.git
git push -u origin master

De esta forma sustituimos TU_USUARIO y TU_REPO por tu usuario de GitHub y tu repositorio respectivamente.

Ya que tengamos esta parte, sabemos que ambos repos en GitHub como en Local están vinculados y ya podríamos hacer push para empezar a trabajar, pero, antes que eso vamos a dejar que el script no se pare a preguntarnos ningún dato.

Como utilizamos SSH en este caso a la hora de vincular el repositorio, Git necesitará una llave SSH vinculada. Hacer esto es muy sencillo:

Abrimos la Git Bash o la misma Bash de Ubuntu (En Windows o en Ubuntu, ambas funcionan perfecto) y corremos el primer comando:

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Y aquí sustituimos por su correo registrado en GitHub. De esta forma ya genera una llave, ahora nos indicará dónde queremos guardarla y la mandamos a /c/Users/TU_USUARIO/.ssh/id_rsa solamente presionando enter.

Por último nos pedirá una contraseña y le incluimos algo para mantener de forma segura la llave SSH y así no cualquiera pueda utilizarla para hacer movimientos.

Ahora, hay que iniciar el ssh-agent en el fondo para ello corremos el comando:eval $(ssh-agent -s) y si inició correctamente, veremos la respuesta estilo Agent pid 59566 . Ahora hay que agregar la llave privada al agente SSH con el comando ssh-add ~/.ssh/id_rsa y listo.

Ahora hay que agregar esa llave SSH a GitHub, primero hay que copiar la llave SSH, para ello podemos hacer uso de una librería como xclip, para usarla solo hay que instalarla usando sudo apt-get install xclip, después solo usamos el comando xclip -sel clip < ~/.ssh/id_rsa.pub, ahora sin cerrar la consola, vamos a la página de GitHub.

En la página de GitHub vamos a cliquear en la imagen de perfil arriba a la derecha y hacer click en “Settings”. Después vamos a buscar SSH and GPG Keys en el menú lateral izquierdo.

Hacemos clic en New SSH Key o Add SSH Key, en el título ponemos algo que describa la key por ejemplo “Computadora de la oficina”, en la parte de la Key solamente pegamos el contenido que ya habíamos copiado de la consola.

Por último la guardamos y ¡Listo!. Ya quedó nuestra llave SSH.

Ahora en la consola que teníamos, vamos a probar que funcione con el comando ssh -T [email protected] nos va a aparecer que si queremos validar el host o IP de GitHub, le decimos que “si” (yes).

Puede que nos solicite después la “contraseña” de haber aceptado la autenticación. Si es así, incluimos la que pusimos a la hora de crear la llave.

Hasta este punto ya autenticamos, logueamos y vimos que todo está correcto, es hora de lanzar nuestro script.

En esta consola que no hemos cerrado (esto con la finalidad de no tener que agregar al agente una vez más ni nada por el estilo) vamos a ver el script:

#!/bin/sh
#
# Git.sh
#
# Uso: ./git.sh
#
# Original: http://sekika.github.io/2016/06/06/github-many-files/
#
# Sin acentos*

# Registros
AddLog="/dev/null"
CommitLog="/dev/null"
PushLog="/dev/null"

# Mensaje
message=$@
if [ -z "$message" ]; then
  message="Subiendo archivos de forma automatica"
fi

# Haciendo los git add/commit/push por steps
while read a b c
do
  total=`find . -type f -size +$a -size -$b | grep -v "^\./\.git/" | wc -l | sed -e 's/ //g'`
  if [ $total -gt "0" ]; then
    echo "Archivos totales $total < $b                              "
  fi
  find . -type f -size +$a -size -$b | grep -v "^\./\.git/" | cat -n | while read num file
  do
    echo "Agregando: "`expr $num \* 100 / $total`"% ($num/$total)\r\c"
    git add "$file" 1>>$AddLog 2>>$AddLog
    if [ `echo $num | grep "$c"` ]; then
      echo "Agregando al commit $num                    \r\c"
      git commit -m "$message" 1>>$CommitLog 2>>$CommitLog; git push 1>>$PushLog 2>>$PushLog
    fi
  done
  if [ $total -gt "0" ]; then
    echo "Ultimo commit de esta etapa                \r\c"
    git commit -m "$message" 1>>$CommitLog 2>>$CommitLog; git push 1>>$PushLog 2>>$PushLog
  fi
done << _LIST_
0 8k 0000$
8k 80k 000$
80k 800k 00$
800k 8M 0$
8M 100M $
_LIST_

#
# Todos los archivos subidos, en esta etapa se intentan subir con LSF
#
echo "Concluyendo con los archivos mas grandes                       "
git add . 1>>$AddLog 2>>$AddLog
git commit -m "$message" 1>>$CommitLog 2>>$CommitLog; git push 1>>$PushLog 2>>$PushLog

echo "Finalizado"

Este código lo agregamos en un archivo llamado git.sh dentro de la carpeta del repositorio, es decir, donde inicializamos previamente el repo ahí deberá vivir y le damos permisos de ejecución con chmod +x git.sh . De preferente este archivo lo deberán de agregar al .gitignore para evitar que se suba a si mismo.

Cabe mencionar que aquí, no pensamos que tendrán archivos de más de 100 megas de peso, si es así deberán configurar Git LSF (https://git-lfs.github.com/)

Con esto, estamos al 90% del tutorial, solo hace falta modificar el HTTP Post Buffer Size de nuestra configuración de Git con el comando git config http.postBuffer 52428800 de esta forma estamos ahora sí listos para empezar.

Ahora si le aventamos a la carpeta los chorromil archivos que necesitamos subir, una vez hecho esto, nos queda solo ejecutar el script previo:

./git.sh

Y veremos como en nuestro repo se empiezan a generar los commits de forma automática y subiéndose los archivos, solo hay que dejar que el script funcione y listo.

Como último para finalizar el tutorial, les hago mención de que el LFS utiliza un ancho de banda limitado, si se pasan deberán pagar por ello así que si quieren retirar los archivos de 100+ megas, lo hacen con este comando:

find . -size +100M | sed -e 's/^\.\///' >> .gitignore

A veces incluso puede que les caigan errores en aquellos archivos que tengan espacios, en lo personal no recomiendo nunca usar archivos con espacios, mejor con guiones bajos, medios para un mejor manejo, si les da error, chequen los archivos con espacios y retiren esos archivos de forma temporal o, si no hay problema con que cambien su nombre, pueden hacer el cambio de espacio a guión bajo con el comando:

for A in $(find . | grep " " | sed -e s/" "/x3Exe/g) ; do mv "$(echo $A | sed -e s/x3Exe/' '/g)" "$(echo $A | sed -e s/x3Exe/'_'/g)"; done

Y si tenían ya cambios previos que intentaban pushear pero no podían con el comando: git reset HEAD~ retiran lo que tenían agregado con git add -A ... y listo pueden hacer uso del script.

Eso es todo, no te olvides de dejarnos tu Clap para más tutoriales y seguirme aquí en Medium si te agradan mis publicaciones. ¡Suerte!

¿Cuál es tu reacción?
+1
0
+1
0
+1
0
+1
0
+1
1
Total
0
Shares
Publicación anterior

Haciendo gráficas en “tiempo real” con Angular, ChartJS y  NodeJS

Siguiente Publicación

Desarrollando una sencilla API REST con NodeJS y Express

Publicaciones Relacionadas