# Introducción a Git, Github y Markdown Esta documentación está inspirada en: [Git Book v1](https://git-scm.com/book/es/v1) [The Git, the Bad and the Ugly](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/es/) [Learn Git with Bitbucket Cloud](https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud) Se exponen conceptos básicos de sistemas de control de versiones, Git y Github. [TOC] ## ¿Qué es Git? Git es un sistema de control de versiones de código abierto creado por Linus Torvalds *(desarrollador del kernel de Linux)* en 2005. Un **sistema de control de versiones** registra los cambios realizados sobre un archivo o conjunto de archivos **(TODO TIPO DE ARCHIVOS, archivos con código de software, imagenes, etc)** a lo largo del tiempo, de modo que se pueden recuperar versiones específicas más adelante. ### Noblezas de un sistema de control de versiones Un sistema de control de versiones permite: * Revertir archivos a un estado anterior. * Revertir el proyecto entero a un estado anterior. * Comparar cambios a lo largo del tiempo. * Ver quién modificó por última vez algo que puede estar causando un problema, quién introdujo un error y cuándo, y mucho más. ... esto significa que si rompés o perdés un archivo o un proyecto, ¡podés recuperarlo fácilmente! #### Sistemas de control de versiones locales Se trata de una simple base de datos que registra los cambios de un proyecto (versiones) con alcance local, es decir, un proyecto unipersonal en mi computadora. ![Sistema de Control de versiones local](https://git-scm.com/figures/18333fig0101-tn.png) A la hora de trabajar en un proyecto colaborativo, el alcance local de un sistema de control de versiones no sirve. Si varios programadores desean trabajar conjuntamente en un mismo proyecto, deben optar por alguno de los siguientes sitemas de control de versiones: #### Sistemas de control de versiones centralizados Este sistema de control de versiones *centraliza* el registro de los cambios de un proyecto en un servidor y los clientes descargan una copia del mismo. ![Sistema de control de versiones centralizado](https://git-scm.com/figures/18333fig0102-tn.png) Las ventajas sobre un sistema de control de versiones local están a la vista, varias personas pueden trabajar en un mismo proyecto, el administrador del mismo puede controlar los permisos de cada uno, todos los colaboradores pueden saber en qué están trabajando los otros, etc. La desventaja radica en el hecho de que si la única fuente de archivos no está disponible *(si el servidor se cae)*, el proyecto se cae, existe un tercer modelo de sistema de control de versiones que soluciona este inconveniente: #### Sistema de control de versiones distribuído En este caso no existe un solo servidor que registra los cambios o versiones del proyecto, los clientes no sólo descargan la última versión del proyecto, sino una copia de seguridad con ella, lo que los convierte en servidores de respaldo. ![Sistema de control de archivos distribuído](https://git-scm.com/figures/18333fig0103-tn.png) **Git es un sistema de control de versiones distribuído.** Git *"sigue"* tu proyecto a lo largo del tiempo y cuando vos lo decidís, *"crea una instantánea"* del mismo, crea un punto importante en la historia de tu proyecto al cuál podés volver cuando lo desees: ![Diagrama Git](https://git-scm.com/figures/18333fig0105-tn.png) ### Noblezas de Git * Git trabaja con archivos y recursos locales, es decir que para realizar cualquier operación sobre tu proyecto, no es necesario nada más que tu computadora. * Git es íntegro, realiza verificaciones con una operación denominada *checksum*, esto, entre otras cosas, implica que no hay modificaciones que *"se le escapen"* a Git. ### Los tres estados principales Durante el seguimiento de tu proyecto, ahora vamos a hacer referencia al mismo como *proyecto Git*, Git puede encontrar tus archivos en **tres posibles estados**: #### Modificado *(modified)* Significa que uno o más archivos de tu proyecto fueron modificados, pero todavía no hiciste una confimación para decirle a Git que cree un punto de retorno a dicha versión. #### Preparado *(staged)* Después de que uno o más archivos fueron modificados, tu proyecto está listo para confirmar a Git que el estado actual será una nueva versión del mismo. #### Confirmado *(confirmed)* Tu proyecto fue modificado con respecto a la última versión, lo preparaste y confirmaste para decirle a Git que se trata de una nueva versión de tu proyecto, es decir un punto. Existe un **directorio** asociado a cada uno de los estados antes mencionados: ![Directorios git](https://git-scm.com/figures/18333fig0106-tn.png) * **Directorio de trabajo:** es una copia de una versión del proyecto. Estos archivos se sacan de la base de datos comprimida en el directorio de Git, y se colocan en disco para que los puedas usar o modificar. * **Directorio de preparación:** es un sencillo archivo, generalmente contenido en tu directorio de Git, que almacena información acerca de lo que va a ir en tu próxima confirmación. * **Directorio Git:** es donde Git almacena los metadatos y la base de datos de objetos para tu proyecto. Es la parte más importante de Git, y es lo que se copia cuando clonas un repositorio desde otro ordenador. ## Instalación de Git ### GNU/Linux ``` shell sudo apt-get install git ``` ### Windows Descargar y ejecutar el [Instalador de Git](http://msysgit.github.com/). ## Configuración de Git Para configurar por primera vez tu identidad con Git: ``` shell git config --global user.name "John Doe" git config --global user.email johndoe@example.com ``` ## Uso básico de Git A partir de ahora denominaremos **repositorio** al conjunto de archivos sometido a un control de versiones, a esa *carpeta* donde guardás tu proyecto. ### Crear un repositorio local Seguimos haciendo referencia a ese directorio que aloja los archivos de tu proyecto, crear un repositorio significa *decirle a Git* que comience a registrar y administrar los cambios y versiones del mismo. Si ese directorio todavía no existe: ``` shell mkdir mi_repositorio cd mi_repositorio ``` Una vez en el directorio cuyos cambios queremos que Git *"siga"* : ``` shell git init ``` Initialized empty Git repository in mi_repositorio/.git/ Hemos creado un repositorio, el mismo tiene alcance local, por ahora. Vamos a agregar el primer archivo al repositorio, se trata de un archivo llamado *"README"* que contendrá algunas líneas de texto que describan rápidamente el proyecto. ``` shell touch README.md ``` NOTA: md es la extensión de archivos de texto en Markdown, abordaremos este tema más adelante. Por ahora nuestro proyecto consta de un archivo vacío. Nuestro repositorio ha sido modificado, en este momento nos encontramos en el **directorio de trabajo**, para confirmar esto: ``` shell git status ``` On branch master Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) README.md ... para preparar nuestro proyecto hacia una nueva versión debemos *agregar* los cambios: ``` shell git add README.md ``` ![Git add](https://www.atlassian.com/dam/jcr:dbf0c59f-848d-4814-bfd5-6b190a092963/03.svg) Confirmamos los cambios: ``` shell git status ``` On branch master Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: README.md ... nuestro repositorio está listo para ser confirmado como una nueva versión. Para crear un punto de retorno, un hito en la línea del tiempo del proyecto, esto es **confirmar** los cambios realizados: ``` shell git commit -m "Commit inicial" ``` ![Git commit](https://www.atlassian.com/dam/jcr:d5f60ca0-b606-4e7c-b3a2-430165bc0672/04.svg) La opción *-m* permite especificar un mensaje que indica brevemente los cambios efectuados en el proyecto, es importante tener en cuenta que este mensaje debe ser útil para todo aquel que lo lea. Debe ser claro y conciso, aportar rápidamente información del/los cambios que se realizaron, es una buena práctica respetar el modo imperativo que usan los mensajes de Git, por ejemplo: *"se agregó archivo README"*. ### Ignorar elementos con gitignore En cualquier proyecto, existen archivos/directorios que no deben incluirse en el repositorio. Como ficheros de log, archivos que contienen usuarios y claves de autenticación, caché, archivos que resultan de compilación, etc. Para indicarle a git que queremos excluirlos del seguimiento, así como no subirlos al repositorio remoto asociado, debemos crear y editar un archivo con el nombre *".gitignore"* (el punto al inicio del nombre es importante), en el se especifica lo antes mencionado, ya sea nombre de directorios, de archivos o indicarle ignorar todos los archivos con determinada extensión por ejemplo: "*.bin". ## Introducción a Github Github es una plataforma de desarrollo colaborativo para alojar proyectos utilizando el sistema de control de versiones Git. ### Crear un repositorio remoto Para trabajar conjuntamente con otras personas en un mismo proyecto, una buena opción es crear un repositorio remoto, esto es, en la nube. En este caso vamos a usar Github. #### Crear una cuenta en Github Nos dirigimos a [Github](https://github.com) y creamos una cuenta de usuario: ![](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/github_website.png) #### Crear un repositorio en Github Desde nuestra página principal, simplemente hacemos click en "Create new repository": ![Nuevo repositorio](https://tutorial.djangogirls.org/en/deploy/images/new_github_repo.png) ##### Noblezas de Github Github, como plataforma de trabajo colaborativo, es un sitio web en el que los desarrolladores comparten con todo el mundo sus proyectos, algunas de las ultilidades más importantes para el trabajo en equipo son: ![Elementos de Git](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_general.png) * **Code**: Es la página principal de un repositorio en GitHub, incluye la descripción del proyecto, unas etiquetas para clasificar la temática del proyecto y una vista de seguidores, estrellas, commits, branches, releases, etc del repositorio. Contiene también un explorador de archivos y una vista previa del archivo README. ![Code Github](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_code.png) * **Issues**: gestor de bugs en forma de Issues. Cada Issue representa un problema o mejora del proyecto. Dentro de cada Issue se pueden poner comentarios en los que informar de los progresos o debatir la mejor forma de solucionarla. Un Issue puede ser asignado a personas en particular del proyecto. ![Issues Github](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_issues.png) * **Fork**: sistema de permisos que controla qué usuarios pueden subir código a cada repositorio. Si deseamos hacer alguna modificación al software de una tercera persona, pero no tenemos autorización para publicar en su repositorio, podemos hacer un Fork de dicho repositorio. Un Fork no es más que una copia del repositorio, que pasa a ser propiedad del usuario que hizo el Fork. De esta forma, ese usuario ya podría realizar modificaciones sobre el código del repositorio en su copia, sin necesidad de tener autorización para subir cambios. * **Pull requests**: Si realizamos una copia del repositorio de un tercero, hacemos modificaciones, mejoras, podemos pedir autorización al dueño del repositorio original para integrar nuestros cambios al mismo, es decir un Pull request. * **Projects**: es un espacio de Github para organizar tareas e Issues relacionadas entre sí. Está inspirada en el método Kanban. A cada Project le podremos añadir tarjetas que pueden corresponder o no con Issues del proyecto y moverlas entre las distintas columnas del pizzarrón. ![Projects Github](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_project.png) * **Wiki**: GitHub nos permite también tener documentación asociada a un proyecto en una wiki alojada en GitHub. Esta wiki se puede editar online, y está basada en Gollum.La wiki se almacena en un repositorio independiente que podemos clonar y editar también localmente. ![Wiki Github](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_wiki.png) * **Graph**: La pestaña Graph nos permite ver distintas visualizaciones de datos relacionadas con nuestro repositorio, como cuántas líneas de código/commits ha aportado cada contribuidor o cuál es la franja horaria en la que se suelen hacer más commits. ![Graph Github](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/elements_graphs.png) ### Asociar repositorio local con repositorio remoto Ahora vamos a asociar el repositorio local que creamos y administramos con git, con el repositorio (vacío por ahora), recientemente creado en la nube, en Github, para ello necesitamos la URL del repositorio que creamos en Github, con ella, en la consola escribimos: ``` shell git remote add origin <url de nuestro repo> ``` ![](https://www.atlassian.com/dam/jcr:a226d62e-3f0f-4c7e-8d99-c3c73188f9f6/01.svg) ### Crear un repositorio local a partir de uno remoto Para crear un repositorio local a partir de uno alojado en internet: ``` shell git clone <url del repositorio remoto> ``` esto copia el repositorio de interés en nuestro equipo, con todos los archivos asociados a git. ### Subir y bajar cambios a un repositorio remoto Si queremos subir los cambios realizados localmente al repositorio remoto: ``` shell git push origin <branch> ``` ... donde *branch* es la rama del repositorio. La rama principal se denomina *master*. #### Ramas Una rama en un repositorio de git es una bifurcación del mismo, es útil a la hora de separar nuestro trabajo del trabajo ya existente, es útil en casos en los que estamos ante una versión no estable del proyecto, o estamos solucionando un bug, creamos entonces una bifurcación de la última versión estable, trabajamos en una rama nueva y una vez que lo consideramos adecuado, volvemos a la rama principal y subimos lo cambios realizados. ![Ramas Git](https://www.atlassian.com/dam/jcr:ad5914a2-a5af-4517-a035-fc04b84c7a62/01.svg) ##### Crear una rama Para crear una rama y con ella una bifurcación del repositorio actual: ``` shell git branch <nombre_rama> ``` Para ver las ramas existentes asociadas al repositorio actual: ``` shell git branch ``` ##### Cambiar de rama Si estamos trabajando en una rama y queremos movernos a otra: ``` shell git checkout <nombre_rama> ``` ##### Subir nueva rama a repositorio remoto Para subir una rama recientemente creada al repositorio remoto asociado: ``` shell git push origin <rama> ``` si nos dirigimos al repositorio remoto en Github, podremos ver las ramas existentes, en el siguiente ejemplo se muestra una bifurcación del repositorio original, una rama a la que se denominó *"test"*: ![](https://david-estevez.gitbooks.io/the-git-the-bad-and-the-ugly/content/assets/05_github_branches.png) ##### Fusionar ramas Si deseamos integrar los cambios realizados en una rama, hacia la principal, debemos movernos a la principal y usar el comando *"merge"* como sigue: ``` shell git checkout <rama_base> git merge <rama_a_fusionar> ``` ##### Borrar ramas Para eliminar una rama: ``` shell git branch -d <rama_a_borrar> ``` ### Moverse a un commit específico Una de las funcionalidades más importantes de git es revertir cambios, volver a puntos estables de nuestro proyecto, corregir errores, *"volver en el tiempo"* de nuestro repositorio cuando algo anda mal. Para moverse a un commit en particular, es decir a un hito específico en la historia de nuestro repositorio, debemos conocer el hash del mismo, es decir un identificador alfanumérico que podemos encontrar en el archivo log de git: ``` shell git log git checkout <hash_del_commit> ``` ### Deshacer cosas #### Modificar un commit Si enviamos el estado de nuestro repositorio recientemente al área de confirmación, es decir, si hicimos un commit y deseamos modificarlo por ejemplo porque nos olvidamos de agregar un archivo, se emplea el comando ```commit --amend```: ``` shell git add <archivo_que_faltaba> git commit --amend ``` #### Sacar un archivo del área de preparación: Si recientemente agregamos un archivo al área de preparación (con ```git add```), pero no estaba listo: ``` shell git reset HEAD <archivo> ``` #### Deshacer cambios de un archivo Esta operación se realiza dentro del directorio de trabajo, por lo que, al descartar los cambios de un archivo, los perdés. ``` shell git checkout -- <archivo> ``` Vamos a convertir el directorio de nuestro proyecto Django en un repositorio y subirlo a la red: ``` shell cd municipalidad git init ``` Initialized empty Git repository in ~/municipalidad/.git/ Configuremos nuestra identidad en git: ``` shell git config user.name "Tu nombre" git config user.email tú@ejemplo.com ``` ... estamos en el directorio de trabajo, debemos preparar los archivos para confirmar la primera versión de nuestro proyecto Django. Tenemos que indicarle a git qué elementos de nuestro repositorio no queremos que siga, creamos un archivo llamado *".gitignore"* con el siguiente contenido: ``` shell *.pyc __pycache__ myvenv db.sqlite3 .DS_Store ``` Ahora git está *"siguiendo"* nuestro repositorio e ignorando lo que le indicamos en el archivo .gitignore. Para ver el estado del mismo: ``` shell git status ``` Vamos a pasar a la fase de *"preparación"* de nuestro repositorio, previa a confirmar la primer versión de nuestro proyecto: ``` shell git add * ``` ... habiendo trasladado los archivos relacionados con el seguimiento de versiones desde le directorio de trabajo (luego de *git init*) hacia el directorio de preparación, vamos a confirmar la primera versión de nuestro trabajo: ``` shell git commit -m "Mi app Django, primer commit" ``` Hemos creado el primer hito en la línea del tiempo de nuestro proyecto, en el futuro podremos retornar al mismo. Lo siguiente es vincular nuestro trabajo local con un repositorio remoto, ``` shell git remote add origin https://github.com/<your-github-username>/my-first-blog.git ``` ... para compartir nuestro proyecto con el mundo, debemos subir nuestro trabajo al repositorio recientemente vinculado en la nube: ``` shell git push -u origin master ``` ## Introducción a Markdown Mark Down es un lenguaje de marcado ligero creado por John Gruber que trata de conseguir la máxima legibilidad y facilidad de publicación tanto en su forma de entrada como de salida, inspirándose en muchas convenciones existentes para marcar mensajes de correo electrónico usando texto plano. Esta herramienta cobra importancia a la hora de documentar nuestros proyectos, ya sea el archivo principal que describe nuestro trabajo ante el mundo, documentación técnica de software, tareas asignadas a las personas involucradas en el proyecto, una wiki, etc. Un archivo con extensión .md es fácilmente convertible en HTML, pdf, entre otros. Elementos principales de un documento: ### Tabla de contenido ``` markdown [TOC] ``` [TOC] ### Formato de texto ``` markdown *cursiva*, **negrita**, * **negrita-cursiva** * +subrayado+, ~~tachado~~, ^superíndice^, ~subíndice~ ``` *cursiva*, **negrita**, ***negrita-cursiva*** ++subrayado++, ~~tachado~~, ^superíndice^, ~subíndice~ ### Estructuras básicas #### Encabezados ``` markdown # Encabezado1 ## Encabezado2 ### Encabezado3 #### Encabezado4 ##### Encabezado5 ###### Encabezado6 ``` # Encabezado1 ## Encabezado2 ### Encabezado3 #### Encabezado4 ##### Encabezado5 ###### Encabezado6 #### Listas ##### Lista desordenada ``` markdown - Ítem 1 * Ítem 2 + Ítem 3 ``` - Ítem 1 * Ítem 2 + Ítem 3 ##### Lista ordenada ``` markdown 1. Ítem primero 2. Ítem segundo 3. Ítem tercero ``` 1. Ítem primero 2. Ítem segundo 3. Ítem tercero ##### Lista de tareas *(TODO List)* ``` markdown [] Tarea por hacer [x] Tarea realizada [] Tarea por hacer [] Tarea por hacer [x] Tarea realizada ``` [] Tarea por hacer [x] Tarea realizada [] Tarea por hacer [] Tarea por hacer [x] Tarea realizada #### Citas ``` markdown > "Sólo somos una raza de monos avanzados en un planeta más pequeño que una estrella promedio. Pero podemos entender el universo. Eso nos hace muy especiales." - *Stephen Hawking* ``` > "Sólo somos una raza de monos avanzados en un planeta más pequeño que una estrella promedio. Pero podemos entender el universo. Eso nos hace muy especiales." - *Stephen Hawking* #### Tablas ``` markdown |Columna1|Columna1|Columna3| |--------|--------|--------| |celda1,1|celda1,2|celda1,3| |celda2,1|celda2,2|celda2,3| ``` |Columna1|Columna1|Columna3| |--------|--------|--------| |celda1,1|celda1,2|celda1,3| |celda2,1|celda2,2|celda2,3| #### Delimitación de secciones ``` markdown --- fin de sección ___ fin de sentencia *** salto de página ``` #### Insertar objetos ##### Insertar imágenes ``` markdown ![Puente colgante Río Cuarto](https://images.duckduckgo.com/iur/?f=1&image_host=http%3A%2F%2F1.bp.blogspot.com%2F-iIoSBklElAc%2FTdLYF6d0EHI%2FAAAAAAAAAOA%2FL3TdUkUhUZg%2Fs1600%2FPuente-colgante-rio-cuarto2.JPG&u=http://1.bp.blogspot.com/-5m1CxVtLPNo/Th4TGCDBywI/AAAAAAAAAAA/eUFpUIHtrdQ/s1600/Puente-colgante-rio-cuarto2.JPG) ``` ![Puente colgante Río Cuarto](https://images.duckduckgo.com/iur/?f=1&image_host=http%3A%2F%2F1.bp.blogspot.com%2F-iIoSBklElAc%2FTdLYF6d0EHI%2FAAAAAAAAAOA%2FL3TdUkUhUZg%2Fs1600%2FPuente-colgante-rio-cuarto2.JPG&u=http://1.bp.blogspot.com/-5m1CxVtLPNo/Th4TGCDBywI/AAAAAAAAAAA/eUFpUIHtrdQ/s1600/Puente-colgante-rio-cuarto2.JPG) ##### Insertar hipervínculos ``` markdown [Sitio web Gobierno de Río Cuarto](http://www.riocuarto.gov.ar/) ``` [Sitio web Gobierno de Río Cuarto](http://www.riocuarto.gov.ar/) ##### Insertar Código ``` python saludo = 'hola' print('saludo') ``` ``` python saludo = 'hola' print(saludo) ``` ##### Insertar expresiones matemáticas ``` markdown $E = mc^2$ $ \alpha, \beta $ ``` $E = mc^2$ $\alpha, \beta$ ## Crear README del proyecto Django Creamos un archivo con el nombre README.md con el siguiente contenido: ``` markdown # Desarrollo web y gestión de proyectos con Django, Python y Git <Breve descripción> ## Requerimientos <Librerías y herramientas requeridas> ## Instalación ## Guía de uso rápido ## Cómo contribuir ``` Vamos a guardar y subir los cambios del repositorio: ``` shell git status git add README.md git commit -m "Se agregó README" git push ``` ## PythonAnywhere PythonAnywhere es una plataforma web que permite crear, modificar, ejecutar proyectos en python, bash, permite hostear sitios web dinámicos. A partir de este momento podemos trabajar remotamente en nuestro proyecto, vamos a hacerlo desde [PythonAnywhere](https://www.pythonanywhere.com/) Creamos una cuenta y abrimos una terminal en Bash, una vez ahí: ``` shell git clone <URL_repositorio_Github> ``` Ahora nuestro trabajo puede ser modificado en la nube.