Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducción a Git

Introducción a Git

Curso que cree en 2015 focalizado en las herramientas de Jetbrains. Concretamente para Android Studio y un equipo de desarrollo de Android.

Jose María Flores Zazo

January 07, 2022
Tweet

More Decks by Jose María Flores Zazo

Other Decks in Programming

Transcript

  1. Jose María Flores Zazo
    https://jmfloreszazo.com
    Introducción a Git para Android Studio
    Autoformación 2015

    View Slide

  2. • Introducción a Git.
    • Instalación y configuración de Git.
    • Ignorar ficheros.
    • Añadir Ficheros.
    • Añadir Repositorio en Bitbucket de la App.
    • Clonación (Cloning) de la App: HelloWorld.
    • Bifurcación (Forking) de la App: HelloWorld.
    • Derivación (Forking) de la App: HelloWorld.
    • Usando el Log de Git.
    • Ramificación (Branching).
    • Desarrollo de una Rama (Branch).
    • Git Commits y Ramas.
    • ¿Cómo revertir (revert) los cambios?.
    Índice I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  3. • Diferencia entre Revert y Reset.
    • Fusión (Merging).
    • Resetear el Historial de Cambios.
    • Reorganización (Rebase) de Git.
    • Detached Head (Jefe Independiente).
    • Referencias Relativas.
    • Resolución de Conflictos en Rebasing.
    • Git en Remoto.
    • Pull vs. Push.
    • Resumen.
    • Anexo I: GitLab.
    • Sitios y Recursos Recomendados.
    • Bibliografía.
    Índice II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  4. • El sistema de control de versiones (VCS) Git se esta convirtiendo rápidamente
    en estándar de facto, no sólo en el desarrollo de aplicaciones Android, en toda
    la industria del software.
    • A diferencia de los anteriores VCS que requieren el uso de un servidor central,
    Git es distribuido, es decir, que cada copia del repositorio contiene toda la
    historia del proyecto y ningún colaborador (contributor) tiene más privilegios
    que otro.
    • Git fue desarrollado por Linus Torvalds para gestionar el desarrollo del sistema
    operativo Linux.
    • Y al igual que el movimiento de código abierto, Git es sistemáticamente no
    jerárquico y alienta el modelo colaborativo.
    • Git basa su trabajo en la línea de comandos, pero como presentación esta ligada
    a Android Studio vamos a centrarnos en el uso dentro del entorno.
    Intoducción a Git
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  5. • La herramienta la descargaremos de https://git-scm.com/downloads.
    • Mi recomendación es instalar Git en un directorio corto, por ejemplo en el de Java,
    pero si decides instalarlo en otro sitio asegúrate que las rutas no tengan nombre con
    espacio.
    • Una vez instalado debemos asegurarnos que el directorio \git\bin\ es parte de
    nuestras variable de entorno PATH.
    • Para ejecutar Git, debemos ir al icono que lanza el terminal Git Shell. Y para ver que
    todo esta bien y realizar una pequeña personalización, vamos a ejecutar:
    git config -–global user.name “Jose Maria Flores Zazo”
    git config -_–global user.email “[email protected]
    Instalación y configuración de Git I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  6. • La herramienta que usaremos como cliente visual será SourceTree:
    https://www.sourcetreeapp.com/.
    • SourceTree no es una herramienta de uso exclusivo para Bitbucket, algo que
    podríamos pensar ya que ambos pertenecen a la compañía Altassian.
    • Podremos usar esta herramienta tanto en GitHub como en un Git Server
    privado.
    Instalación y configuración de Git II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  7. • Si no tienes una cuenta en Bitbucket es el momento de crearla, ya que en este
    curso es el sistema de alojamiento que vamos a usar.
    • Independientemente de estas herramientas comunitarias, vamos a poder
    instalar un servidor en nuestra propia red, bien sea por la política de la empresa
    de IT en la que trabajemos o bien sea porque deseamos tener una privacidad
    absoluta de nuestras fuentes. En este caso mi propuesta es: GitLab. Más
    información en el Anexo I.
    Instalación y configuración de Git III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  8. • Volvemos a Android Studio y creamos un proyecto de pruebas, llamado
    HelloWorld y damos siguientes a todas las opciones.
    • Ahora vamos a configurarla integración con Git desde File → Settings, y
    buscamos Git en la opción Version Control. En el panel derecho tenemos que
    elegir la ruta donde hemos instalado Git seleccionado el ejecutable “git.exe” y
    probamos con el botón de Test. Y debe salir una ventana informativa con el
    mensaje “Git executed sucessfully”.
    • El siguiente paso es situarnos en el menú VCS → Import into Version Control →
    Create Git Respository. Y marcar la raíz del proyecto:
    Instalación y configuración de Git IV
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  9. • Aceptamos y ya hemos añadido nuestro proyecto a repositorio.
    • Podrás observar que la mayoría de los nombres de archivo en la ventana de
    herramienta de proyecto se han vuelto marrón.
    • Esto significa que los archivos están reconocidos por Git localmente pero no
    están siendo rastreaos por Git y no se han sido programado para añadirlos.
    • Esto se debe a que Git usa el commit en dos etapas (que es diferente al usado
    por otras herramientas de control de versiones como TFS, Subversion o Visual
    Sourcesafe). En el área de preparación es donde Git organiza los cambios antes
    de una confirmación. La diferencia entre los cambios en curso, el área de
    preparación de cambios y los cambios confirmados son significativas y pueden
    abrumar a los nuevos usuarios y como resultado, Android Studio no expone
    estas diferencias; en lugar de ello muestra una sencilla interface de cambios que
    permite gestionar archivos modificados y hacer un commit de ellos con mayor
    facilidad.
    Instalación y configuración de Git V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  10. • Cuando creamos un repositorio local, Android Studio genera un fichero llamado
    .gitignore, que nos permitirá indicar ficheros y directorios que no va a ser
    rastreados.
    • Este fichero es habitual que se encuentre en la raíz del proyecto.
    • Por defecto Android Studio nos provee de una configuración inicial que no pertenece
    al proyecto en si mismo, si no que es único por usuario o espacio de trabajo:
    • Debemos prestar especial atención la /build. Gradle sitúa todas las salidas de
    compilación aquí y como es lógico estará continuamente cambiando y por tanto no
    tiene ningún sentido rastrearlo.
    Ignorar ficheros I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  11. • Android Studio usa una guía de colores que nos permite fácilmente identificar
    que es lo que está o no viendo nuestro sistema de control de versiones:
    • Marrón, que ya mencioné, indica que Git está reconociendo el fichero de forma local
    pero no lo está rastreando y no lo está programando para ser añadido.
    • Verde se usa para los archivos que están siendo rastreado por Git.
    • Negro (o blanco, depende del theme usado) indica que los o bien no han cambiado o
    bien no están siendo rastreados por Git.
    • Android Studio mantiene un constante seguimiento de los archivos agregados al
    proyecto para mantenerlos sincronizados con Git .
    Ignorar ficheros II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  12. • Abrimos la vista “Version Control” en la parte inferior de la ventana y pulsamos
    sobre el icono de la carpeta:
    • Podrás ver que existen dos carpetas “Default” y “Unversioned Files”.
    • La sección “Default”, inicialmente vacía, representa los cambios activos, tan pronto
    como cambies un fichero, dicho fichero se moverá a esta sección, es decir, son
    ficheros a los que vamos a realizar un commit en el VCS.
    • Los ficheros bajo “Unversioned Files” son aquellos que no están siendo rasterados
    por VCS.
    Añadir Ficheros I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  13. • En nuestro ejemplo de HelloWorld, ningún fichero está siendo rastreados y por
    tanto están bajo la sección “Unversioned Files”.
    • No situamos en la carpeta “Unversiones Files” y con el botón derecho del ratón
    seleccionamos la opción “Add to VCS”.
    • Después de añadir los ficheros estos cambian al color verde.
    • Y finalmente pulsamos sobre “Commit Changes”que nos mostrará la ventana
    que permite realizar el commit.
    Añadir Ficheros II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  14. • En la primera versión del proyecto daremos un mensaje como por ejemplo
    “Primer commit de HelloWorld”.
    • Durante el proceso podremos indicar el autor, si vamos a revisar los TODO que
    tengamos pendiente, etc.
    Añadir Ficheros III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  15. • Si no tenemos la cuenta de Bitbucket y la herramienta SourceTree instalada, es
    el momento de hacer estos pasos.
    • Ejecutamos el programa SourceTree y como sugerencia creamos una carpeta
    para diferenciar nuestros .
    Añadir Repositorio en Bitbucket de la App I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  16. • Ahora elegimos la opción “Add Working Copy” y la ruta local.
    • Tras ejecutar Add, nos situaremos en el proyecto HelloWorld y nos vamos a
    nuestra cuenta de Bitbucket para crear el contenedor.
    Añadir Repositorio en Bitbucket de la App II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  17. • En nuestra cuenta de Bitbucket, seleccionamos Crear → Crear Repositorio.
    Añadir Repositorio en Bitbucket de la App III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  18. • Una vez creado, nos muestra la siguiente ventana, donde debemos elegir
    “Tengo un proyecto existente” para poder obtener la URL que vamos a copiar y
    usar en SourceTree
    Añadir Repositorio en Bitbucket de la App IV
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  19. • Y de vuelta a SourceTree, desde Settings, vamos a Remotes → Add y rellenamos
    en base a la siguiente captura, indicando la URL / Path que hemos generado
    desde Bitbuket.
    • Nota: Podremos elegir otro tipo de Host, como GiyHub o el nuestro.
    Añadir Repositorio en Bitbucket de la App V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  20. • Al pulsar sobre OK, ya estamos listos para poder subirlo a nuestro espacio
    remoto con solo pulsar sobre la opción de menú “Push” y marcar la rama
    “master” que se copiará en la rama “master” remota.
    • Y tras pulsar sobre OK comenzará el volcado del proyecto en nuestro
    repositorio on-line.
    Añadir Repositorio en Bitbucket de la App VI
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  21. • Y si volvemos a Bitbucket ya podremos ver nuestro proyecto en el dashboard.
    Añadir Repositorio en Bitbucket de la App VII
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  22. • Clonar es cuando hacemos un clon de un repositorio, es decir, nos bajamos una copia del mismo a
    nuestra máquina. Comenzamos a trabajar, hacemos modificaciones y luego hacemos un Push. ¡Cuando
    haces el Push estás modificando el repositorio que hemos clonado!.
    • Primero borramos el directorio desde el explorador de fichero y luego borramos el proyecto en
    SourceTree (nos mostrará una advertencia al entrar, eso es sinónimo de el rastreo continuo que hace
    Git).
    • Desde SourceTree, no situamos en la carpeta “ejemplos” y ejecutamos Clone/New → Clone Repository
    → Botón con el icono del símbolo terrestre y elegimos el proyecto a HelloWorld a clonar.
    Clonación (Cloning) de la App: HelloWorld
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  23. • Este término no pertenece a Git, es un termino que acuñan los sistemas
    remotos como GitHub y Bitbucket.
    • Cuando hacemos un fork de un repositorio, se crea un nuevo repositorio en la
    cuenta de GitHub o Bitbucket, con una URL diferente (fork) y acto seguido
    tenemos que hacer un clon de esa copia sobre la que empezamos a trabajar
    cuando hacemos un Push. Por tanto ¡estás modificando TU COPIA (fork)!. El
    repositorio original sigue intacto.
    • Hacer un fork implica mucha terminología y gestión de proyectos, ya que estos
    cambios que yo tengo puedo pedir que un jefe de proyecto realice el “pull
    requests” y mueva esos cambios a la versión padre y a su vez mueva esos
    cambios a los diferentes fork del proyecto.
    • Esta introducción no pretende entrar en estos detalles, pero sí que vamos a
    partir de un fork para continuar aprendiendo más cosa de este marco de
    trabajo.
    Bifurcación (Forking) de la App: HelloWorld I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  24. • Este término no pertenece a Git, es un termino que acuñan los sistemas
    remotos como GitHub y Bitbucket.
    • Cuando hacemos un fork de un repositorio, se crea un nuevo repositorio en la
    cuenta de GitHub o Bitbucket con una URL diferente (fork) y acto seguido
    tenemos que hacer un clon de esa copia sobre la que empezamos a trabajar
    cuando hacemos un Push. Por tanto ¡estás modificando TU COPIA (fork)!. El
    repositorio original sigue intacto.
    • Hacer un fork implica mucha terminología y gestión de proyectos que se sale de
    esta introducción. Estos cambios en mi fork para que reviertan en el proyecto
    principal debe hacerse con un “pull requests” y este a su vez mueva esos
    cambios a la versión padre e inmediatamente se trasladan a los diversos fork
    que existan.
    • Esta introducción no pretende entrar en estos detalles, pero sí que vamos a
    partir de un fork para continuar aprendiendo más cosa de este marco de
    trabajo.
    Derivación (Forking) de la App: HelloWorld I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  25. • Desde nuestra cuenta de Bitbucket y en situados en el proyecto HelloWorld,
    pulsamos derivación y Dividimos el repositorio.
    • Dividir es una forma de contribuir a un proyecto aun cuando no tengamos
    permisos de escritura.
    Derivación (Forking) de la App: HelloWorld II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  26. • El siguiente paso es clonar el repositorio y comprobar que existe: entramos
    desde el Dashboard Bitbucket al nuevo proyecto HelloWorld2.
    • Entramos en el proyecto y pulsamos sobre clonar para obtener la URL que
    debemos usar en Android Studio.
    • Una vez dentro de Android Studio, nos situamos en VCS → Checkout from
    Version Control → Git.
    • Y una vez clonado, podremos abrir el nuevo proyecto.
    Derivación (Forking) de la App: HelloWorld III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  27. • El log de Git es una herramienta muy potente, no da la posibilidad de explorar el historial
    de commit (finalizar/aceptar/asentar) de nuestro proyecto.
    • O bien entramos desde la carpeta inferior de Version Control o bien usando Alt+9 y una
    vez dentro sobre la opción Log.
    • Haciendo clic en cada uno de los nodos de la línea de tiempo, podremos ver información
    en los paneles de la derecha e izquierda de la sección Log.
    • Y si haces clic en cualquier archivo del panel derecho, nos mostrar una ventana donde
    podremos hacer comparaciones del historial, quien lo modifico, cuando, fechas, el código
    hash, etc.
    Usando el Log de Git
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  28. • Hasta ahora hemos realizado los commits en una sola rama (branch), la rama master
    (maestro), que es el nombre de la rama por defecto. Y no tenemos por qué permanecer
    en la rama master.
    • Git permite hacer tantas ramas como queramos y las ramas pueden servidos para
    diferentes propósitos. Por ejemplo en este escenario: si trabajamos con un equipo de
    desarrolladores y cada uno está asignado a tareas específicas, por ejemplo unos a
    programar nuevas funcionalidades (dev) y otros a depurar los errores (bug). La manera
    lógica de abordar cada tarea es convirtiéndolas en ramas. Cuando el desarrollador
    completa una tarea y la prueba, deberán fusionar la rama dev en la rama bug y el
    desarrollador continua su trabajo en dev. Al final del ciclo la rama bug se prueba por el
    equipo de control de calidad, que, o bien rechaza los cambios y envía el proyecto de nuevo
    a desarrollo o bien fusiona la rama bug a la rama master. Este proceso se llama Git Flow,
    y es la forma recomendada para desarrollar software en un equipo de Git. Más
    información sobre Git Flow.
    • Flujo Git funciona muy bien con los equipos grandes, pero si estás desarrollando en
    solitario o trabajas con sólo uno o dos desarrolladores, es posible que queramos usar un
    flujo de trabajo diferente. Sea cual sea su flujo de trabajo, la funcionalidad de ramificación
    en Git es flexible y nos permitirá adaptar el flujo de trabajo.
    • Nota: SourceTree un apartado donde implementa el ciclo de vida GitFlow.
    Ramificación (Branching)
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  29. • Supongamos que vamos a añadir una nueva funcionalidad a nuestro programa
    HelloWorld2.
    • Abrimos el proyecto HelloWorld2 y en entramos en VCS → Git → Branches → New
    Branch, creamos la rama.
    • Ya tenemos nuestra nueva rama incluyendo el checkout de la misma. Abrimos la ventana
    de cambios (Changes) y creamos una lista de cambios.
    Desarrollo de una Rama (Branch) I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  30. • Entramos en VCS → Commit Changes … o Crtl+K. Podremos movernos por los ficheros
    nuevos, por los antiguos y ver que hemos cambiado, etc.
    Desarrollo de una Rama (Branch) II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  31. • Una buena praxis es revisar el código mediante la opción de diferencias, para
    poder ver variables que estén en color gris claro, aquellas que no se usan, así
    como dar un vistazo general al nuevo código por si algo hemos realizado mal, de
    este modo dejamos el código más pulcro y depurado.
    • Pulse la tecla Esc para cerrar el punto de vista de diferencias y añade un
    mensaje de confirmación antes de confirmar los cambios, habitualmente
    propondrá el comentario de la lista activa.
    • Pulsa sobre Commit para permitir que Android Studio realice el análisis de
    código, si hemos marcado la opción inmediatamente verás otro cuadro de
    diálogo que indica que algunos de los archivos contienen problemas: el cuadro
    de diálogo insinúa que hay advertencias en el código. En este punto, podemos
    hacer clic en el botón Revisar para cancelar el commit y generar una lista de
    todos los posibles problemas o bien continuar y realizar definitivamente el
    commit.
    Desarrollo de una Rama (Branch) III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  32. • El estilo de confirmaciones de Git basado en ramas es similar pero algo diferente de
    lo que estamos acostumbrados en TFS, Visual SourceSafe o Subversion.
    • Debemos entender las sutiles diferencias de Git a la hora de maneja los commit y las
    ramas. Este tratamiento es el núcleo de la potencia y flexibilidad de Git y no
    queremos confundir a los recién llegados, por eso vamos a ver una serie de
    diagramas y explicaciones donde aprenderemos bien todos los conceptos.
    • Los commits en Git se tratan como entidades de primera clase en el histórico de un
    proyecto, son identificables por un código hash especial. Si bien no es necesario
    entender esta clase de detalles es importante pensar en las confirmaciones
    (commits) como objetos o entidades que existen dentro de un la línea del tiempo del
    historio del repositorio.
    • Un commit existe como una unidad atómica del trabajo que se ha producido en un
    momento en la historia y que lleva asociado una nota con el mensaje del informe
    que describe el trabajo.
    • Cada commit tiene un padre de uno o más commit que le preceden.
    • Puedes “pensar en la siguiente asociación”: las ramas son las etiquetas que apuntan
    a un commit individual en el histórico.
    • Cuando se crea una rama, se crea una etiqueta en ese punto de la historia, y como
    hemos realizado un commit sobre esa rama, la etiqueta sigue la historia de lo
    commits.
    Git Commits y Ramas I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  33. • La rama principal está representada con la flecha gris y apunta al último commit
    A del proyecto clonado.
    • La rama EtiquetaTexto001 es la flecha verde y apunta al último commit de la
    serie de commits B y C que implementan una nueva funcionalidad.
    • Usamos las letras A, B y C por simplificar, Git usa un código hash.
    Git Commits y Ramas II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    Nota: Android Studio representa el log de commits de abajo a
    arriba, mientras que estos diagramas los voy a poner de arriba
    abajo.

    View Slide

  34. • Una de las cosas que más quebraderos de cabeza da al principio en Git, es la
    opción de revertir (revert) cambios, en cierta medida es debido a que funciona
    de forma diferente a otros VCS.
    • Git Revert, es un commit (una unidad de trabajo) que deshace un commit
    previo. La mejor forma de entender esto es verlo en acción.
    • Vamos a revertir los cambios en HelloWorld2. Para ello metemos una nueva
    etiqueta de texto “Etiqueta 002” y hacemos un commit del mismo.
    • Revert de Android Studio es muy diferente del comando Revert de Git. Por eso
    voy a trabajar con la línea de comandos para que se entienda la diferencia.
    • Primero copiamos el hash del cambio
    ¿Cómo revertir (revert) los cambios? I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  35. • Desde el terminal de Android Studio. Escribiremos el siguiente comando:
    • Y como resultado obtendremos y escribiremos en esa pantalla “:” y “q” para hacer el
    commit.
    ¿Cómo revertir (revert) los cambios? II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    :q

    View Slide

  36. • Una reversión en Git provoca un nuevo commit y deshace el commit previo.
    Vuelve Android Studio y observa los cambios.
    • El historial de Git refleja ese commit. Git aplica una reserva de todos lo cambios
    previos al commit e inmediatamente realiza el commit con los cambios y
    presenta un mensaje idéntico indicando que existe un Revert.
    • Por el contrario otros sistemas lo que hacen es rastrear las modificaciones
    locales y permiten deshacer los cambios antes del commit.
    • Android Studio no ofrece un interface para hacer que el Revert que he
    mostrado por línea de comandos. Quizá lo implementen en futuras versiones.
    • En el siguiente esquema podemos ver que es lo que sucedió cuando realizamos
    los comandos.
    ¿Cómo revertir (revert) los cambios? III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  37. ¿Cómo revertir (revert) los cambios? IV
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    D
    -D

    View Slide

  38. • La otra forma de deshacer un cambio es usando el comando reset, funciona
    de forma similar a revert, pero con una gran diferencia.
    • Desde Android Studio, VCS → Git → Reset Head. Introduce HEAD~1 en la
    ventana y pulsa sobre reset.
    • Git sincronizara el repositorio al commit anterior de nuestro último commit, es
    decir, es un deshacer del commit, dejando el historial igual que el diagrama de
    la diapositiva 35.
    • Esto nos da una segunda oportunidad en caso de haber ejecutado el reset por
    accidente.
    ¿Cómo revertir (revert) los cambios? V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  39. • Pulsamos el botón reset y nos pedirá los ficheros que queremos aplicar
    ese reset.
    • Una vez aplicados, volveremos a ver lo que teníamos antes.
    • En el siguiente diagramas vamos a ver el reset de forma esquemática.
    ¿Cómo revertir (revert) los cambios? V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  40. ¿Cómo revertir (revert) los cambios? VI
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    D
    -D
    E

    View Slide

  41. • Entre ambos existe una diferencia sutil pero importante: un revert se utiliza
    para deshacer una confirmación anterior. En git, no se puede alterar o borrar un
    commit antes de hacer ejecutarlo. Así que en lugar de la edición de la anterior
    confirmación, revertir introduce un nuevo commit que invierte/deshace un
    commit anterior. Mientras que reset se utiliza para deshacer los cambios en su
    directorio de trabajo que aun no han sido confimados (comitted).
    • Si has confirmado accidentalmente algo, a menudo se desea deshacer o
    eliminar una confirmación. Es razonable utilizar reset en estos casos, ya que es
    la opción más sencilla y no añadir cosas al historial. En algunos casos, sin
    embargo, es posible que desees que el historial refleje el trabajo, como por
    ejemplo una característica que hemos eliminado y queremos dejarlo
    documentado, en cuyo caso se hace un revert.
    • Otro uso importante para revertir se debe a los repositorios remotos, y es que
    sólo se pueden agregar commit a repositorios remotos, la única manera de
    quitar o desconectar un commit en un repositorio remoto es utilizar una
    reversión, que añade los cambios invertidos como una confirmación.
    Diferencia entre Revert y Reset
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  42. • La fusión es un medio de combinar el trabajo a partir de dos ramas separadas.
    Históricamente, las fusiones siempre han requerido un esfuerzo adicional debido a los
    conflictos entre las ramas. Gracias a la implementación de Git las fusiones son más
    sencillas y será necesario menos trabajo.
    • Vamos a empezar añadiendo una nueva característica en la rama principal. Desde VCS →
    Git → Branches. Elige la master y hacemos un checkout y creamos una nueva ChangeList,
    nos dirá que la anterior lista no es la activa y la quitamos.
    Fusión (Merging) I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  43. • De nuevo introducimos una serie de cambios en HelloWorld2. Y hacemos un commit de
    los cambios.
    • Introducimos una nueva etiqueta de texto en el diseño para que podamos ir viendo los
    cambios.
    • Hemos cambiado nuestro HEAD al master y realizado un commit en D. Una forma de ver
    como evoluciona el esquema es desde el historial.
    Fusión (Merging) II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    D

    View Slide

  44. • En VCS → Git → Branches elegimos la rama que habíamos llamado C y
    pulsamos sobre Merge (fusionando C y D). Quedando el proyecto de la
    siguiente forma:
    Fusión (Merging) II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    D
    E
    EtiquetaTexto001

    View Slide

  45. • ¿Qué ocurre si quieres tratar tus recordatorios importantes como una rama? Nunca
    hemos creado una rama para esta función, pero en cambio si que hemos programado
    sobre la rama master.
    • Este este caso se puede forzar a la rama principal a que realice una copia de seguridad y
    apunte a D el commit.
    • Desde VCS → Git → Reset Head. Y en el campo To Commit ponemos HEAD~1. Y
    realizamos un commit.
    • Ahora creamos una nueva rama que llamaremos “EtiquetaTexto002” a la que se asociará
    la nueva lista.
    Resetear el Historial de Cambios I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    D
    EtiquetaTexto002

    View Slide

  46. • En el diagrama anterior master y EtiquetaTexto002 están en la misma rama, es decir, que
    apunta al mismo commit y esto no se debe hacer. Para hacer las cosa bien, debemos
    entrar en VCS → Git → Branches, hacemos un reset en la rama y después un checkout
    para dejar el proyecto de una forma más lógica.
    • Internamente estamos moviendo la rama.
    Resetear el Historial de Cambios II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    EtiquetaTexto001
    D EtiquetaTexto002

    View Slide

  47. • Rebase significa crear una rama desde otra rama o serie de commits. Es similar
    a una fusión (merge) desde el punto de vista que combina ramas pero en
    ningún momento crear commits de varios padres.
    • En VCS → Git Rebase abre el cuadro de dialogo Rebase Branch.
    • En el diremos que queremos hacer un Rebase de la rama master en
    EtiquetTexto001.
    Reorganización (Rebase) de Git I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  48. • Nos presentará una pantalla donde de forma interactiva vamos a quitar y
    cambiar commits individuales de nuestro historial de commits.
    • Esta pantalla nos muestra todos aquellos commits que existen en el historial.
    • Donde podremos optar por realizar acciones por cada uno de ellos: escoger,
    editar, saltar o squash (sin traducción: más bien agrupar dos o más commit en
    uno).
    Reorganización (Rebase) de Git II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  49. • Si decidimos saltar un commit que ya no nos interesa, solo debemos hacer skip
    sobre el.
    Reorganización (Rebase) de Git III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    master
    D
    E
    EtiquetaTexto001
    EtiquetaTexto002

    View Slide

  50. • Partimos de este supuesto: tenemos un desarrollador trabajando en una nueva función cuando
    clonamos el proyecto y deseamos combinar esa funcionalidad.
    • Para simular este escenario, debemos regresar al punto A del historial y empezar la nueva
    característica.
    • Hasta ahora he mostrado como trabajar contra una rama específica: ya sea la master o una con
    nombre personalizado (EtiquetaTexto001/ EtiquetaTexto002).
    • Aquí voy a mostrar una alternativa que existe en Git y que se conoce como Detached HEAD Mode.
    • Si miramos un commit en particular en vez de una rama. HEAD esta desenganchado de cualquier rama
    en la que estas trabajando. Por tanto lo primero que necesitamos es situarnos, por ejemplo, en
    EtiquetaTexto001. Debemos ir a: VCS → Git → Branches
    Detached Head (Jefe Independiente) I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  51. • Es decir, tenemos el siguiente esquema:
    Detached Head (Jefe Independiente) II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    HEAD
    D
    E
    EtiquetaTexto001
    EtiquetaTexto002
    master

    View Slide

  52. • Git ahora nos sitúa en un nuevo HEAD separado de cualquier rama creada como
    parte del desarrollo. Formalmente HEAD habría seguido formando parte de
    cualquier rama que crearas.
    • Al hacer un commit, la rama se movería con el HEAD de la última confirmación.
    • El campo EtiquetaTexto001~1 que hemos introducido es una referencia con
    respecto a donde queríamos comenzar. Se puede asignar referencias relativas
    en la mayoría de las operaciones que esperan precisan de un checkout.
    • Las referencias relativas utilizan uno de los dos formatos siguientes:
    • BranchOrCommitHash^
    • BranchOrCommitHash~NumberOfStepsBack
    • Usar ^ indica un paso atrás en el historial, mientras que ~ indica una serie de
    pasos atrás, tantos como el número indique.
    Detached Head (Jefe Independiente) III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  53. • Se trata de expresiones que Git usa para hacer referencia a un punto
    específico del historial.
    • Constan de un punto de partida o referencia y un objetivo (número de
    pasos del punto de referencia).
    • Habitualmente en las referencias se usa HEAD, pero también podemos
    usar el nombre de una rama o el códiho hash.
    • Las referencias relativas se pueden usar para tareas tales como: mover
    una rama de cualquier lugar del historial, seleccionar un commit en
    particular, o mover el HEAD a un punto específico del historial.
    Referencias Relativas I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  54. • Para ilustrar su uso vamos a crear una nueva rama llamada EtiquetaTexto003 y
    una lista de cambios asociada a esta nueva rama.
    • Añadimos alguna funcionalidad y realizamos un commit del proyecto.
    Referencias Relativas II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    D
    E
    EtiquetaTexto001
    EtiquetaTexto002
    master
    F EtiquetaTexto003

    View Slide

  55. • No debemos alarmarnos con las ventanas emergentes, eso se debe a que Git ha
    encontrado algunos conflictos.
    • Git marca los archivos que no se pueden fusionar automáticamente con un
    estado de conflicto. Y debemos ser nosotros quien resuelva los conflictos para
    que podamos continuar.
    • La resolución de conflictos requiere de esfuerzo y colaboración, especialmente
    cuando realizamos una combinación. Y por eso debemos familiarizarnos con la
    tarea de colaboración haciendo fusiones y resolviendo conflictos.
    • Hacer de estas tareas un hábito, no dará más experiencia a la hora de resolver
    los conflictos.
    Resolución de Conflictos en Rebasing I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  56. • Para resolver el conflicto vamos a VCS → Git → Resolve Conflicts y nos mostrará
    la siguiente venta:
    • Donde podemos admitir los cambios de otro, que sean los mios o bien unificar
    los cambios.
    • Para ilustrar la via complicada, vamos a elegir Merge…
    Resolución de Conflictos en Rebasing II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  57. • Como podremos observar, nos emplaza a realizar la ardua tarea de unificar un
    proyecto. Y mediante los símbolos “»” o “«“ podremos ir avanzando en la
    integración.
    Resolución de Conflictos en Rebasing III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  58. • Una vez admitidos los cambios, volvemos al menú VCS → Git → Continue Rebasing. En este momento tendremos la opción de
    abortar el rebase o saltar este rebase cuando realicemos un commit. En el supuesto caso que estuviésemos en medio de una
    unificación complicada y hubiésemos realizado algo verdaderamente catastrófico, podremos abortar y dejar todo en el estado
    anterior al iniciar el rebase. Si accidentalmente se realizar un commit con conflictos, tendremos la opción de saltar. Si no estamos
    en ninguno de esos casos, lo normal es continuar con el Rebasing. Y tras esta acción se crea un commit
    que podremos ver reflejado en el historial.
    Resolución de Conflictos en Rebasing IV
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    A
    B
    C
    D
    EtiquetaTexto001
    EtiquetaTexto002 F EtiquetaTexto003
    B’
    C’
    E’ master

    View Slide

  59. • Master contiene los commits de B y C, EtiquetaTexto001, commit de E; y
    commits de F con EtiquetaTexto003. Y si lo deseamos podremos meter
    EtiquetaTexto002 con otro rebase.
    • Y finalmente vamos a poner la rama master en nuestra cuenta de Bitbucket.
    Desde VCS → Git → Push…
    Git en Remoto V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    Por si alguien lo
    pregunta, aquí
    unifiqué todas las
    funcionalidades para
    continuar con el
    master.

    View Slide

  60. • Ya hemos usado Bitbucket y seguro que muchos conocen de la existencia de GitHub, ambos sistemas gratuitos hasta
    cierto punto nos permiten tener sincronizados nuestros repositorios en un hosting on-line.
    • Remoto básicamente significa respaldos del repositorio Git almacenados en un servidor accesible sobre una red.
    • Podemos usarlo de forma similar a un VCS tradicional basado en cliente/servidor, pero es mejor pensar en ellos como
    copias del acceso publico/privado a nuestro trabajo. Es decir nuestro flujo de trabajo en Git no es hacer commit a un
    servidor central compartido, si no, hacer en solicitudes de código en un servidor central.
    Git en Remoto I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    Usuario A
    Fichero
    Usuario B
    Fichero
    Servidor Central VCS
    Base de datos de
    Versiones
    Version 1.1
    Version 2
    Version N
    Computadora Local
    Base de datos de
    Versiones
    Version 1.1
    Version 2
    Version N
    Fichero
    Checkout
    Servidor Central
    VCS
    Base de datos de
    Versiones

    View Slide

  61. • La forma habitual de trabajar es mediante la clonación completa de un proyecto Git del
    repositorio para poder trabajar en local donde realizamos cambios y commit a nivel local
    para finalmente impulsar (push) esos cambios al servidor remoto.
    • Otra forma habitual es trabajar en local, construir el proyecto y a continuación, impulsar el
    proyecto al servidor Git. Si lo hemos publicado en Bitbucket podremos hacer que sea
    publico o privado e invitar a desarrolladores a colaborar.
    • Una vez que esos cambios están el servidor, aquél desarrollador que tiene privilegios
    sobre un átomo superior será quien realice la integración mediante las herramientas de
    Git.
    • Esos cambios una vez integrados pueden ser enviados a los desarrolladores que cuelgan
    bajo la rama en la que hemos estado integrando y se hace mediante una petición de carga
    (pull).
    Git en Remoto II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  62. • Aquí se muestra como un bug fue arreglado siguiendo una metodología de Git. Es decir, estamos
    usando el método distribuido (lo veremos más adelante en la demo).
    • Explicación: hacemos commit 0, 1, 2, suponiendo que trabajamos con CI (integración continua) o
    similar, alguien nos avisa y nos dice que hay un error en C2, pero ya habíamos crreado creamos la
    rama iss53 para meter una nueva carácterística, creando el C3, lo probamos y vemos que funciona,
    pero nos avisan que existe otro error urgente, por eso creamos la rama hostfix y lo arreglamos haciendo
    un commit C4 y publicamos el parche, como veréis no lleva los cambios de la rama iss53 ni su commit
    C3, volvemos a nuestra tarea original y hacemos un C5 dentro de iss53, terminamos la depuración y
    ahora toca hacer la integración con C4 y C5, generando C6 y donde eliminaremos el hotfix para dejar la
    rama master y iss53.
    Git en Remoto III
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  63. • Si no comprendemos la metodología Git (caso 1), puede que estemos usando el sistema de la forma
    tradicional y lo que tenemos es simplemente lo siguiente:
    • Explicación: sobre el ejemplo anterior, el problema al que nos enfrentamos que o bien perdemos las
    cosas de la nueva característica iss53 o bien nos las ingeniamos para comentar todo el código, arreglar
    el error, publicar el programa y rezar para que no nos vuelvan a interrumpir y volver a ingeniárnoslas
    para no perder nada o bien, paramos a todos los usuarios y hasta que no esté todo, no lanzamos una
    releases (seguro que alguno ya tiene un ejemplo en la cabeza).
    Git en Remoto IV
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    C0 C1 C4
    C2 C3 C5

    View Slide

  64. • Si no comprendemos la metodología Git (caso 2), puede que estemos extendiendo el sistema de la
    forma tradicional y lo que tenemos es simplemente lo siguiente:
    • Explicación: este caso es algo mejor que el anterior, pero deberíamos borrar las ramas que hemos
    puesto y ya no usamos, para no confundirnos con una característica que nunca llegó a desarrollarse. El
    problema al que nos enfrentamos que para no perder las cosa de la característica iss53 nos creamos
    una rama cuando nos han avisado del error y desarrollamos aquí en iss53 y hacemos el C3. En la master
    se arregla el error hostfix y posteriormente alguien en vez de integrar mediante git, integra a mano el
    C3 pero donde no queda constancia alguna.
    Git en Remoto V
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015
    C0 C1 C4
    C2
    C3
    C5

    View Slide

  65. • Tradicionalmente los sistemas VCS se basan en un modelo de inserción mediante el cual las
    características se trabajan por varios desarrolladores y eventualmente se empujan (push) hacia
    arriba a un servidor central. Si bien, este modelo es el que ha funcionado durante años, tiene
    una limitación importante: si la rama master se corrompe (no quiere decir que se estropee el
    fichero, puede ser un error de programación) los contribuyentes no podrán fusionar los cambios
    y se deberá hacer de forma manual.
    • Git sigue el modelo de carga (pull) distribuida tratando el proyecto como una entidad
    compartida:
    • Permite copias distribuidas de la rama principal (fork), por lo tanto permite que cualquier
    persona y en cualquier momento pueda actualizar una copia local, reduciendo la complejidad
    relacionada con la fusión del trabajo entre contribuyentes. Tratará cada commit individual del
    repositorio local contribuyente como instantáneas en la línea del tiempo del proyecto integrado.
    • Permite las confirmaciones individuales (Detached HEAD).
    • Añade flexibilidad en la gestión de múltiples cambios para convertirlo en un solo cambio.
    • Las fusiones son más precisas y manejables, la complejidad del trabajo se reduce drásticamente.
    • Por ejemplo, un líder de proyecto podría cargar una característica que ha implementado en 10 o
    mas commits y difundida en varias ramas, compactándolo en un solo mensaje o dos o tres (lo
    que considere oportuno), organizando el historial personal antes de realizar el commit en la
    rama principal. Asi finalmente impulsar y dar a conocer la nueva característica.
    Modelo Pull vs. Modelo Push I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  66. • Si la anterior explicación formal entre uno y otro sistema, no te convence, os
    planteo la siguiente necesidad que no tiene Visual Sourcesafe y siempre he
    querido tener: un historial y protecciones para hacer comparaciones locales
    antes de publicar algo en el servidor .
    • En el supuesto caso que yo he desprotegido un fichero y he realizado cambios,
    al día siguiente el cliente me cambia las especificaciones o bien publico el
    cambio y desprotejo para que quede constancia de lo que realicé y rezo para
    que no salga un ejecutable con eso que esta mal al resto de desarrolladores o
    marco en el servidor como copia de trabajo la anterior a la que yo toqué o bien
    deshacernos cambios y perdemos ese código o bien un zip con el proyecto…
    Bien es conocido el caso que tras enviar la supuesta mejora, esa no era la buena
    y era la que habíamos realizado previamente. Con el sistema tradicional lo
    habitual era haberla perdido.
    • Y por fin se acabo el trabajar cada uno en un formulario/actividad
    independiente, ya podremos trabajar 2 o más desarrolladores sobre uno, eso sí,
    nuestro jefe tendrá que hacer la integración del mismo.
    Modelo Pull vs. Modelo Push II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  67. • En este curso hemos aprendido lo básico para empezar a usar Git en Android
    Studio.
    • Hemos visto como Git realiza el seguimiento de los cambios.
    • Hemos demostrado como añadir código fuente a Git y aprendido a usar el Log
    para ver un resumen del historial de commits.
    • Hemos visto en profundidad ejemplos:
    • De como las ramas trabajan como etiquetas para apuntar a los commits.
    • Para mover ramas entre commits usando refrencias relativas o incluso eliminadas
    completamente.
    • Hemos demostrado como el historial de Git puede modificar cambios que han
    sido añadidos en paralelo en la línea del tiempo de nuestro proyecto.
    • Hemos demostrado algunos aspectos del trabajo colaborativo involucrando a
    varias ramas simultáneamente.
    • Y si ahora quieres avanzar hasta el siguiente nivel, recomiendo la lectura del
    siguiente libro (es gratuito):
    ProGit por Scott Chacon and Ben Straub
    Resumen
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  68. Demo
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  69. • Si estamos desarrollando software de código abierto, Bitbucket o similares son
    las opciones más interesantes. Pero si vamos a desarrollar código privado, como
    es nuestro caso y queremos usar una herramienta que nos proporciona el
    control, flexibilidad y facilidad de uso parecido a lo que nos ofrece Bitbucket y
    que nuestros repositorios Git estén en servidores fuera de nuestro control,
    debemos usar GitLab.
    • GitLab, proporciona una simple pero potente interfaz web de forma similar a
    como funciona GitHub, con la diferencia que podemos alojarlo en nuestro
    propio servidor cloud, controlar el acceso como queramos y donde el tamaño
    estaría limitado al espacio de almacenamiento que tenga nuestro servidor.
    Anexo I: GitLab I
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  70. • En este curso sería inviable explicar la configuración y puesta en marcha de
    GitLab. Por eso, recomiendo la lectura del siguiente libro. Este libro nos explica
    todo el proceso de forma sencilla y visual.
    Anexo I: GitLab II
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  71. Demo
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  72. Preguntas
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  73. • Git
    • Atlassian SourceTree
    • GitLab
    • Aprende Git de forma visual
    • Guia TryGit de GitHub
    • Comunidad de Git en Google+
    Sitios y Recursos Recomendados
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  74. • Documentación oficial de Git.
    • ProGit, Apress.
    • Git Recipes, Apress.
    • Mastering Git, Packt Publishing.
    • GitLab Cookbook, Packt Publishing.
    Bibliografía
    INTRODUCCIÓN A GIT PARA ANDROID STUDIO – Autoformación 2015

    View Slide

  75. Jose María Flores Zazo
    https://jmfloreszazo.com
    GRACIAS

    View Slide