Uso básico de Git
Crear un proyecto
Crear un programa "Hola Mundo"
Creamos un directorio donde colocar el código
$ mkdir cursDeGit
$ cd cursDeGit
Creamos un fichero hola.php
que muestre Hola Mundo.
<?php
echo "Hola Mundo\n";
Crear el repositorio
Para crear un nuevo repositorio se usa la orden git init
$ git init
Initialized empty Git repository in /var/www/html/cursDeGit/.git/
Añadir la aplicación
Vamos a almacenar el archivo que hemos creado en el repositorio para poder trabajar, después explicaremos para qué sirve cada orden.
$ git add hola.php
$ git commit -m "Creación del proyecto"
[master (root-commit) 18a30f9] Creación del proyecto
1 file changed, 2 insertions(+)
create mode 100755 hola.php
Comprobar el estado del repositorio
Con la orden git status
podemos ver en qué estado se encuentran los archivos de nuestro repositorio.
$ git status
On branch master
nothing to commit, working tree clean
Si modificamos el archivo hola.php
:
<?php
@print "Hola {$argv[1]}\n";
Y volvemos a comprobar el estado del repositorio:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hola.php
no changes added to commit (use "git add" and/or "git commit -a")
Añadir cambios
Con la orden git add
indicamos a git que prepare los cambios para que sean almacenados.
$ git add hola.php
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hola.php
Confirmar los cambios
Con la orden git commit
confirmamos los cambios definitivamente, lo que hace que se guarden permanentemente en nuestro repositorio.
$ git commit -m "Parametrización del programa"
[master d13ad44] Parametrización del programa
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working tree clean
Diferencias entre workdir y staging.
Modificamos nuestra aplicación para que soporte un parámetro por defecto y añadimos los cambios.
<?php
$nombre = isset($argv[1]) ? $argv[1] : "Mundo";
@print "Hola, {$nombre}\n";
Este vez añadimos los cambios a la fase de staging pero sin confirmarlos (commit).
git add hola.php
Volvemos a modificar el programa para indicar con un comentario lo que hemos hecho.
<?php
// El nombre por defecto es Mundo
$nombre = isset($argv[1]) ? $argv[1] : "Mundo";
@print "Hola, {$nombre}\n";
Y vemos el estado en el que está el repositorio
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hola.php
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hola.php
Podemos ver como aparecen el archivo hola.php dos veces. El primero está preparado para ser confirmado y está almacenado en la zona de staging. El segundo indica que el directorio hola.php está modificado otra vez en la zona de trabajo (workdir).
Warning
Si volvieramos a hacer un git add hola.php
sobreescribiríamos los cambios previos
que había en la zona de staging.
Almacenamos los cambios por separado:
$ git commit -m "Se añade un parámetro por defecto"
[master 88d1eff] Se añade un parámetro por defecto
1 file changed, 2 insertions(+), 1 deletion(-)
$ git status
[master 88d1eff] Se añade un parámetro por defecto
1 file changed, 2 insertions(+), 1 deletion(-)
usuarigit@b563acaa6db5:/var/www/html/cursDeGit$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hola.php
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hola.php
$ git commit -m "Se añade un comentario al cambio del valor por defecto"
[master 4ccf057] Se añade un comentario al cambio del valor por defecto
1 file changed, 1 insertion(+)
Info
El valor "." despues de git add
indica que se añadan todos los archivos de forma recursiva.
Warning
Cuidado cuando uses git add .
asegúrate de que no estás añadiendo archivos que no quieres añadir.
Ignorando archivos
La orden git add .
o git add nombre_directorio
es muy cómoda, ya que nos permite añadir todos los archivos del proyecto o todos los contenidos en un directorio y sus subdirectorios. Es mucho más rápido que tener que ir añadiéndolos uno por uno. El problema es que, si no se tiene cuidado, se puede terminar por añadir archivos innecesarios o con información sensible.
Por lo general se debe evitar añadir archivos que se hayan generado como producto de la compilación del proyecto, los que generen los entornos de desarrollo (archivos de configuración y temporales) y aquellos que contentan información sensible, como contraseñas o tokens de autenticación. Por ejemplo, en un proyecto de C/C++
, los archivos objeto no deben incluirse, solo los que contengan código fuente y los make que los generen.
Para indicarle a git que debe ignorar un archivo, se puede crear un fichero llamado .gitignore, bien en la raíz del proyecto o en los subdirectorios que queramos. Dicho fichero puede contener patrones, uno en cada línea, que especiquen qué archivos deben ignorarse. El formato es el siguiente:
# .gitignore
dir1/ # ignora todo lo que contenga el directorio dir1
!dir1/info.txt # El operador ! excluye del ignore a dir1/info.txt (sí se guardaría)
dir2/*.txt # ignora todos los archivos txt que hay en el directorio dir2
dir3/**/*.txt # ignora todos los archivos txt que hay en el dir3 y sus subdirectorios
*.o # ignora todos los archivos con extensión .o en todos los directorios
Cada tipo de proyecto genera sus ficheros temporales, así que para cada proyecto hay un .gitignore
apropiado. Existen repositorios que ya tienen creadas plantillas. Podéis encontrar uno en https://github.com/github/gitignore
Ignorando archivos globalmente
Si bien, los archivos que hemos metido en .gitignore
, deben ser aquellos ficheros temporales o de configuración que se pueden crear durante las fases de compilación o ejecución del programa, en ocasiones habrá otros ficheros que tampoco debemos introducir en el repositorio y que son recurrentes en todos los proyectos. En dicho caso, es más útil tener un gitignore que sea global a todos nuestros proyectos. Esta configuración sería complementaria a la que ya tenemos. Ejemplos de lo que se puede ignorar de forma global son los ficheros temporales del sistema operativo (*~
, .nfs*
) y los que generan los entornos de desarrollo.
Para indicar a git que queremos tener un fichero de gitignore global, tenemos que configurarlo con la siguiente orden:
git config --global core.excludesfile $HOME/.gitignore_global
Ahora podemos crear un archivo llamado .gitignore_global
en la raíz de nuestra cuenta con este contenido:
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*~
*.swp
# IDEs #
######################
.idea
.settings/
.classpath
.project
Trabajando con el historial
Observando los cambios
Con la orden git log
podemos ver todos los cambios que hemos hecho:
$ git log
commit 4ccf057234ca676a17ea747b95b57b63fe8f9e5d (HEAD -> master)
Author: Narcis Buisac <nbuisac@institutmontilivi.cat>
Date: Sat Jan 8 15:59:59 2022 +0000
Se añade un comentario al cambio del valor por defecto
commit 88d1effe7d63c21f87d53c13e6a6bb898c311719
Author: Narcis Buisac <nbuisac@institutmontilivi.cat>
Date: Sat Jan 8 15:57:38 2022 +0000
Se añade un parámetro por defecto
commit d13ad445802beff89eea7e88ef14b15f96cfd7a3
Author: Narcis Buisac <nbuisac@institutmontilivi.cat>
Date: Sat Jan 8 15:52:52 2022 +0000
Parametrización del programa
commit 18a30f93048e49ccfb1a5227747dc325826198bb
Author: Narcis Buisac <nbuisac@institutmontilivi.cat>
Date: Sat Jan 8 15:48:02 2022 +0000
Creación del proyecto
También es posible ver versiones abreviadas o limitadas, dependiendo de los parámetros:
$ git log --oneline
4ccf057 (HEAD -> master) Se añºade un comentario al cambio del valor por defecto
88d1eff Se añade un parámetro por defecto
d13ad44 Parametrización del programa
18a30f9 Creación del proyecto
git log --oneline --max-count=2
git log --oneline --since='5 minutes ago'
git log --oneline --until='5 minutes ago'
git log --oneline --author=sergio
git log --oneline --all
Una versión muy útil de git log
es la siguiente, pues nos permite ver en que lugares está master y HEAD, entre otras cosas:
$ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
* 4ccf057 2022-01-08 | Se añade un comentario al cambio del valor por defecto (HEAD -> master) [Narcis Buisac]
* 88d1eff 2022-01-08 | Se añade un parámetro por defecto [Narcis Buisac]
* d13ad44 2022-01-08 | Parametrización del programa [Narcis Buisac]
* 18a30f9 2022-01-08 | Creación del proyecto [Narcis Buisac]
Crear alias
Como estas órdenes son demasiado largas, Git nos permite crear alias para crear nuevas órdenes parametrizadas. Para ello podemos configurar nuestro entorno con la orden git config
de la siguiente manera:
git config --global alias.hist "log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short"
Example
Puedes configurar incluso alias para abreviar comandos. Algunos ejemplos de alias útiles:
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st "status -u"
git config --global alias.cane "commit --amend --no-edit"
Recuperando versiones anteriores
Cada cambio es etiquetado por un hash, para poder regresar a ese momento del estado del proyecto se usa la orden git checkout
.
$ git checkout 18a30f9
Note: switching to '18a30f9'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 18a30f9 Creación del proyecto
$ cat hola.php
<?php
echo "Hello, World\n";
El aviso que nos sale nos indica que estamos en un estado donde no trabajamos en ninguna rama concreta. Eso significa que los cambios que hagamos podrían "perderse" porque si no son guardados en una nueva rama, en principio no podríamos volver a recuperarlos. Hay que pensar que Git es como un árbol donde un nodo tiene información de su nodo padre, no de sus nodos hijos, con lo que siempre necesitaríamos información de dónde se encuentran los nodos finales o de otra manera no podríamos acceder a ellos.
Volver a la última versión de la rama master.
Usamos git checkout
indicando el nombre de la rama:
$ git checkout master
Previous HEAD position was 18a30f9 Creación del proyecto
Switched to branch 'master'
Etiquetando versiones
Para poder recuperar versiones concretas en la historia del repositorio, podemos etiquetarlas, lo cual es más facil que usar un hash. Para eso usaremos la orden git tag
.
$ git tag v1
Ahora vamos a etiquetar la versión inmediatamente anterior como v1-beta. Para ello podemos usar los modificadores ^
o ~
que nos llevarán a un ancestro determinado. Las siguientes dos órdenes son equivalentes:
$ git checkout v1^
$ git checkout v1~1
$ git tag v1-beta
Si ejecutamos la orden sin parámetros nos mostrará todas las etiquetas existentes.
$ git tag
v1
v1-beta
Y para verlas en el historial:
$ git hist master --all
- 4ccf057 2022-01-08 | Se añade un comentario al cambio del valor por defecto (tag: v1, master) [Narcis Buisac]
- 88d1eff 2022-01-08 | Se añade un parámetro por defecto (HEAD, tag: v1-beta) [Narcis Buisac]
- d13ad44 2022-01-08 | Parametrización del programa [Narcis Buisac]
- 18a30f9 2022-01-08 | Creación del proyecto [Narcis Buisac]
Borrar etiquetas
Para borrar etiquetas:
git tag -d nombre_etiqueta
Visualizar cambios
Para ver los cambios que se han realizado en el código usamos la orden git diff
. La orden sin especificar nada más, mostrará los cambios que no han sido añadidos aún, es decir, todos los cambios que se han hecho antes de usar la orden git add
. Después se puede indicar un parámetro y dará los cambios entre la versión indicada y el estado actual. O para comparar dos versiones entre sí, se indica la más antigua y la más nueva. Ejemplo:
$ git diff v1-beta v1
diff --git a/hola.php b/hola.php
index 8383c90..cc7265e 100755
--- a/hola.php
+++ b/hola.php
@@ -1,3 +1,4 @@
<?php
+// El nombre por defecto es Mundo
$nombre = isset($argv[1]) ? $argv[1] : "Mundo";
@print "Hola, {$nombre}\n";