"Si tú no trabajas por tus sueños, alguien te contratará para que trabajes por los suyos”

Steve Jobs

Afiliado
Dominios3Euros

Instalación de Git en los distintos sistemas operativos

Es tan fácil instalar en linux desde terminal que da mucha pereza instalar de otra forma.

$ apt-get install git

Si necesitas que os explique con instalar en otros sistemas operativos, me dices o mira esta lista links sobre git que vamos apuntando, puede alguien ya lo haya hecho.

Git es un motor de sistema control de versiones distribuido, el cual en los repositorios locales tienes una copia total del histórico, que luego puede ser distribuido en repositorios remotos.

Inicializar repositorio local

Un repositorio local git es copia total del histórico de cambios de un proyecto. Iniciar un repositorio local es muy sencillo, tanto si es un primer commit, como si queremos clonar un repositorio ya existente.

Si tienes un proyecto y quieres empezar utilizar git como gestor versiones , solo necesitas 3 comandos para iniciar tu primer repositorio local, con git init inicializamos git, con git add añadimos todos los ficheros que tenemos en directorio actual, y git commit creamos el primer commit, ver Primer commit.

Si queremos traer a nuestro equipo en local un repositorio existen con git clone, ejemplo de clonar repositorio de GitHub :

$ git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY

Git clone tiene un mogollón de opciones para poder clonar, mas adelante las veremos, de inicio quédate que la url que ponemos suele indicar el protocolo a utilizar a git.

Una vez iniciado el repositorio local ya nos podemos añadir, modificar, eliminar ficheros y lineas de código, con la garantía y la ventaja que tiene utilizar un sistema de control de versiones.

Tanto si eres un programador que empiezas con Git, mi recomendación es comitear y comitear,  no pienses en organizar cuando y como comitear, simplemente comitea todo aquello que hagas, ya tendrás tiempo de  analizar y ver  cuando realmente necesitas comitear y como.

¡ Te advierto !
git se hace muy adictivo

Configuración de Git

Aunque es muy sencillo crear un repositorio local con git de tu proyecto, eso no implica que si necesitas configuraciones especiales no puedas realizarlas, ya que git tiene muchísimas opciones para configurar a tu gusto tu proyectos en repositorio locales o en repositorios remotos, ahora anoto las básicas que utilizamos nosotros:

  • Git config: Con este comando podrás configurar el usuario y  el mail, ideal si trabajas con mas programadores o repositorios remotos.
    Tambien con este comando puedes configurar que git tenga en cuenta los cambios de los permisos en los ficheros, algo útil cuando trabajamos en distintos servidores con permisos distintos.Mas info sobre  Git config,  :-)
  • fichero .gitignore : Este fichero es ideal para descartar el seguimiento de ficheros , ficheros como cache, configuraciones,...  aquello que no queremos controle git o publique en repositorio.

Recuerda que cuando comiteas un fichero, este queda registrado en git, aunque luego lo cambies o lo elimines , queda en el historia de git, por lo que cambiando al comit correspondiente podras verlo, esto puede ser un agujero de seguridad.

Primer commit en Git

$ git init # Añade repositorio.. crea un directorio oculto .git en esa misma ruta 
$ git add . # Marca todos los ficheros para el próximo commit.
$ git commit -m "Estado inicial" # Crea un nuevo commit con los ficheros marcados.

Con las tres instrucciones anteriores ya hicimos el primer commit, ya tienes creado un repositorio local de git de tu proyecto.

Saber en el estado que estamos.

Empezamos trabajar y realizamos cambios en nuestro código, ahora queremos saber que:

  • ficheros nuevos ( untracked )
  • Ficheros modificicados
  • Ficheros borrados

Con el siguiente comando:

git status

Nos indica estos ficheros nos apareceran todos en ROJO, inicialmentes ya que no los hemos añadido STAGED (preparados para comitear).

Si nos aparece alguno en VERDE es que ya lo añadimos con git add.

Si queremos solo listar los ficheros nuevos que son untracked

Lo podemos hacerlo con:

git ls-files --others --exclude-standard 

 Si os pasa como a mi, que necesitaís sabes el peso de esos ficheros, ya que la mayoría son imagenes y las suben clientes que no respectan los estandares de nombres y pesos, yo utilizo esta  consulta.

git ls-files --others --exclude-standard | sed -e 's/ /·/g' -e 's/·/\\ /g' | xargs ls -hs | sort -hr

 

Preparar para comitear añadir STAGED

Una vez queremos sepamos que fichero queremos añadir a nuestro nuevo commit, debemos indicarlo para que git los prepare para commitear (STAGED), si queremos añadir todo utilizamos la siguiente instruccion:

git add .

Con el anterior comando al volver hacer "git status" nos apareceran los ficheros en VERDE, indicando que cambios a indicar ser confirmados. Si nos apareciera alguno en ROJO  es que no se añadio a esa confirmacion.aquellos ficheros que se modificaron, se eliminaron o que está( sin seguimiento) que son los nuevos normalmente, utilizamos la siguiente instrucción

 Al poner el  (.) indicas que prepare los ficheros cambiados a partir de la ruta que estas.

También puedes añadir fichero a fichero, simplemente añadiendo el nombre del fichero.

Hay otra forma más intuitiva de utilizar esta instrucción con la opción :

git add -i

Donde nos muestra un menú como este:

*** Commands *** 
1: status   2: update   3: revert   4: add untracked
5: patch   6: diff   7: quit   8: help

Seleccionando cualquiera de las opciones , nos permite con simple numero , y secuencias como 1-12, 13 ,15 añadir varios ficheros a la vez... marcándolos con * cuando estén añadidos.

En este menú interactivo puedes ver algunas de la opciones que tiene este comando. Ver entrada Git Add

En todo momento podrás volver ejecutar el comando "git status" para saber el estado de los ficheros.

Comitear ficheros modificados / nuevos o/y eliminados.

Una vez tengamos los fichero añadidos con "add" y al verlos con "status" están listos, preparados para comitear:

git commit - m " Texto breve de los queremos comitear

La instrucción anterior es el método abrevidado, sin la opción -m , te abre el editor por defecto que tengas asignado config de git y ahi puede escribir el texto.

Al abrir el editor al comitear te muestra lineas comentadas, que tu puede des-comentar eliminando # al inicio de la linea, una forma rápida comentar un commit.

Recuerda que el  mensaje que pongas a la hora comentar lo puedes ver , una forma cómoda es con git log, también se puede buscar esos commit donde hay un texto determinado.

Eliminar un fichero ya comiteado.

Si quieres eliminar un fichero que comiteaste en su día, puedes hacerlo directamente con:

git rm <fichero>

Donde lo elimina y lo prepara para comitear.

Es lo mismo que si lo eliminamos nosotros a mano y luego realizamos git add <fichero eliminado>, recuerda que estos ficheros si ya fueron comiteado, podrías recuperarlos si lo deseas con instrucción git checkout , que veremos mas adelante.

Si tuviéramos muchos ficheros la mejor opción sería:

git rm $(git ls-files -d)

Está instrucción hace lo  mismo eliminado los ficheros y prepara commit  de todos los ficheros eliminados.

OJO:
Si el fichero no esta incluido en el seguimiento (tracket) entonces elimina simplemente manual, ya  que git no lo tiene control sobre el.

¿Imagina que antes comitear quieres ver las diferencias que tiene un fichero determinado?

Tiene varios comando para realizar esto, pero el principal

git diff [ruta/del/fichero]

Nos mostrará todos los cambios de ese fichero, si no ponemos fichero , nos muestra todos los cambios de todos los ficheros que no está commiteados.

Este comando tiene muchas opciones y posibilidades ver más información en Git Diff -Ejemplos

Algunos IDES y incluso programas como DIFFUSE se complementan perfectamente con GIT y muestra las diferencias de los ficheros de una forma visual.

Deshacer el ultimo commit

Muchas veces hacemos un commit y nos damos cuenta que los cambios realizados están mal o nos falto algo. Aunque yo soy de los pienso que hagas otro commit y listo, pero bueno a veces por motivos de orden, estetica o que vas añadir a un repositorio, no quieres que vean varios commits, pues puede desahacer el ultimo commit.

Para eliminar el ultimo commit y asi poder añadir esos cambios y volver a commitear.

git reset HEAD~

Te deja todos los ficheros como están, si realizar un git status, veras que podrás volver añadirlos para commitear.

 Es muy importante que entiendas que ese ultimo commit esta en tu rama y solo en local, no lo subiste a un repositorio remoto, ya que vas cambiar la cabecera de esa rama. Es importante que no lo hubieras subido o que no este en las ramas remotas ya que luego tendrías problemas para subirlo.

¿ Ahora queremos dejar todo como estaba ?

Muchas veces necesitamos recuperar el estado de unos ficheros , que fuimos cambiando o se cambiaron , por algún motivo...

Pues si queremos volver a recuperar el estado del ultimo commit de todos los ficheros, podemos realizar:

git reset --hard HEAD

Donde está instrucción deja el repositorio en el ultimo comit de esa rama.

Con esta ultima instrucción los ficheros que hubieras eliminado los recuperas y los que modificaste te los deja modificado pero sin preparar para commit.

A veces confundimos esto con dejar como estaba antes, sin mantener lo cambios que realizamos antes del commit, por lo que los ficheros que tiene a mayores sin comitear te los deja tal cual, no los cambia.

Para recuperar el estado HEAD debemos hacerlo con git checkout de lo ficheros que cambiamos.

 ¿ Quiero ver lo que cambie en commit anteriores ?

Para listar los commit realizados ( nuestro árbol) . Con la instrucción :

git log

git log

Nos muestra un listado de los commit que tenemos en el proyecto, en orden descendente, es decir muestra el ultimo al primero.

Ahora si queremos que nos muestre en una sola linea una forma cómoda es:

git log --pretty=format:"%h - %an, %ar : %s"

Si ademas nos gustaría que nos informe de los ficheros que cambiamos (M) Modificamos (D) Eliminamos , pero solo el nombre...

git log --pretty=format:"%h - %an, %ar : %s" --name-status

Mas sobre la git log

Si queremos saber los commit que realizaron en es proyecto debemos ejecutar dentro del proyecto

$ git log <path> 
# Mostrar todos los commits para un fichero especifico con info detallada
$ git log -n 2 -- <path>
# Mostrar sólo los dos últimos commits para ese fichero
$ git log -oneline -- <path>
# Formato abreviado con id de commit y comentario $ git log <SINCE>..<UNTIL> -- <path>
# Mostrar los commits para ese fichero entre dos commits indicados

 

Localizar y restaurar ficheros borrados

$ git log --diff-filter=D --summary # Mostrar los ficheros borrados en los últimos commits $ git checkout <COMMIT>^ -- <path> # Restaurar un fichero borrado en un commit dado

El ^ al final del commit es para restaurar el fichero desde el commit anterior al que fue borrado. Equivale a ~1.

Abrir GITK mostrando gráficamente el historial para un fichero o ruta dado:

$ gitk <path>

 

git whatchanged

Una vez localicemos el commit , anotando el numero que nos indica, podemos ver los ficheros que cambiamos en ese commit, con la instrucción

git whatchanged -1 [8 digitos por lo menos del numero commit]

Entonces nos listará los ficheros que cambiamos en ese commit.

Con este mismo comando podemos listar todos los commit que afectaron a un fichero.

git whatchanged [/ruta/del/fichero]

Y si antes de la ruta , ponemos la opción -p , ya nos muestra los cambios en cada commit.

¿ Queremos comparar un fichero en distintos commit?

Ahora imaginar que necesitas saber los cambios que realizamos en un ficheros con respecto al estado actual de ese fichero. Conociendo el numero commit, con git diff ya puedes verlo:

git diff [numero commit] /ruta/del/fichero 

Nos muestra los cambios que tenemos en el fichero ( estado actual)  comparando con el mismo fichero en momento realizar el commit.

Si quisiéramos comparar ese fichero pero cuando comitamos , es decir comparar el estado del archivo en los momento de dos comit.

git diff [nºcommit1] [nºcommit2] /ruta/del/fichero 

Más retorcido todavía....

Y si queremos comparar un fichero con otro fichero que este incluido dentro del repositorio de git con el comando diff

diff -u /ruta/del/fichero1 /ruta/del/fichero2 

¡¡ IMPRESIONANTE !!...

 

Ramas en  Git : Locales o remotas

Una rama es bifurcación del proyecto en punto determinado (commit). Cuando iniciamos un repositorio nos inicia en la rama "master" que la rama principal del proyecto.

En todo proyecto es recomendable tener por lo menos, dos ramas "master" y "stable" que sería la rama produccion, los nombres de las ramas podra ser el queramos.

Cuando  vamos realizar un cambio, lo recomendables es hacer rama nueva, luego lo podremos mezclar con master.

En los repositorios de git, recuerda que tambien hay ramas, estás son las ramas remotas.Tenemos que tener en cuenta, que podemos tener ramas locales que no estén remoto y viceversa

Mas informa sobre git branch

Ramas locales

Instrucciones básicas trabajar con ramas locales,  para poder listar ,crear, cambiar nombre o eliminar una rama local.

Listar ramas locales existentes.

Es ideal saber en todo momento que rama existen en tu repositorio local.

$ git branch 
# Lista las ramas existentes.

Con esta instrucción nos muestra todas las rama que tenemos en el repositorio.

$ git branch -l pattern # nos muestra lista las ramas que coincidan con el patrón.

Crear un ramas locales

Cuando creamos una rama lo hacemos desde el commit actual.

$ git branch <nombre>                 
# Crear la rama en el punto actual.
$ git checkout

Con la siguiente instrucción , nos ahorramos la primera instrucción ( git branch )

$ git checkout -b <nombre>

Las dos instrucciones anteriores realizan lo mismo, crear la rama desde el punto actual y se mueve a ella.

Como cambiar de rama

Con la siguiente instrucción tanto podemos cambiar de rama , como situarnos en commit de terminado.

$ git checkout <nombreRama o commit> # Nos mueve la rama o commit 

Cuanto pones la cabecera en un commit determinado y vas hacer cambios, te recomiendo que crees una rama desde es punto.

Cambiar el nombre de una rama.

$ git branch -m <actual> <nuevo>  # Renombrar la rama

 

Como borrar una rama local

Cuando ya no necesitamos una rama, no vamos continuar con ella, para eliminarla si esta ya fusionada o contenida en master o otras ramas podemos utilizar siguiente instrucción.

 $ git branch -d <nombre> # Borrar la rama

En el caso que no esta fusionada con otra rama, podemos eliminar, forzando el borrado con la siguiente instrucción.

$ git branch -D nombredelarama # Borrar la rama aunque no este fusionada

Como crear una rama desde un commit determinado

 $ git branch <nombre> <COMMIT>
$ git checkout      
 # Crea la rama a partir del commit dado. Es necesario hacer checkout.
$ git checkout -b <nombre> <COMMIT>          
 # Crear rama a partir del commit dado.

De las dos formas que podemos crear una Rama , indicando el commit desde el queremos crear la nueva rama.

 

Ramas Remotas

Las rama remotas son las ramas que tenemos en repositorio remoto.No estan creadas por defecto en local, se puede crear una rama local a partir de un repositorio remoto.

Crear una rama local a partir de una remota

$ git checkout -b nombrerama origen/rama_remota

En la instrucción anterior creamos una rama local a partir de una rama remota. El nombre de la rama local no tiene porque ser el mismos de la remota.

De esta forma tenemos una rama local denominada rama de seguimiento que tienen una relación directa con alguna rama remota, esto sucede automáticamente con master, pero puede suceder otras ramas que tengamos en remoto, pero no tiene porque estar relacionadas.

No tengo claro cuando crea esa relación de seguimiento, ya que en algunas ocasiones después de crear la rama de remoto, al hacer push para subir los cambios de esa rama en remoto, me dice que le falta referencia.

Crear una rama remota desde una rama local

Si tenemos el puntero en la rama queremos subir , con la siguiente instrucción:

git push origin ramanueva

Teniendo en cuenta origin es el alias que utilizamos para nuestro repositorio remoto.

 

 

Listas ramas locales y remotas

Si tenemos añadido un origen remoto y queremos listar las ramas remotas y locales:

$ git branch -va

 En la instrucción anterior nos muestra el commit en el que esta, tambien nos muestran las rama locales, que las muestra en rojo.

Si queremos ver las ramas que están fusionadas con la actual rama, podemos hacer:

$ git branch -va --merged 

# Mostrar ramas que se han fusionado con la actual, y por tanto pueden borrarse

Por el contrario si queremos saber aquella que no estan fusionadas con la actual

 git branch -va --no-merged # Mostrar ramas con trabajos sin funsionar. Intentar borrarlas dará un error.

 Si solo quisieramos ver las locales , quitando la opcion -va , seria suficiente.

Eliminar ramas remotas de nuestros repositorio local.

A veces sucede que en repositorio remoto eliminan ramas, que ya se descartaron o fusionaron, pero en nuestro repositorio local nos la sigues mostrando.

Con la siguiente instrucción nos purga las rama remotas que ya no existen.

$ git fetch --prune

Existe tambien la opcion git remote --prune, pero la verdad nunca la utilice.

Fusionar ramas

Para fusionar ramas yo utilizo merge o rebase. Ambas instrucciones consigue unir ramas, aunque la primera te hace un commit confirmando el merge y el rebase lo que hace mover el puntero de la rama en la que esta fusionado.

Os pongo un link donde explica muy bien la diferencias entre estas dos instrucciones. (link a medium entrada de Miguel Casas), pero en esencia los viene a decir es:

El rebase fusiona las ramas dejando un arbol lineal. El merge aun deja el gráfico de las ramas.

 

$ git merge <nombre>       # Fusiona la rama indicada en la rama actual

Las diferencias se resuelven automáticamente si es posible. En caso de conflictos (código o ficheros binarios modificados en ambas ramas) el proceso se detiene (merging) a la espera de una resolución manual.

Resolver conflictos de fusionado:

Al hacer "merge" y si hay conflictos , git nos marca los ficheros con <<<< HEAD  y separando el codigo que tiene conflicto con ============  , cerrando  con >>>>>>>>>>>>>

Esto solo es posible en ficheros de texto plano, claro está... :-)

La sección “Unmerged paths” de git status muestra los ficheros que requieren atención. Debe resolverse cada conflicto manualmente dentro del fichero (eliminando las marcas agregadas por git) y marcarlo como resuelto con git add.

En vez de editar los ficheros es posible escoger una de las dos versiones disponibles (rama actual o rama que se está fusionando):

$ git checkout --ours -- <file> # Obtener la versión del fichero en la rama actual $ git checkout --theirs -- <file> # Obtener la versión del fichero en la rama que se está fusionando con la actual

Para abortar la acción o anularla una vez realizada:

Resolución gráfica de conflictos:

$ git mergetool # Inicia la herramienta gráfica de resolución de conflictos

La herramienta crea ficheros adicionales por cada fichero en conflicto (backup, base, local, remote) para que la herramienta de resolución pueda mostrarlos al usuario al mismo tiempo y éste establecer la versión final. Estos ficheros deberían borrarse automáticamente tras la edición (en caso de que persistan es necesario borrarlos manualmente).

La resolución básica sólo sirve para ficheros de texto. En ficheros binarios usar git checkout –ours o git checkout –theirs para escoger una de las dos versiones disponibles.

Deshacer cambios

$ git revert <COMMIT> # La recuperación hace un nuevo commit en la rama actual sin ir "hacia atrás" en la historia $ git reset --hard # Deshace los cambios locales $ git reset --hard HEAD~1 # Elimina el último commit

Recuperar una versión determinada de un fichero o path:

$ git reset <COMMIT> -- <path> # git reset NO sobreescribe cambios locales $ git reset -p <COMMIT> -- <path> # Seleccionar interactivamente las partes a restaurar $ git checkout <COMMIT> -- <path> # Sobreescribe cambios locales sin preguntar</

En Windows se puede abrir git-bash directamente en cualquier subcarpeta carpeta del proyecto (botón derecho – git bash here). Entonces para recuperar un fichero o path local:

$ git checkout <COMMIT> -- ./<path>

Y mas cosas git

Git es impresionante y tiene un sin fin de cosas mas.

 

Git Stash: Guardar cambios actuales para recuperarlos después

Imagina que tienes unos cambios realizados y quieres cambiar rama, no puedes, para ello la siquiente instrucción es ideal. Si por cualquier cosa hay conflitos te hace un merge.

$ git stash 
# Directorio de trabajo guardado y estado de índice WIP on master: 86ba40f3 Arreglo para funciones balanzas.

Realmente lo que hace es guardar en memoria (índice WIP?) los cambios que tiene realizados desde el HEAD.

Ojo , solo los cambios, los ficheros nuevos sin seguimiento no lo hace, ya que si tenemos ficheros sin seguimiento, git nos permite cambiar rama perfectamente.

# Cambiamos de rama y ejecutamos.
$ git stash pop
# Recupera los cambios guardados

Tambien si lo deseamos ya podemos crear una nueva rama con los cambios guardados.

git stash branch testchange

 Ahora imagina que quieres solo guardar en stash uno o dos ficheros, no todos los que tienes cambiados.

Lo hice hasta ahora era primero git add , aquellos que voy comitear y luego comiteo. Listo, ya solo me queda los ficheros que quiero guardar en stash.

Lo que pasa que a veces la cabeza nos da mala pasada y pensamos al reves, queremos primero guardar esos cambios stash y luego seguir con el comit, pues tambien hay solucion:

git stash push fichero_queremos_guardar_stash

Luego continuamos con lo que estabamos haciendo, comiteamos y si nos acordamos que hemos guardado un cambio en stash , pues hacemos lo queríamos hacer con el. :-)

 

Git Tag : Marcar un commit

 Git tag lo utilizamos normalmente para marca un commit como una version del proyecto.

$ git tag -a V.0.0.0

Marcaria el comit actual como una etiqueta de la version, saldría refleja en log.

$ git tag -s <nombre> -m <mensaje>

El tag queda firmado usando la firma GPG asociada al autor (ver Creating SSH keys).

$ git tag

Listaria todos los tag que existan en el proyecto.

¿ Si quieres saber cual es el ultimo tag ?

Si quieres saber el ultimo tag en el que estas, en la version del proyecto que estas, podríamos decir:

$ git describe 

No responde algo asi

v0.2.30-3-g0a5aeabc

El ultimo grupo de digitos es numero de commit.

 

 

El nombre identifica al tag y se usa en los demás comandos (ej. git checkout). Por ejemplo, v2.32.45r1

$ git tag -d <nombre> # Eliminar Tag $ git tag -a <nombre> # Crear Tag no firmado $ git push --tags # Subir Tags al repositorio remoto $ git push origin :refs/tags/<nombre> # Eliminar Tag borrado localmente

Localizar ficheros con una cadena de texto

$ git grep <texto> # Mira en todos los ficheros del repositorio $ git grep <texto> -- <ruta> # Mira sólo en la ruta o rutas especificadas # Admite patrones (ej. *.cpp)

 

 

Comentarios  
My family every time say that I am wasting my time here at net, except I know I am getting experience
everyday by reading thes fastidious content.
#2 utilizamos Joomla.
Hey would you mind sharing which blog platform you're working with?
I'm looking to start my own blog in the near future but I'm having a
difficult time selecting between BlogEngine/Wordpress/B2evolution and
Drupal. The reason I ask is because your design seems different then most blogs
and I'm looking for something unique. P.S Apologies for being off-topic but I had to ask!
Thanks for your personal marvelous posting! I seriously enjoyed reading
it, you may be a great author. I will ensure that I bookmark your blog
and will often come back in the future. I want to encourage you continue your great posts, have a nice morning!