viernes, 10 de octubre de 2014

PARTE 4 - Resolución de conflictos del merge

Link de emergencia (siempre buscar primero aquí cualquier error):

En el panel derecho del Blog tienen el índice de prácticas >>


En la PARTE 3 seguimos trabajando con ramas, pero esta vez haciendo merges de los cambios.

En esta parte veremos la resolución de algunos conflictos de un Merge.
Recuerden la Terminología común que hay que conocer

Las dudas preguntarlas en el hilo de la PARTE 4 en el foro.


Antes de continuar, leer el apartado "¿Qué son los conflictos de un Merge?" en el artículo sobre merge.

Si ya lo habían leído, denle una nueva lectura, ya que suelo actualizarlos con algunas explicaciones extra o incluso algún ejemplo más, y recuerden que ese artículo es orientativo y no debe tomarse como el paso a paso de este ejercicio.


También leer:

[Artículo] PlasticSCM: El merge sustractivo como reemplazo del borrado

[Artículo] PlasticSCM: Qué es el Cherry Pick y cómo se usa


Vamos a generar conflictos a propósito en el merge para aprender a resolverlos, equivocarnos, ejecutar y ver si todo sigue funcionando y volver a intentarlo.




A) INTEGRACIÓN DE OBJETOS


En esta parte vamos a agregar 2 controles, uno en cada rama de trabajo, simulando a un usuario distinto trabajando en el mismo componente, y luego mezclaremos los cambios.

Cada uno, en su rama de trabajo "usuario" hagan lo siguiente:

1.  Creen una nueva rama con su "usuario" + "2" (ej: fdbozzo2) desde la rama de tarea y pásense a ella. Ahora tendrán 2 ramas paralelas de trabajo: usuario (la que ya tenían) y usuario2 (la nueva).

2. Modifiquen su form agregando un botón cmdBoton_B y caption "Boton B" con un MESSAGEBOX("cmdBoton_B") en el evento click, y a continuación hagan checkin y el merge en la rama de tarea (no olvidar la vista texto). Este merge será automático.

3. Pásense a la otra rama de trabajo ("usuario") y agreguen un botón cmdBoton_A y caption "Boton A" con un MESSAGEBOX("cmdBoton_A") en el evento click, y a continuación hagan el merge en la rama de tarea. Aquí deberán mantener ambos cambios, y antes de hacer el checkin ejecuten el form para estar seguros de que funciona bien.

4. Sincronizar el repositorio



B) INTEGRACIÓN DE MÉTODOS


En esta parte vamos a simular un cambio de 2 usuarios en el mismo método, donde se quieren mantener ambos cambios.


1.  En vuestra rama de trabajo "usuario2" modificar el evento click de cmdBoton_B, agregar lo siguiente al final y luego hagan checkin de los cambios:

IF _SCREEN.StartMode = 1 THEN && CON ERROR PROVOCADO!
   MESSAGEBOX( "Modo Objeto" )
ENDIF

2. Pásense a vuestra otra rama de trabajo ("usuario") y en el evento click de cmdBoton_A, agregar lo siguiente al final y luego hagan checkin de los cambios

IF _VFP.StartMode = 0 THEN
   MESSAGEBOX( "Modo Desarrollo" )
ENDIF

3. Desde la misma rama "usuario", hagan el merge a la rama de la tarea (debería ser automático) y luego hacer el checkin.


4. Desde la rama "usuario2", hagan el merge a la rama de la tarea, donde deben quedar ambos cambios y luego hacer el checkin.


5. Probar el form: el boton A debería funcionar bien, el botón B debería dar un error (ignorarlo), finalmente sincronizar el repositorio




C) DESINTEGRACIÓN DE UNA RAMA


En esta parte vamos a simular una funcionalidad que se quiere quitar para resolver un error, por lo que vamos desintegrar los últimos cambios de vuestra rama usuario2 (el boton B), para que solo queden los de la rama usuario.


1.  Con la casa en la rama de tarea, elegir el intervalo necesario para desintergar los changesets de vuestra rama usuario2 (recordar cómo deshacer un grupo de changesets) y hacer un Merge Sustractivo del mismo. Esto creará un nuevo changeset en la rama tarea que excluirá los cambios de vuestra rama usuario2, o sea que deberá quedar el IF correspondiente a "Modo Desarrollo" de vuestra rama usuario. Seguramente requiera intervención manual para quitar todo lo relacionado el botón B que agregamos en la rama usuario2.



2. Luego de regenerar el binario, por haber hecho un merge, abran el form con VFP y verifiquen que funciona y que muestra el Botón A con el messagebox de Modo Desarrollo y no muestra el Botón B.

3. Si todo es correcto, hacer el checkin y sincronizar todo.




D) ARREGLO DEL ERROR EN LA RAMA DESINTERGADA


En esta parte vamos a arreglar el error provocado del botón de la rama desintegrada de antes.


1. En vuestra rama usuario2, abrir el form en el evento click de cmdBoton_B y cambiar _SCREEN por _VFP.

2. Probar el form y comprobar que el Botón B muestra un messagebox y ningún error

3. Si todo es correcto, hacer el checkin y sincronizar todo.



E) REINTEGRACIÓN DE CHANGESETS DESINTEGRADOS


En esta parte vamos a reintegrar el último changeset desintegrado y posteriormente arreglado.
Para reintegrar algo que se quitó con un merge sustractivo, es necesario usar el cherry pick, que es otro tipo de merge, e indicarle a Plastic que ignore el merge tracking.


1. Con la casa en la rama de tarea, elegir la rama de trabajo (no un changeset) donde se originó el merge sustractivo y elegir "Cherry Pick de esta rama", ignorando el merge tracking, como se explicó en artículo de Cherry Pick, aceptar y Recalcular el merge (el botón de al lado), ya que de otra forma, no mostrará archivos, porque ya habían sido quitados antes.




2. Al finalizar el merge, donde se reincorpora todo lo relativo al Botón B, no olviden rehacer los binarios

Nota: Al hacer el merge manual, es conveniente ordenar los procedimientos y objetos alfabéticamente (primero el Boton A y luego el B), para evitar futuras diferencias, ya que al regenerar luego el binario, si se hiciera nuevamente la versión texto, FoxBin2Prg haría ese ordenamiento y marcaría diferencias. No es imprescindible ni es una cambio funcional, sino sólo para evitar esas diferencias. Recordar que marcando/desmarcando los cambios con el título de la ventana de merge, se logra que un cambio pase de arriba a abajo (probarlo en ambos paneles para comprobarlo). Modificar el código manualmente en el panel inferior, debe ser siempre el último recurso a usar.

3. Si todo es correcto, hacer el checkin y sincronizar todo.

Listo, ya podrán comprobar los cambios de los últimos changesets, y lo que se ha agregado y quitado en cada uno, incluyendo el agregado final.



Para cuando terminen esta parte, ya sabrán:


- Integrar métodos de 2 o más ramas
- Integrar objetos de 2 o más ramas
- Resolver algunos conflictos manuales y automáticos en el merge de 2 o más ramas
- Desintegrar un changeset y una rama
- Volver a integrar un changeset o una rama con el Cherry Pick




Nos vemos en el foro! :D

domingo, 17 de agosto de 2014

PARTE 3- Merge

Link de emergencia (siempre buscar primero aquí cualquier error):

En el panel derecho del Blog tienen el índice de prácticas >>


En la PARTE 2 estuvimos trabajando con ramas, cada uno en la suya, haciendo un form, protegiendo los cambios (checkin) y viendo las diferencias (Diff).

En esta parte veremos el Merge (Mezcla o Integración de código) en detalle.
Recuerden la Terminología común que hay que conocer

Las dudas preguntarlas en el hilo de la PARTE 3 en el foro.


Simulación Real:


La práctica que haremos en este apartado es una simulación de la vida real del trabajo con ramas, donde yo haré el papel de Integrador principal para la rama /main de los desarrollos que ustedes hagan, y ustedes controlarán sus ramas de trabajo y de tarea particular.



Lectura:


Antes de que hagamos los ejercicios de Merge del final, es necesario leer lo siguiente:


[Artículo] - PlasticSCM: ¿Qué es el Merge?

[Artículo] - PlasticSCM: ¿Qué es el Shelve?

[Artículo] - PlasticSCM: Opciones de búsqueda y visualización de ramas y changesets



Ejercicios:


1. Shelve de los cambios


Hagan una modificación en vuestro formulario, luego ciérrenlo (y Clear All), vayan a la vista de Cambios Pendientes y refrésquenla (F5); van a ver los 2 archivos del form, regeneren las versiones texto de los archivos pendientes (verán 3 archivos), y finalmente en el menú del Checkin (flechita a la derecha) elijan Shelve y acepten (obviamente, en la lista verán sus archivos, no los míos):


También cierren el diálogo posterior de confirmación.

Vayan a la vista del Shelve, abran el panel lateral y agreguen un comentario sobre las modificaciones que acaban de guardar:






2. Deshacer archivos modificados "sin querer" :)


Vuelvan a la vista de Cambios Pendientes y deshagan los cambios de del sc2 y del sct "sin querer" :)   (click-derecho sobre los 2 archivos ya marcados -> Deshacer cambios)





Ok, imaginen que lo que acaban de hacer, realmente lo hicieron sin querer, porque se confundieron.

Una anécdota: hace poco me pasó que para una Integración de código de muchos archivos (unos 200), tenía que deshacer todos aquellos a los que no se les generaba el texto tx2 (que significa que no tuvo cambios el binario), por lo que los binarios sin tx2, los deshacía. Habiendo revisado más de 100 archivos y deshecho unos cuántos, en un descuido deshice un grupo de archivos que estaba al lado del que realmente debía deshacer.... como resultado, se invalidó toda la operación, y para peor, como estaba en el paso previo del checkin, los archivos que deshice no estaban en la BDD, por lo que perdí los cambios...



3. Restaurar el Shelve


...pero resulta que como sabía que iba a ser un trabajo propenso a errores, antes guardé todo en un Shelve, por lo que, lo único que tuve que hacer, fue deshacer todos los cambios y a continuación aplicar el Shelve para poder comenzar otra vez sin haber perdido nada más que algo de tiempo :)




Deshagan todos los cambios de la vista de Cambios Pendientes, apliquen el Shelve que guardaron y terminen de hacer el bendito checkin :)

Nota: El Shelve se puede usar para guardar cambios pendientes normales, no los cambios pendientes de un Merge, ya que no puede guardar el link de Merge.



4. Merge a vuestra rama de tarea


Deben hacer un Merge (no Cherry Pick!) desde vuestra rama de trabajo (/main/tarea-nnn/usuario) a la rama de la tarea (/main/tarea-nnn). Cuidado, la casa debe estar en la rama de la /tarea-nnn. No olvidar antes el Clear All / Close All en Fox, si lo tienen abierto, y que en la vista de Cambios Pendientes no debe haber nada (refrescarla con F5).



Y luego no olviden volver a poner la casa en la rama de trabajo, que la rama de tarea es solo para merge:



Nota: Si se preguntan cómo hice para mostrar mi rama sola, sin todo el resto, la respuesta es: prueben hacer click-derecho en la rama de la tarea-nnn (la rama, no un changeset!) -> Explorador de Ramas -> Mostrar las ramas seleccionadas y relacionadas en un nuevo diagrama



5. Replicación de vuestro repositorio local


Una vez hayan hecho el Merge en la tarea, sincronizan desde la vista de Sincronización de repositorios y me avisan, así Integro los cambios de la tarea-nnn de cada uno en la rama principal /main



6. Integración en la rama /main


Cuando yo tenga esos cambios integrados en mi repositorio local, les avisaré a cada uno para que puedan volver a sincronizar y obtener así los cambios integrados.




7. Nueva replicación de vuestro repositorio local




Sin con estas cortas instrucciones lo logran, ya van a tener terminada una pequeña práctica sobre sincronización de repositorios Plastic, que luego pueden usar con sus propios repositorios entre la PC de trabajo y otra en sus propias redes de casa o la oficina (aprovéchenlo, es un backup redundante y barato) :D

Cuando les confirme (a cada uno por separado) que el paso 6 está hecho para sus cambios, deben volver a sincronizar el repositorio de prácticas, y recién ahí podrán ver el resultado de mi integración local en la rama /main, con el trabajo de las tareas de todos.
 Mientras tanto pueden seguir haciendo cambios en sus forms en vuestra rama de trabajo, pero no sigan con los siguientes pasos hasta que les avise.



8. Nivelación de vuestra rama de tarea




Cuando todos tengan sus cosas Integradas en /main (y yo les haya confirmado a cada uno), entonces tendrán que hacer la nivelación de sus ramas de tarea (tarea-nnn) desde la rama /main (cuidado, la casa debe estar en la rama de la tarea-nnn).

Explicación:  Esta nivelación se hace para que vuestra rama de tarea se actualice con el trabajo de los demás que yo Integré en /main, por eso nivelan desde /main





9. Nivelación de vuestra rama de trabajo personal (usuario)


Aquí pueden haber 2 situaciones:


1) Que hayan seguido haciendo modificaciones de sus forms (imagen), en cuyo caso deberán:


    1.a) Hacer un merge de vuestra rama de trabajo (usuario) a la rama de tarea (tarea-nnn).
    Explicación: Esto se hace para que vuestra rama de tarea-nnn se actualice con el trabajo que ustedes siguieron haciendo mientras yo Integraba los cambios de todos




    1.b) Hacer un merge de nivelación de vuestra rama de tarea a la de trabajo (usuario)
    Explicación: Esto se hace para que vuestra rama de trabajo se actualice con el trabajo que integraron en (a) y con el trabajo de los demás que ustedes ya nivelaron en vuestra tarea-nnn.




    2) Que no hayan hech modificaciones al form y no tengan cambios pendientes (imagen), en cuyo caso deberán:



      Solamente hacer un merge de nivelación de vuestra rama de tarea a la de trabajo (usuario)
      Explicación: Esto se hace para que vuestra rama de trabajo se actualice con el trabajo de los demás que ustedes ya nivelaron en vuestra tarea-nnn.





      Para cuando terminen esta parte, ya sabrán:


      - Hacer merge para agregar los cambios hechos en una rama, a otra
      - Hacer merge para nivelar una rama desactualizada
      - Para qué sirve el Shelve
      - Manejarse con las opciones de búsqueda y visualización de ramas y changesets



      Nos vemos en el foro! :D

      sábado, 16 de agosto de 2014

      PARTE 2 - Ramas (Branches)

      Link de emergencia (siempre buscar primero aquí cualquier error):

      En el panel derecho del Blog tienen el índice de prácticas >>


      En esta parte veremos las Ramas (Branches en Inglés) en detalle, que el menos ya conocemos por la Terminología común que hay que conocer

      Las dudas preguntarlas en el hilo de la PARTE 2 en el foro.


      Aquí explico más en detalle cómo se trabaja con una rama
      Todavía no hagan ninguna, hasta que les indique más abajo luego de que lean el siguiente artículo:

      Bueno, ahora sí:
      Como habrán visto al sincronizar vuestro repositorio local Plastic con el repositorio público que comenté en la Parte 1 (punto 6 en adelante de la guía de replicación), hay muchas ramas nuevas que dejé preparadas con el nombre "tarea-nnn", donde preparé una rama de tarea para cada uno.

      Deberían ver algo como esto:



      Por las dudas vuelvan a sincronizar con GitHub, refresquen la vista con F5, y sigan atentamente los pasos a continuación.

      15/09/2014 - Por algunos problemas con GitHub, hemos cambiado de repositorio. Ver en la Parte 1 como configurarlo.

      De la rama de tarea que a cada uno le toque, según la lista que hay debajo, deberán crearse una sub-rama de trabajo cuyo nombre será vuestro nombre de usuario, así las identificamos más fácilmente, ya que deberán quedar de la forma /main/tarea-nnn/usuario.

      Como hay muchas ramas y muchas se solapan, es díficil elegir una desde la vista del Explorador de Ramas, por lo que se debe usar la vista de "Ramas" del panel izquierdo en modo texto para crear la rama de trabajo.

      La sub-rama que deben hacer se parecerá a la de la figura 5 del artículo anterior de ramas.

      Ramas de tareas preasignadas por usuario:

      - Allan Raúl Acuña (nicafox) - tarea-001
      - Manuel Tovar [mtovar] (mtovar1111) - tarea-002
      - Sergio Alejandro García Méndez (tayiogar) - tarea-002
      - Osornino (osornino) - tarea-003
      - Francisco Prieto (fajprieto) - tarea-004
      - Antonio Meza (antoniomeza) - tarea-005
      - Richard Silva (rsilvam) - tarea-006
      - Armando Rodriguez B. (armandomx) - tarea-007
      - Fidel Charny (fidelcharny) - tarea-008
      - Ricardo Pina (ricpina) - tarea-009
      - Irwin Rodriguez (Irwin1985) - tarea-010
      - Guru Christian (jwchristianlg) - tarea-011
      - Juan Miguel Solis (jmsolis) - tarea-012
      - Sergio Alejandro Garcia Mendez (tayiogar) - tarea-013
      - Viktor Velazquez (vivelas) - tarea-014
      - Miguel Angel (Advenmig) - tarea-015
      - Julian May (julianmd) - tarea-016
      - Elvis Mallqui Sauñe (mashaell) - tarea-017
      - Henry Herrera (hjherrera) - tarea-028
      - Eric Zbrun. (EricZbrun) - tarea-023
      - Luis Fernando Reyes.
      - Tomás Cruz [tomcrux].
      - Moisés Medina Paz. (mamp) - tarea-018
      - Narcizo Norzagaray [kyro].
      - Felix Rejopachi [farh].
      - Luis [Desarrollos AM] (luis101962) - tarea-019
      - Mauricio Pulla [mpulla] (mpulla) - tarea-020
      - Carlos Alfaro (calfagua) - tarea-021
      - Alex A. Vega [Alex Vargas] (AlexVargasVega) - tarea-022
      - César Pistiner (cpistiner) - tarea-024
      - Rodolfo Arias - tarea-029 (la tengo que crear)




      Una vez que tengan la rama creada (click-derecho -> "Crear rama hija...") y que hayan comprobado en la vista Ramas que quedó de esta forma: "/main/tarea-nnn/usuario" (debe quedar marcada en negritas, si no se le debe hacer click-derecho y elegir "Apuntar workspace a esta rama") y que en la vista del Explorador de ramas el icono de la casa está en la nueva rama creada, entonces ya pueden comenzar a trabajar, para lo que comenzaremos a un formulario.
      Lo de verificar las vistas de Ramas y Explorador de ramas es una doble verificación que haremos solo al principio, para evitar confusiones, ya que el no poder estar yo a vuestro lado mirando cómo lo hacen, no tengo otra forma de verificarlo.
      Si se encuentran algún problema, envíen captura de pantalla para podernos situar en contexto.

      Observen que en el workspace ya hay varios directorios y archivos existentes, que tomé de las prácticas de marzo.


      Solo recuerden 3 cosas:

      1. Las reglas mínimas de buenas prácticas, que nos evitará algunos problemas
      2. Haber probado el funcionamiento de FoxBin2Prg en solitario
      3. Crear solamente un formulario en el directorio forms que lleve vuestro usuario (por ejemplo: frm_irwin.scx), sin clases ni nada, pero puede incluir imágenes y usar los datos de Tastrade que vienen en Fox, en cuyo caso no copien las tablas, úsenlas directamente con algo como USE ( HOME(2)+"tastrade\data\customer.dbf" ) que a todos les funcionará. También lo pueden agregar al menú que hay disponible y al proyecto, así se puede invocar desde los mismos.

      Cuando tengan hecho el formulario con la funcionalidad que quieran, entonces pueden seguir leyendo los siguientes artículos para guardar vuestros cambios (checkin) en el control de código. (Recordar cerrar cualquier form, proyecto o clase que estén usando en el workspace y hacer CLEAR ALL / CLOSE ALL antes del checkin):

      - FoxPro 9: Creando un componente y añadiéndolo al control de código (Plastic)

      - FoxPro 9: Modificando un componente que ya está bajo control de código

      - PlasticSCM: Hice un checkin erróneo en un archivo, ¿cómo lo arreglo?

      - PlasticSCM: ¿Qué es el Diff?

      - PlasticSCM: ¿Para qué sirve el Annotate?


      Al finalizar lo anterior, si no hubo problemas y les quedó parecido a la imagen de abajo (podrían tener más changesets ustedes, si hicieron checkin más de una vez), hagan la sincronización, pero si hubo problemas, pregunten para resolverlos.


      Para cuando terminen esta parte, ya sabrán:


      - Cómo crear una rama
      - Cómo subir código normalizado al control de código, tanto cosas nuevas como modificaciones
      - Cómo hacer un Diff para ver las diferencias
      - Como usar el Annotate para ver quién y cuándo se cambio una línea o bloque de código

      Y deberían ver su rama de cambios parecida a esta (click para agrendar la imagen):





      PARTE 1 - Instalación de Plastic y conociendo FoxBin2Prg

      15/09/2014 - Actualizado con la nueva conexión a usar que sustituye a GitHub.



      Referencia del inicio de las prácticas. Antes de comenzar, lean esto si todavía no lo hicieron:

      [Artículo] - Control de versiones: ¿Para qué sirve? ¿Por qué es necesario?

      [Artículo] - Cómo configurar las notificaciones en los Grupos de Google de forma óptima

      [Artículo] - Control de código fuente: Terminología común que hay que conocer

      Para anotarse en las prácticas:
      [Foro] - Prácticas de VFP 9 con control de código fuente desde CERO - Preliminares

      En el panel derecho del Blog tienen el índice de prácticas >>


      Las dudas preguntarlas en el hilo de la PARTE 1 en el foro.


      INICIO

      Esta es la primera parte, donde vamos a instalar Plastic (el componente cliente y el componente servidor) en su configuración por defecto.

      Los pasos a seguir son los de la siguiente lista:

      [Artículo] - Descarga e Instalación de PlasticSCM paso a paso


      Si no te hiciste un usuario GitHub, hazlo aquí y luego envíamelo.
      El repositorio de GitHub a usar en el siguiente artículo, es este: https://github.com/fdbozzo/dvcs_vfp9.git

      [Artículo] - PlasticSCM: Sincronización con GitHub

      Actualización 15/09/2014 


      - Debido a algunos problemas con GitHub, el repositorio a usar ya no será ese, sino que será un repositorio Plastic público que monté temporalmente para estas prácticas en fdbozzo2.no-ip.org:8087 (ver más adelante).

      Para configurarlo, leer el siguiente artículo de cómo se configura la replicación, pero reemplazando los datos de conexión por lo indicado a continuación del artículo, y enviarme un correo particular para que les pueda crear un usuario de pruebas, ya que hay un límite de 15 usuarios:


      [Artículo] - PlasticSCM: Cómo configurar la replicación de repositorios Plastic locales y remotos


      Luego de leer el artículo de replicación, este es el resumen de pasos a seguir para configurar la replicación:



      FoxUnit repository:

      a) Crear un nuevo repositorio vacío llamado FoxUnit, apuntando a un nuevo directorio con el mismo nombre (por ejemplo, c:\desa\FoxUnit), ojo, que el directorio debe estar vacío!



      b) En el paso (3) de la guía de replicación, hay que elegir como origen el nuevo repositorio FoxUnit

      c) En el paso (4) de la guía de replicación, se debe crear la conexión destino con estos datos: fdbozzo2.no-ip.org:8087 (es la conexión sin SSL, que parece que es lo que da problemas y que no logro configurar)


      dvcs_vfp9 repository:

      d) En el paso (5) de la guía de replicación, les debería mostrar en la lista mi repositorio FoxUnit, que deben elegir e) Crear un nuevo repositorio vacío llamado dvcs_vfp9_red, apuntando a un nuevo directorio con el mismo nombre (por ejemplo, c:\desa\dvcs_vfp9_red), ojo, que el directorio debe estar vacío!


      f) En el paso (3) de la guía de replicación, hay que elegir como origen el nuevo repositorio dvcs_vfp9_red

      g) En el paso (4) de la guía de replicación, se debe crear la conexión destino con estos datos: fdbozzo2.no-ip.org:8087

      h) En el paso (5) de la guía de replicación, les debería mostrar en la lista mi repositorio dvcs_vfp9, que deben elegir






      i) El resto debería ser como explico en la guía de replicación.

      [Artículo] - FoxBin2Prg: Detalle de vistas, datos de uso, configuraciones y más

      [Artículo] - FoxBin2Prg: Guía rápida de uso y configuración


      Al finalizar esto, ya tendrán instalado el programa (puede que necesiten reiniciar la PC), conocerán las reglas de buenas prácticas que usaremos en las pruebas y también conocerán cómo funciona FoxBin2Prg, que es el conversor de binarios de VFP9 a texto y texto a binarios que usaremos. Este programa es independiente de Plastic, y se puede usar con cualquier SCM.


      Cada nueva PARTE la iré publicando en este Blog y en el foro, así nadie se pierde y lo puede consultar en cualquier momento sin revolver entre mensajes.

      Cuando todos tengan todo a punto y configurado, seguimos en la PARTE 2.

      Por favor, cuando tengan el repositorio sincronizado, no modifiquen ningún programa ni se lancen a hacer ramas todavía, que eso lo haremos en la próxima parte.

      Nos vemos en el foro! :D

      Soporte para las prácticas de control de código fuente en VFP 9 del foro

      16/08/2014

      Este nuevo Blog es exclusivamente para las prácticas de control de código fuente.

      La idea es que nadie se pierda entre los cientos de mensajes del foro y pueda seguir las prácticas desde aquí, y usar el foro para las preguntas.

      Dirección URL del foro Google de FoxPro:
      http://groups.google.com/group/publicesvfoxpro


      Fernando D. Bozzo