Usando las herramientas para Git de VS2012

Muy buenas! En este post voy a contar (o al menos intentarlo) como usar las herramientas de Git para VS2012 y trabajar con un repositorio Git instalado en TFS Services.

Nota: Este post está muy orientado a gente que viene de TFS, está acostumbrada a TFS y se siente un poco “perdida” con esto de Git. No pretende ser, ni mucho menos, un tutorial de Git.

Requerimientos previos

Debes tener instalado VS2012 y al menos el Update 2. Ve a la página de Updates de VS2012 para descargarte el último update (en la actualidad es el 3).

Una vez tengas el VS2012 actualizado, debes instalarte las herramientas para Git de VS2012, que te puedes descargar desde el gestor de extensiones de VS2012 o bien desde la propia página de las Visual Studio Tools for Git.

Finalmente debes tener una cuenta de TFS Services, que te puedes abrir en http://tfs.visualstudio.com. Abrir una cuenta es totalmente gratuito y te da acceso a un TFS listo para 5 usuarios de forma totalmente gratuita.

Antes que nada: diferencias entre Git y TFS clásico

El control de código fuente clásico de TFS es lo que se conoce como un CVS (Concurrent Version System), mientras que Git es un DCVS (Distributed Concurrent Version System). En TFS está claro quien es el servidor: te connectas a un servidor TFS, te bajas código de él y subes código en él.

Con Git, cada máquina es también un repositorio de código fuente. Vas a tener tu propio repositorio de código fuente en local. No tendrás solo “la última versión” si no todo el control de código fuente. Esto hace que operaciones como Branch o Merge sean mega rápidas (y puedas hacerlas offline).

De hecho, no hay en Git, un flujo que obligue a que haya un “servidor de Git centralizado”: puedes tener varios repositorios remotos con los cuales te sincronizas.

De todos modos, dado que es bastante habitual un flujo donde haya un servidor Git “central”, este es el que veremos en este post. En nuestro caso este “servidor git central” será TFS Services con el control de código fuente Git habilitado.

En Git no hay check-in o check-out, ni tampoco lock. En su lugar las operaciones básicas que tenemos son:

  1. Commit: Pasa cambios de tu working folder a tu repositorio git local pero NO al remoto.
  2. Push: Pasa cambios de tu repositorio git local al remoto
  3. Pull: Pasa cambios del repositorio git remoto al local y a la working folder.

Ahora sí…. empecemos.

Primer paso: Crear el team project

Para tener un repositorio Git en TFS debemos tener un team project. Así que dale al botón “New Team Project” desde la página principal de TFS Services y en las propiedades del proyecto asegúrate de seleccionar Git como gestor de código fuente:

image

Una vez tengas el team project creado estás listo para empezar a trabajar con Git.

Añadir la solución al control de código duente.

Para ello desde el solution explorer seleccionamos la opción “Add solution to Source control”. VS2012 nos preguntará si deseamos usar Git o bien el control de código fuente de TFS. Hasta ahora simplemente habíamos creado un repositorio de Git, pero no le habíamos indicado a VS2012 que íbamos a usarlo en nuestra solución:

image

Asegúrate de marcar la opción de Git y dale a Ok. Ahora si que estamos listos para hacer commits.

Al marcar la opción de Git, VS2012 nos crea un repositorio de Git local que está en el mismo directorio que nuestra solución. De hecho si abres con el explorador de archivos la carpeta de la solución, verás una carpeta oculta, llamada .git que es la que contiene el repositorio local.

Commit

Vamos a guardar nuestro código o en el repositorio de Git local. A diferencia del TFS clásico en Git no se protegen o desprotegen ficheros, así que no hay opciones de check-in o check-out. Básicamente Git mira todos los cambios que se producen entre la working folder y el repositorio Git local y son los ficheros que tengan cambios (de cualquier tipo) los que podemos “commitear” y enviar al repositorio Git local. Para hacerlo vete a la página inicial del team explorer pulsando el icono de home:

image

 

Ahora pulsa sobre de “Changes”. Con eso VS2012 te mostrará todos los archivos de la working folder que tengan algún cambio respecto al repositorio de Git local (es decir que se hayan añadido, borrado o modificado).

image

 

Los ficheros que aparecen en Included Changes son los ficheros que se incluirán en el commit. Los que aparecen en Excluded Changes son los que no se incluirán en el commit. Puedes pasar ficheros de un sitio a otro arrastrándolos. Una vez tengas el commit listo, debes añadir un mensaje de commit y ya podrás darle al botón “Commit”.

Una vez lo hayas hecho VS2012 te mostrará un mensaje diciendo que el commit ha sido correcto y continuarás en la misma página de commits, para seguir haciendo commits si quedan ficheros con cambios (es decir, ficheros que antes habías colocado en “Excluded Changes”). Eso es así porque con Git es costumbre hacer muchos commits y muy pequeños.

Push

Si ahora vuelves a la página inicial del Team Explorer (con el icono de la casita) y pulsas sobre el enlace “Commits” te aparecerá una ventana como la que sigue:

image

VS2012 nos pide que repositorio Git va a ser el remoto. Este debe estar vacío. Recuerda que antes hemos creado uno en TFS Services, pero todavía no habíamos dicho en ningún sitio que queríamos usarlo. Ahora ha llegado el momento. Copia la URL del repositorio Git remoto (la puedes encontrar en la página de TFS Services si vas al team project creado y al apartado “Code”) y dale al botón “Publish”. Con este proceso asociarás tu repositorio de Git local con el repositorio de Git remoto y además harás un push de los commits pendientes (es decir pasarás el código de tu repositorio Git local al remoto).

Cuando haya terminado te aparecerá una página parecida a:

image

¡Felicidades! Ya tienes un repositorio de Git local y remoto enlazado a tu solución.

Veamos ahora como añadir un cambio.

Para ello modifica un par de archivos del proyecto. Puedes hacerlo directamente: recuerda, olvida el concepto de check-out (desproteger). Vete a la página de Changes del team explorer (ve a la página principal a través del icono de casa y luego pulsa en Changes) y te aparecerán los dos archivos modificados:

image 

Arrastra uno de los dos a Excluded Changes, añade un mensaje de commit y dale a commit. Te aparecerá una pantalla como la siguiente:

image

Ahora arrastra el otro archivo a Included Changes, pon otro comentario y dale a commit de nuevo. Con esto has generado dos commits en el repositorio git local.

 

Si ahora te vas a la página de Push (vete a la inicial con el icono de la casa) y dale Commits (debajo de Changes) verás algo parecido a:

image

En outgoing commits te aparecerán los commits que has hecho en el repositorio local y que no están en el repositorio remoto. Si le das a “Push” subirás los cambios (los commits) desde el repositorio local al remoto.

Obtener los cambios de otro usuario

Vale, a no ser que estés tu solo en un proyecto (y sí, si estás tu solo en un proyecto te recomiendo encarecidamente también usar control de código fuente) en algún momento deberás incorporar los cambios que hay en el repositorio remoto al tu repositorio local.

Vete a la página de commits del team explorer (ya sabes, desde la home le das al enlace de Commits):

image

Debajo de “Incoming Commits” hay dos opciones:

  1. Fetch: Te permite obtener el listado de cambios que tienes pendientes de integrar. Es decir, el listado de commits que están en el repositorio remoto pero NO en tu repositorio local.
  2. Pull: Se trae los commits desde el repositorio remoto al repositorio local y actualiza la working folder.

Si le das a Pull el proceso es automático (Git se trae los commits del repositorio remoto al local y desde el local hacia la working folder resolviendo los conflictos si hiciese falta).

Si le das a Fetch, te aparecerán los commits que existen en el repositorio remoto, pero están pendientes de ser integrados a tu repositorio local:

image

Viendo los detalles de un commit

A veces, antes de integrar el código del repositorio remoto (es decir, antes de hacer pull) te interesa ver como este commit puede afectar a tu trabajo. Para ello, una vez has obtenidos los commits pendientes de integrar (es decir, una vez has hecho fetch) puedes ver los detalles de un commit pulsando con el botón derecho sobre él y seleccionando la opción “View Commit Details”:

image

Esto te permite ver los ficheros que conforman el commit, ver su contenido y compararlo con la versión anterior de este mismo fichero.

Resolviendo conflictos.

Imagina la situación en que tienes modificado un fichero en tu carpeta local pero NO has hecho commit de este fichero en tu repositorio git local. Imagina que haces pull y hay un commit que tiene este fichero modificado.

Cuando esto ocurrer recibirás el siguiente mensaje de error:

image

Si te aparece este mensaje debes primero hacer commit de tus cambios pendientes en tu repositorio Git local. Una vez hayas hecho el commit (no es necesario que hagas el push hacia el repositorio remoto) ya puedes volver a hacer el pull.

Entonces, Git intentará hacer merge automático entre el contenido de tu repositorio local y los commits que vienen del repositorio remoto). Pero puede que el merge automático no sea posible:

image

Nota: En esta pantalla “Incoming Commits” son los dos commits que estoy intentando integrar y en “Outgoing Commits” hay el commit que he hecho para colocar los cambios de la carpeta local hacia mi repositorio remoto. Como solo he hecho commit pero no push, por eso me aparece aquí.

Ahora pulsas sobre el enlace “Resolve the conflicts” y te aparece la página de resolución de conflictos:

image

Pulsando sobre cada uno de los archivos en “Conflicts” tendremos las opciones clásicas de tomar el archivo local (el de nuestro repositorio Git local), el remoto (el del repositorio Git remoto) o combinarlos:

image

Si le damos a “Merge” nos aparecerá la clásica ventana de Merge:

image

 

 

 

Una vez hayamos resuelto todos los conflictos, aceptamos el merge y repetimos la operación por todos los archivos. Al final llegaremos a una página parecida a:

image

Donde no habrá nada en “Conflicts” y todo estará en “Resolved”. Ahora tenemos estos cambios en nuestra working folder, pero NO en nuestro repositorio local de Git (y mucho menos en el remoto obviamente). Así que le damos a “Commit Merge” para pasar estos cambios de nuestra working folder a nuestro repositorio Gi local. Al hacerlo iréis a la página de Changes con el commit listo para ser enviado al repositorio local:

image

Fíjate que el commit que se me ha creado incluye tanto el archivo Program.cs (que es el que tenía conflictos) como el archivo App.config que pertenecía al otro “incoming commit”.

Una vez le deis a commit ya lo tendréis en el repositorio git local.

Finalmente os vais a la página de “Commits” y vereis los commits pendientes de integrar hacia el repositorio remoto (es decir, pendientes de hacer push):

image

Ahora puedes hacer push sin ningún problema y tu código integrado ya está en el reposiorio Git remoto.

Conclusiones finales

Cuando se trabaja en Git, no se trabaja a nivel de fichero, como con el control de código fuente clásico de TFS, si no que trabajamos a nivel de commit.

Debido a esto, haz commits pequeños.

Recuerda siempre el concepto de que hay un repositorio Git local y otro de remoto. A diferencia del control de código fuente clásico de TFS donde solo hay el remoto.

Si intentas hacer pull y tienes algún fichero modificado en tu working folder (del cual no has hecho commit hacia tu repositorio local) que está incluído en los commits que vas a integrar desde el servidor remoto, te dará error y deberás hacer primero un commit de este fichero (es decir pasarlo a tu repositorio local).

Espero que con esto os quede un poco más claro como funciona Git usando esta extensión de VS2012.

Finalmente: esta extensión no es, ni de lejos, el mejor cliente Git para Windows. Para flujos sencillos funciona bien, ya que está integrada en Visual Studio, pero para flujos de trabajo más complejos se queda corta. En estos casos es mejor usar un cliente de Git específico como SoureTree.

Saludos!

[Editado 20/07/2013] – Corregido un error (mirar comentario de Enrique Ortuño).

 

Katana: Cortando el framework

Si eres desarrollador en tecnologías Microsoft y especialmente desarrollador web, acúerdate de esas dos palabras: Proyecto Katana. Este proyecto representa el futuro a corto plazo de todas las tecnologías de desarrollo web de Microsoft y, no me cabe duda de ello, el futuro a medio plazo del propio .NET.

No dejes que esa introducción te confunda: Katana no es una nueva tecnología, ni una nueva plataforma, ni un lenguaje nuevo, ni tan siquiera realmente una API nueva. Es simplemente un cambio de filosofía. Es como Microsoft entiende que debe ser la evolución de ASP.NET para poder seguir dando respuestas al, cada vez más, cambiante mundo del desarrollo de aplicaciones web. Katana se circumscribe sólo a ASP.NET, pero no me cabe duda de que al final todo .NET irá en la misma dirección.

¿Y qué dirección es esa? Para saber donde vamos hemos de saber de donde venimos…

Hace 12 años (año arriba, año abajo)…

Microsoft sacó .NET y con él una “nueva versión” de ASP. Conocida primero como ASP+, luego ASPX para adoptar la terminología de ASP.NET al final. La intención de MS con ASP.NET era doble. Por un lado que los desarrolladores de “toda la vida” en tecnologías web de Microsoft (que en un 95% usaban ASP) empezaran a usar la nueva versión. Pero también que esa nueva versión pudiese ser atractiva y usable rápidamente por la gran mayoría de los desarrolladores que usaban tecnologías Microsoft, lo que era equivalente a decir VB6 en aquella época.

Es este segundo objetivo el que hace que Microsoft apueste por el modelo de Webforms para que “desarrollar para web sea igual a hacerlo para escritorio”. No olvides eso: el assembly principal de ASP.NET (System.Web.dll) está totalmente acoplado a IIS.

ASP.NET se integró dentro de lo que se pasó a llamar (y se llama) .NET Framework: Un framework monolítico del que ASP.NET era tan solo una parte y que se actualizaba cada cierto tiempo (entre 1 y 2 años y pico), básicamente cada vez que había una nueva versión de Visual Studio.

En medio de todo este tiempo varios cambios en el paradigma del desarrollo web a los que ASP.NET no podía responder con prontitud por su modelo de distribución y actualización, hicieron que alguien en Redmond se diese cuenta de que alguna cosa se tenía que hacer.

Hace 4 años (año arriba, año abajo)…

Veía la luz ASP.NET MVC. Era un nuevo framework, basado en ASP.NET que venía a complementar a Webforms. Desde este momento había dos APIs para desarrollar aplicaciones web en tecnologías Microsoft: Webforms y ASP.NET MVC. Ambas funcionaban bajo toda la plataforma de ASP.NET (y el .NET Framework subyacente que era el 3.5SP1 por aquel entonces).

Pero la novedad principal de ASP.NET MVC no era que fuese una nueva API si no el hecho de que se distribuía independientemente del .NET Framework. Era la primera vez que una API de Microsoft veía la luz fuera del “paraguas” aglutinador del .NET Framework. Esto suponía la posibilidad para Microsoft de evolucionar ASP.NET MVC mucho más ágilmente. Para que te hagas una idea: junto con el .NET Framework 4, salió ASP.NET MVC2. Después salieron MVC3 y MVC4 sin que hubiese ninguna versión más del Framework, hasta que salió Visual Studio 2012 y el .NET Framework 4.5.

ASP.NET MVC marcaba una nueva tendencia (que luego ha seguido Entity Framework) en donde se intenta huir de un framework monolítico para pasar a otro “framework” formado por varios módulos que se actualizan de forma separada.

Pero recuerda: ASP.NET MVC seguía funcionando bajo System.Web.dll y por lo tanto estaba “atada” a IIS (y también al .NET Framework, ya que System.Web.dll forma parte del .NET Framework).

Hace tres año (año arriba, año abajo)…

La aparición de ASP.NET MVC3 supuso otro hito importante en esta historia, no por MVC3 en si mismo, si no por un componente que le acompañaba: NuPack.

NuPack, luego llamado NuGet, era una extensión de Visual Studio que permitía (permite) instalar paquetes de forma muy sencilla. Estos paquetes pueden ser cualquier cosa, usualmente librerías de terceros (pero también templates de proyectos, etc). Era como tener PEAR pero en .NET.

No sé si cuando salió alguien fue consciente de la importancia que adquiriría NuGet para el desarrollo en tecnologías Microsoft…

Hace un año (año arriba, año abajo)…

Salió ASP.NET MVC4 y el hito final de esta pequeña historia. No por MVC4 si no por un componente que le acompañaba (otra vez) y que parecía que formaba parte de MVC4 cuando realmente poco tenía que ver con ella: WebApi.

La gran novedad de WebApi es que no tenía ninguna dependencia contra System.Web.dll. Es decir, WebApi podía evolucionar de forma completamente independiente de ASP.NET (eso no era del todo cierto en ASP.NET MVC aunque se distribuyera via NuGet) y además al no depender de System.Web.dll implicaba que no se estaba atado a IIS por lo que se podía hospedar WebApi en otros procesos (p. ej. una aplicación de línea de comandos).

La idea de WebApi es pues la idea final: una parte del framework sin dependencias externas, que evoluciona a su propio ritmo y que se distribuye automáticamente via NuGet.

Hoy (día arriba, día abajo)…

El proyecto Katana es quien ha tomado el relevo de esta filosofía que se inaugura con WebApi. La idea del proyecto Katana es tener un conjunto de componentes cada uno de los cuales pueda evolucionar independientemente y por supuesto sin ninguna dependencia a System.Web.dll.

Katana es un conjunto de componentes, implementados por Microsoft y que son componentes OWIN. Estos componentes van desde hosts, servidores hasta componentes funcionales (p. ej. hay una versión de SignalR “katanizada” o la propia WebApi). Recuerda la clave: cada componente podrá evolucionar a su propio ritmo y podrá ser sustuído por otro en cualquier momento. Olvídate de decir que “esta web es ASP.NET 3.5” y que todo el mundo sepa que es esto. Tu web serà una combinación de distintos módulos, cada uno con su propia versión. Desde NuGet seleccionarás cual de los módulos quieres usar (p.ej. un nuevo módulo de autenticación).

Y a futuro… extiende esta visión a todo el framework. Cierra los ojos e imagina que ya no hay un .NET Framework 6 ó 7 o el que toque y que en su lugar tu proyecto usará System.Collections en una versión y también System.Net y el entity framework que toque y nada más. Incluso, porque no, seleccionar que CLR (o CLRs) quieres atacar. Yo al menos lo veo así (aunque desde que predije el fracaso del iPad tengo claro que como pitoniso no me ganaré la vida).

OWIN

Antes he mencionado que Katana es (será) básicamente un conjunto de componentes OWIN y me he quedado tan ancho. Pero… ¿qué es básicamente OWIN? Pues inspirándose de nuevo en la comunidad de Ruby (en concreto en Rack) la comunidad de .NET ha creado una abstracción entre el servidor web y los componentes del framework que se use. La idea es que:

  1. Se puedan (y usar) crear nuevos componentes de forma sencilla y fácil
  2. Sea más sencillo portar aplicaciones entre hosts.

No entraré en detalles sobre OWIN ahora (lo dejo para un post siguiente) pero básicamente sus puntos clave son:

  1. El servidor Web OWIN es el encargado de rellenar los datos OWIN (environment según la especificación) a partir de la petición. A la práctica estos datos son un diccionario (IDictionary<string,object>). Las cadenas usadas como claves están definidas en la propia especificación de OWIN.
  2. Los componentes deben implementar el application delegate (AppFunc). Básicamente la idea es que los componentes reciben el diccionario anterior y devuelven una Task con la definición de la tarea a realizar.

Estos dos puntos parecen una chorrada, pero quédate con un par de ideas al respecto:

  • OWIN está diseñado con visos de ser asíncrono (de ahí que los componentes devuelvan un Task). La idea es parecida a la de nodejs: procesar asíncronamente aumenta el rendimiento en aquellas peticiones que básicamente dependen de E/S que son la mayoría.
  • Los componentes OWIN son encadenables de forma sencilla.

Conclusión

El modelo de un framework monolítico podía ser válido hace, pongamos, siete años, pero cada vez es necesario poder evolucionar más rápidamente.

Evolución rápida implica que sea al margen del .NET Framework. ASP.NET MVC abrió el camino y el proyecto Katana es la culminación de esa idea: tener todas las APIs y componentes de ASP.NET (y algunos más) pero sin dependencias contra System.Web.dll (y por lo tanto con el .NET Framework y con IIS). Para la implementación de Katana, Microsoft se ha apoyado en OWIN, una iniciativa de la comunidad .NET, que define una interfaz entre servidores web y frameworks de desarrollo web modulares.

En próximos posts iremos ampliando la información sobre OWIN y Katana.

Saludos!