git es un programa que sirve para rastrear los cambios en las versiones de un programa o proyecto ("version control system", o VCS). Se puede usar desde la línea de comandos; permite checar cambios en cualquier punto de la historia, resetear a algún punto específico del historial, tener desarrollos independientes, etc. Es código abierto. Fue inventado por Linus Torvalds en el 2005 para el manejo y desarrollo del kernel de Linux. En pocas palabras, es un manejador de repositorios.
GitHub es un sitio-web/red social donde uno puede hacer un desarrollo colaborativo de algún proyecto, de forma abierta o cerrada, y permite hacer respaldos en la nube. Actualmente, es donde se realizan la mayor parte de los proyectos abiertos.
Los comandos debajo están diseñados para usarse en sistemas tipo Unix, es decir en Linux y Mac. Para usarlos en Windows, es necesario instalar Git Bash y llevar a cabo los comandos directamente desde Git Bash (no desde el Notebook). También en Linux y Mac los comandos se pueden teclear directamente desde la terminal. Para hacerlo, simplemente no se escriben los ;
al principio de los comandos.
git
es un manejador de repositorios con mucha flexibilidad. Un repositorio es un directorio donde se almacena el desarrollo de un proyecto.
git
, en lugar de hacer copias de cada archivo y cada uno de los cambios del proyecto, lo que hace es guardar los cambios en ciertos puntos de la historia, que el usuario define.
Antes de iniciar, el repositorio, veamos la estructura actual del directorio (que vale la pena, por ahora, que sea "git-test"). Para esto, desde la terminal, ejecutamos:
ls -alp
Esto, se puede hacer desde julia
o IJulia
usando ;
, que manda un comando a la terminal / línea de comandos:
; ls -alp
In [2]:
; ls -alp
El directorio ".ipynb_checkpoints/" incluye información de los distintos puntos donde he salvado este "ipython notebook", que de hecho es un "ijulia notebook". El otro archivo, es la versión actual de este notebook.
Para empezar un repositorio git, hay que ejecutar la instrucción
; git init
Ejercicio 1: Crea un directorio nuevo que se llama git-test
[recuerda que el comando de Linux para crear un directorio es mkdir
, y para cambiar al directorio es cd
] e inicializa tu repositorio git ahí; hazlo sin miedo. NOTA: La celda vacía que hay abajo es para que hagas el ejercicio. Asegúrate de que el archivo 01-git.ipynb
se encuentre en este directorio (moverlo ahí si es necesario y vuelve a abrir el Notebook desde ahí).
In [ ]:
Una vez que lo hayan hecho, el contenido de su directorio debería verse como sigue:
In [4]:
;ls -alp
Entonces, el comando git init
crea el directorio escondido .git/
que contendrá toda la información del repositorio, en este caso, el contenido de este curso. (Nota que hay un punto, ".", antes de "git". Eso corresponde a un archivo o directorio escondido.)
Ejercicio 2: (Desde el IJulia notebook) ¿Qué hay dentro del directorio .git
? (Hint: recuerden lo que hace ;
antes de una instrucción de linux.)
In [ ]:
Antes de seguir adelante, conviene que ejecuten los siguientes comandos, con los cambios apropiados a ustedes:
git config --global user.name "Luis Benet"
git config --global user.email "benet@fis.unam.mx"
git config --global color.ui "auto"
Estos comandos tienen como objetivo configurar la cuenta desde donde están trabajando. Los dos primeros sirven para que los cambios que hagan queden debidamente firmados, por así decirlo; el último sirve para ver la vida de colores, desde la terminal :-)
Para ver la situación o status del repo, ejecutamos la instrucción
git status
In [5]:
; git status
A fin de interpretar el contenido de la salida de
git status
empezaremos por definir ciertos términos:
Entonces, el resultado de git status
indica:
(use "git add" to track)
Vayamos paso a paso. Nos interesa seguir los cambios de "01-git.ipynb"; después veremos cómo se puede ignorar los cambios en ".ipynb-checkpoints/". Entonces, siguiendo lo que nos dice, ejecutaremos:
git add 01-git,ipynb
Pero, antes, vale la pena salvar la situación actual de este archivo.
NOTA Yo haré esto desde IJulia, pero puede ser más conveniente hacerlo desde la propia terminal; así, uno evita hacer cosas que cambian este archivo. Si lo hacen desde la terminal, recuerden no poner el ;
.
In [6]:
; git add 01-git.ipynb
Mmmmmm...
¿Pasó algo? Veamos qué dice git status
; nuevamente, es mejor hacerlo desde la terminal.
In [10]:
; git status
A pesar de que aún no hemos guardado este punto en la historia del proyecto (Changes to be committed:
), vemos que git ahora nos avisa de los cambios que serán hechos: se incluirá el nuevo archivo 01-git.ipynb
. Y también, cómo dar marcha atrás a los cambios: (use "git rm --cached <file>..." to unstage)
; pero esto lo dejaremos para más tarde.
Para guardar este punto de la historia del proyecto ejecutaremos:
git commit -m "Add 01-git.ipynb"
Aquí, la bandera -m
avisa que escribiremos una línea de mensaje, escrito entre comillas. Ese mensaje habla de los cambios que se hicieron (de manera resumida) y sirven como recordatorio.
NOTA: De igual manera uno puede escribir la línea de resumen y más detalles de los cambios que se guardan, cosa que obviamente es beneficiosa. Para esto último, uno ejecutaría git commit
(sin ninguna bandera ni nada más); esto abrirá un editor, por default "vi", donde escribiremos una línea de resumen, y dejando un espacio en blanco, lo que queramos más detallado. Esto conviene hacerlo desde la terminal.
Ver aquí para una guía de "buenas prácticas" sobre cómo escribir los mensajes en los commits; vale la pena leerlo!
In [11]:
; git commit -m "Add 01-git.ipynb"
El mensaje indica que hemos hecho el primer commit, etiquetado "3225b9d", y que éste incluye 315 inserciones. Esta etiqueta (que podría ser otra para ustedes), que de hecho es una etiqueta abreviada, se llama "hash".
Ejercicio 3: ¿Qué indica git status
ahora?
In [ ]:
Para saber más detalles de la historia del repositorio, o sea, echarle un ojo a la bitácora (log), uno utiliza la instrucción
git log
In [13]:
; git log
Aquí ven por qué arriba dije que la etiqueta es abreviada; también ven que yo hice los cambios, cuando, y mi email.
Desde que hice el commit inicial, de hecho, muuuuucho he escrito. Para darme cuenta de ello, un simple git status
basta y sobra. Ahí veré que el archivo 01-git.ipynb
ha sido modificado, y que
.ipynb_checkpoints/
aparece como untracked. Ahora, veremos cómo hacer para que ciertos archivos simplemente no se consideren en la lista; en particular, que .ipynb_checkpoints/
no aparezca nuevamente.
Empecemos por crear el archivo .gitignore
vacío; noten que es un archivo escondido:
touch .gitignore
Ahora, yo escribiré desde la línea de comandos .ipynb_checkpoints
en ese archivo. Esto se logra con:
echo ".ipynb_checkpoints" > .gitignore
Ejercicio 4: Creen un archivo que se llame .gitignore
con el contenido arriba mencionado.
In [ ]:
Si todo va bien hasta aquí, entonces podemos ver el contenido del archivo .gitignore
con el comando cat
:
In [15]:
; cat .gitignore
In [16]:
; git status
Por un lado, he modificado el archivo "01-git.ipynb"; además, hay un nuevo archivo que no está siendo seguido por git: .gitignore
. El punto que resaltar es que el dichoso directorio .ipynb_checkpoints
ya no aparece en la lista de los archivos que no se están siguiendo. Esto es justamente lo que hace el archivo .gitignore
.
Ejercicio 5: Agreguen ese archivo a la lista de los archivos que serán seguidos en el respositorio. ¿Qué resulta dar git status
después de agregar ese archivo? Después, hagan el commit relacionado a ese cambio. Para el mensaje del commit, ¡ejerciten su inglés!
In [ ]:
Ejercicio 6: ¿Qué hay nuevo en la salida de git log
?
In [ ]:
Ahora haré un cambio trivial y no importante en ".gitignore":
In [17]:
; echo ".DS_Store" >> .gitignore
In [18]:
; git status
Claramente, git
nota que ha habido cambios en ambos archivos: en "01-git.ipynb" son los cambios asociados con lo que voy escribiendo ---y que por lo mismo, evitaremos ir comentando---, y el cambio en ".gitignore" que acabo de hacer. Para saber qué cambios he hecho en ".gitignore" usamos
el comando git diff .gitignore
:
In [19]:
; git diff .gitignore
La información muestra que se agregó una línea: +.DS_Store
y su contenido. Cambios más complejos se señalarán de igual manera, pero no les recomiendo hacer esto con "01-git.ipynb". Incidentalmente, en la terminal las diferencias se ven con colores.
Ahora, si por alguna razón queremos revertir los cambios, que por cierto justo ahora no hemos guardado, entonces, siguiendo las instrucciones que están en git status
, ejecutamos:
git checkout -- .gitignore
In [20]:
; git checkout -- .gitignore
In [21]:
; cat .gitignore
Como se puede apreciar, hemos borrado los cambios en ese archivo y hemos vuelto al estado del último commit.
Esto nos lleva a un comentario importante: si bien uno puede borrar un archivo con rm archivo
desde la terminal, esto no implica que git
deje de ser checando los cambios a ese archivo. Si uno quiere borrar un archivo y que también desaparezca de ser seguido por git
, uno debe además ejecutar:
git rm archivo
Resumiendo, el ciclo típico de desarrollo, desde el punto de vista de git
es:
> git status # ver cuál es la situación
[Modificar archivos]
> git status # revisar cambios
> git add *archivo* # prepara los archivos que se cambiaron
> git commit -m "Mensaje"
Una característica de git
es que permite subir los cambios en el repositorio a algún servidor central o un directorio de uso compratido. En particular, permite subir los cambios a GitHub, donde se puede tener un respaldo del repositorio de manera gratuita, siempre y cuando sea de código abierto.
Lo primero necesario, obviamente, es abrir una cuenta en GitHub, y entonces crear un nuevo repositorio; las instrucciones se encuentran aquí. Una vez que se ha creado el repositorio, GitHub explica los comandos que hay que usar para subir los cambios (push) a GitHub. Éstos son:
> git remote add origin https://github.com/NombreUsuario/Proyecto.git
> git push -u origin master
Aquí, "NombreUsuario" es el nombre de identificación ante GitHub (el suyo o el del desarrollador principal del repositorio), y "Proyecto" es el nombre del repositorio. Entonces, la primer instrucción define (configura) el lugar remoto donde se subirán los cambios, en este caso a GitHub; la segunda instrucción sube los cambios del branch master
del repositorio local al repositorio remoto.
Por ahora dejaremos esto, pero eventualmente será algo importante, sobretodo en la parte colaborativa.
git