Herramienta para el control de versiones de ficheros. Convierte nuestro ordenador en una máquina del tiempo.
El repositorio local esta compuesto por tres “árboles” administrados por git:
Por lo tanto, el flujo de trabajo en Git consiste:
Acciones:
git help <comando-git>
git config --global user.name "Nombre usuario"
git config --global user.email "email@contacto.es"
Para comprobarlo:
git config user.name -> Nombre usuario git config user.email -> email@contacto.es
O podemos verlo todo junto con:
git config --global --list
La opción list se puede abreviar como l
Por defecto, Git usa el editor que se haya definido en alguna de las variables de entorno VISUAL o EDITOR o el editor vi para crear mensajes de commit o etiqueta (tag). Para modificar este comportamiento:
git config --global core.editor vim
git config --global alias.lg "log --oneline --decorate --all --graph"
Acabamos de crear el alias lg de tal que manera que al escribir git lg se ejecutará git log --oneline --decorate --all --graph
Podemos ver los alias que tenemos definidos en la configuración:
git config --global -l
Dentro del directorio donde queramos crear un repositorio Git, ejecutamos:
git init
Esto creará un directorio oculto llamado .git. En ese directorio se guardarán los commits, las ramas, etc. todo lo relacionado con el repositorio actual.
git status
Mostrará lo que existe en un directorio y si están siendo registradas o no por Git:
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
Si los archivos aparecen en rojo, no están siendo registrados por Git. Si están en verde quiere decir que están en STAGE y listos para incluirlos en un commit.
Si queremos añadir todos los archivos del directorio para que Git los gestione:
git add .
Si queremos mostrar solo los ficheros que se han modificado:
git status -s
Para saber en qué rama estamos trabajando:
git status -b
Para cambiar el nombre:
git mv nombre-antiguo nombre-nuevo
Para eliminar archivos:
git rm nombre-archivo
Al renombrar y borrar mediante Git, estas operaciones quedarán reflejadas en su histórico.
Cuando hacemos cambios a nivel de sistema de ficheros (renombrar ficheros o borrarlos), Git se da cuenta de que hay cambios no registrados.
Actualizamos el repositorio para que esos cambios pasen al STAGE:
git add -u
Y luego ya podríamos realizar el commit.
Si tenemos ficheros que no queremos que Git registre, debemos crear un fichero llamado .gitignore (lleva un punto inicial):
fichero-excluir.txt *.log node_modules
Con ese fichero le diremos a Git que no haga el seguimiento de fichero-excluir.txt, los que terminen en .log y la carpeta node_modules.
Para añadir los ficheros a stage y crear el commit con un mensaje en un único paso:
git commit -am "Mensaje de commit"
git commit -m "Mensaje de commit"
Si no añadimos la opción m, Git abrirá el editor de texto que se haya definido para escribir el mensaje de commit.
Si queremos hacer algún cambio en cierto commit, identificado como 4e809d4, por ejemplo:
git reset --soft 4e809d4
En ese momento tendremos en nuestro directorio los ficheros tal cual estaban en ese punto.
Por defecto, al hacer un reset Git aplica la opción mixed avisando de los ficheros que cambiaron en el futuro, es decir, los ficheros que se modificaron después del commit al que hayamos hecho reset. Esos ficheros tendrán los cambios, pero no estarán añadidos al STAGE. Si queremos hacer un reset y descartar los futuros cambios, utilizaremos la opción hard:
git reset --hard 4e809d4
Aunque hayamos hecho reset sobre ciertos commits, Git internamente guarda todo lo que va sucediendo en el repositorio. Podemos verlo con:
git reflog
Como aparecerán todos los hashs de los commits, podremos recuperarlo con reset:
git reset --hard 4e809d4
Esto nos traerá todos los commits hasta ese indicado
Si queremos ver las diferencias entre el último commit y lo que tengamos en nuestro directorio:
git diff
Si queremos ver las diferencias entre lo que dejamos en STAGE y lo que había en el último commit:
git diff --staged
Listado completo de commits del repositorio
git log
Ejemplo:
commit d6fc8b73db822cb4f8b755e7be31d55741f2512c (HEAD -> master)
Author: Rodríguez, Fulanito <frodriguez@example.com>
Date: Thu Jul 8 11:32:17 2021 +0200
Creado archivo README.md
Mostrar versión corta:
git log --oneline
Mostrar versión corta y decorada:
git log --oneline --decorate --all --graph
Si queremos dejar todo como estaba en el último commit, es decir, recuperar el último commit:
git checkout -- .
Esto es muy útil cuando por error borramos algunos archivos o guardamos modificaciones que no queríamos. Utilizando el comando anterior podremos volver al estado del último commit.
Podemos seleccionar solo un archivo a revertir:
git checkout -- archivo.ext
Si queremos modificar el mensaje del último commit:
git commit --amend -m "Nuevo mensaje de commit"
Si queremos modificar el mensaje y ficheros del último commit:
git reset --soft HEAD^
Hacemos los cambios que nos interesen y finalmente añadimos todo y corregimos:
git commit -am "Commit corregido"
Añadir un fichero o lista de ellos:
git add fichero.ext [<fichero2.ext> <ficheroN.ext>]
Añadir grupo de ficheros por extensión del directorio actual:
git add *.ext
Añadir grupo de ficheros por extensión en todo el directorio (recursivo):
git add "*.ext"
Añadir directorio:
git add css/
Añadir todos menos y descartar alguno. Para ello tenemos que hacerlo en dos fases. Primero añadimos todos a STAGE:
git add .
Y ahora lo excluiríamos:
git reset archivo.txt
Para mostrar el nombre de los ficheros por commit:
git log --name-only
Ejemplo de salida:
Author: Rodríguez, Fulanito <frodriguez@email.com>
Date: Tue Nov 24 13:24:41 2020 +0100
Modificado actualizador de datos
Correcciones en la actualización de la información a través de la API
que provocaba un desbordamiento.
informes/proyecto/application/controllers/update.php
informes/proyecto/application/models/bd_model.php
Línea de tiempo de commits. Podremos hacer cambios en ellas sin afectar a la rama principal (normalmente master). Estas ramas, finalmente, podrán incorporarse a la rama maestra.
Utilizamos las ramas para desarrollar nuevas funcionalidades. Estos cambios pueden unirse después a la rama principal o solo para hacer pruebas sobre la rama principal y acabar descartando la nueva rama.
Por defecto solo existe la rama master.
Cuando queremos unir una rama a otra realizamos un merge. Git lo hará por nosotros. Nos encontraremos con 3 escenarios:
git branch minuevafuncionalidad
Si queremos ver las ramas que hay en el repositorio:
git branch
Si queremos ver las ramas locales y remotas:
git branch -a
Nos movemos a la rama:
git checkout minuevafuncionalidad
Normalmente, cuando creamos una rama también queremos movernos a ella, así que para hacer todo en un paso: git checkout -b nombre-rama
Para subir esa rama al repositorio remoto:
git push -u origin minuevafuncionalidad
git branch -d nombre-rama
Para ver diferencias entre ramas:
git diff rama1 master
Debemos colocarnos en la rama master:
git checkout master
Para unir:
git merge rama1
Ejemplo de salida:
Updating 9391f7e..b605c52 Fast-forward villanos.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 villanos.md
Al revisar el historial, veremos algo así:
* b605c52 (HEAD -> master, villanos) Añadido Octopus * 0805ac7 Añadidos villanos * 9391f7e Actualización * 62c8a10 Agregando el gitignore * ac0d374 Borramos la historia de batman * b4c748c Cambiamos el nombre de la historia de superman * d877f01 Borrando archivo salvar mundo * c9ee153 Renombrando archivo a salvar-mundo * fa3cd3a Creando el archivo destruir el mundo * 4e809d4 Agregamos a Linterna verde y a Robin * 345d7de Editamos el readme.md * 860c6c2 Agregamos las historias de los heroes * bc1a1e5 Agregamos las ciudades * 6b8f60d Agregamos los heroes * da24862 Agregamos las misiones * 88a423d Se agrego el archivo readme
Cuando se fusiona una rama con la master y en la master ha habido cambios que no conoce la rama a unir, si no supone un conflicto, Git nos pedirá un mensaje de commit para que quede registrada la fusión. Git añade “Merge branch 'nombre rama'”, pero podemos poner lo que queramos. Tras guardar el commit, mostrará un mensaje así:
Merge made by the 'recursive' strategy. villanos.md | 1 + 1 file changed, 1 insertion(+)
Cuando al unir dos ramas obtenemos este mensaje:
Auto-merging misiones.md CONFLICT (content): Merge conflict in misiones.md Automatic merge failed; fix conflicts and then commit the result.
Git nos informa de que existen conflictos que no puede solucionar de forma automática y requiere de nuestra intervención.
Para resolver, abrimos el fichero que tiene conflictos:
# Misiones 1. Acabar con el plan de Lex Luthor 2. Crear la liga de la justicia <<<<<<< HEAD 3. Buscar nuevos miembros que sean superhéroes 4. Necesitamos más comida ======= 3. Buscar nuevos miembros para la liga >>>>>>> rama-conflicto
Las nuevas líneas que aparecen en el fichero indican los conflictos. La línea ======= es el “centro” del conflicto. Todo el contenido entre el centro y la línea <<<<<<< HEAD es contenido que existe en la rama maestra actual a la que apunta la referencia HEAD. Por el contrario, todo el contenido entre el centro y >>>>>>> rama-conflicto es contenido que está presente en nuestra rama de fusión.
Las etiquetas hacen referencia a un commit, el estado en que se encontraba un proyecto en un determinado momento.
Normalmente las etiquetas se usan en commits para marcar versiones o releases de los programas.
git tag nombre-tag
De una manera más completa:
git tag -a v1.0.0 -m "Versión inicial"
Esto asociará el tag al último commit. Si queremos especificar el commit:
git tag -a v0.1.0 345d7de -m "Versión alfa"
345d7de sería el identificar del commit.
Para borrarlo:
git tag -d nombre-tag
Para visualizar los que hay:
git tag
Para ver la lista de tags:
git tag
Para mostrar un tag:
git show nombre-tag
git clone direccion-repositorio
Por ejemplo, para descargar un repositorio de GitHub por HTTPS:
git clone https://github.com/laravel/laravel.git
git pull origin master
git push origin master
Se añaden todos los que queramos:
git remote add repo1 https://github.com/usuario1/proyecto.git git remote add repo2 https://github.com/usuario2/proyecto.git git remote add repo3 https://github.com/usuario3/proyecto.git
Cada vez que queramos subir los cambios, decidimos a cuál. Por ejemplo, para subirlo solo al repo2:
git push repo2 master
El flujo de trabajo cuando se trabaja con más gente es crear una rama (branch) y trabajar sobre ella. La rama master no se debe tocar para evitar tocar los mismos archivos.
Partimos de la rama master:
git checkout master
Descargamos la versión más actualizada:
git pull origin master
Creamos una rama:
git branch minuevafuncionalidad
Nos movemos a esa rama:
git checkout minuevafuncionalidad
Haríamos nuestros desarrollos y commits.
Cada vez que queramos subir los cambios de la rama:
git push -u origin minuevafuncionalidad
Finalmente, para unir esa rama con la master, primero debemos cambiarnos a la rama master:
git checkout master
Asegurarnos de tener la última versión de master:
git pull origin master
Fusionamos las ramas:
git merge minuevafuncionalidad
Estos cambios están en local. Debemos subirlos al repositorio remoto:
git push origin master
Una vez fusionada, es una buena práctica eliminar las ramas que ya no vamos a usar más:
git push origin --delete minuevafuncionalidad
Y también (si queremos) la borramos de local:
git branch -d minuevafuncionalidad
git init: creación de repositorio git local.git add: añade ficheros a STAGE.git commit: se registran los cambios de los ficheros que estén en STAGE (se hace una “instantánea”/snapshot).git status: lista los ficheros que sufrieron algún cambio desde el último commit y lista de ficheros que no está siguiendo Git.Si al añadir ficheros a STAGE nos aparecen las siguientes advertencias:
warning: LF will be replaced by CRLF in archivo.txt. The file will have its original line endings in your working directory
Se debe a que está configurado core.autocrlf = true. Lo que hace esa opción es indicar si quieres que en el repositorio se guarden los saltos de línea de los ficheros en formato Unix (LF) pese a tener tus ficheros en tu entorno local con saltos de línea al formato Windows (CRLF). Al hacer commmit, tus ficheros se transformarán automáticamente a LF, y cuando hagas checkout de un fichero, se convertirá automáticamente a CRLF
Podemos solucionarlo con:
git config core.autocrlf false