jerojasro@343: \chapter{Una gira de Mercurial: lo básico} jerojasro@343: \label{chap:tour-basic} jerojasro@343: jerojasro@343: \section{Instalar Mercurial en su sistema} jerojasro@343: \label{sec:tour:install} jerojasro@343: Hay paquetes binarios precompilados de Mercurial disponibles para cada jerojasro@343: sistema operativo popular. Esto hace fácil empezar a usar Mercurial jerojasro@343: en su computador inmediatamente. jerojasro@343: jerojasro@343: \subsection{Linux} jerojasro@343: jerojasro@343: Dado que cada distribución de Linux tiene sus propias herramientas de jerojasro@343: manejo de paquetes, políticas, y ritmos de desarrollo, es difícil dar jerojasro@343: un conjunto exhaustivo de instrucciones sobre cómo instalar el paquete jerojasro@343: de Mercurial. La versión de Mercurial que usted tenga a disposición jerojasro@343: puede variar dependiendo de qué tan activa sea la persona que mantiene jerojasro@343: el paquete para su distribución. jerojasro@343: jerojasro@343: Para mantener las cosas simples, me enfocaré en instalar Mercurial jerojasro@343: desde la línea de comandos en las distribuciones de Linux más jerojasro@343: populares. La mayoría de estas distribuciones proveen administradores jerojasro@343: de paquetes gráficos que le permitirán instalar Mercurial con un solo jerojasro@343: clic; el nombre de paquete a buscar es \texttt{mercurial}. jerojasro@343: jerojasro@343: \begin{itemize} jerojasro@343: \item[Debian] jerojasro@343: \begin{codesample4} jerojasro@343: apt-get install mercurial jerojasro@343: \end{codesample4} jerojasro@343: jerojasro@343: \item[Fedora Core] jerojasro@343: \begin{codesample4} jerojasro@343: yum install mercurial jerojasro@343: \end{codesample4} jerojasro@343: jerojasro@343: \item[Gentoo] jerojasro@343: \begin{codesample4} jerojasro@343: emerge mercurial jerojasro@343: \end{codesample4} jerojasro@343: jerojasro@343: \item[OpenSUSE] jerojasro@343: \begin{codesample4} jerojasro@343: yum install mercurial jerojasro@343: \end{codesample4} jerojasro@343: jerojasro@343: \item[Ubuntu] El paquete de Mercurial de Ubuntu está basado en el de jerojasro@343: Debian. Para instalarlo, ejecute el siguiente comando. jerojasro@343: \begin{codesample4} jerojasro@343: apt-get install mercurial jerojasro@343: \end{codesample4} jerojasro@343: El paquete de Mercurial para Ubuntu tiende a atrasarse con respecto jerojasro@343: a la versión de Debian por un margen de tiempo considerable jerojasro@343: (al momento de escribir esto, 7 meses), lo que en algunos casos jerojasro@343: significará que usted puede encontrarse con problemas que ya habrán jerojasro@343: sido resueltos en el paquete de Debian. jerojasro@343: \end{itemize} jerojasro@343: jerojasro@343: \subsection{Solaris} jerojasro@343: jerojasro@343: SunFreeWare, en \url{http://www.sunfreeware.com}, es una buena fuente jerojasro@343: para un gran número de paquetes compilados para Solaris para las jerojasro@343: arquitecturas Intel y Sparc de 32 y 64 bits, incluyendo versiones jerojasro@343: actuales de Mercurial. jerojasro@343: jerojasro@343: \subsection{Mac OS X} jerojasro@343: jerojasro@343: Lee Cantey publica un instalador de Mercurial para Mac OS~X en jerojasro@343: \url{http://mercurial.berkwood.com}. Este paquete funciona en tanto jerojasro@343: en Macs basados en Intel como basados en PowerPC. Antes de que pueda jerojasro@343: usarlo, usted debe instalar una versión compatible de Universal jerojasro@343: MacPython~\cite{web:macpython}. Esto es fácil de hacer; simplemente jerojasro@501: siga las instrucciones del sitio de Lee. jerojasro@343: jerojasro@343: También es posible instalar Mercurial usando Fink o MacPorts, dos jerojasro@343: administradores de paquetes gratuitos y populares para Mac OS X. Si jerojasro@343: usted tiene Fink, use \command{sudo apt-get install mercurial-py25}. jerojasro@343: Si usa MacPorts, \command{sudo port install mercurial}. jerojasro@343: jerojasro@343: \subsection{Windows} jerojasro@343: jerojasro@343: Lee Cantey publica un instalador de Mercurial para Windows en jerojasro@343: \url{http://mercurial.berkwood.com}. Este paquete no tiene jerojasro@343: % TODO traducción de it just works. Agreed? jerojasro@343: dependencias externas; ``simplemente funciona''. jerojasro@343: jerojasro@343: \begin{note} jerojasro@343: La versión de Windows de Mercurial no convierte automáticamente jerojasro@343: los fines de línea entre estilos Windows y Unix. Si usted desea jerojasro@343: compartir trabajo con usuarios de Unix, deberá hacer un trabajo jerojasro@343: adicional de configuración. XXX Terminar esto. jerojasro@343: \end{note} jerojasro@343: jerojasro@343: \section{Arrancando} jerojasro@343: jerojasro@343: Para empezar, usaremos el comando \hgcmd{version} para revisar si jerojasro@343: Mercurial está instalado adecuadamente. La información de la versión jerojasro@343: que es impresa no es tan importante; lo que nos importa es si imprime jerojasro@343: algo en absoluto. jerojasro@343: jerojasro@343: \interaction{tour.version} jerojasro@343: jerojasro@343: % TODO builtin-> integrado? jerojasro@343: \subsection{Ayuda integrada} jerojasro@343: jerojasro@343: Mercurial provee un sistema de ayuda integrada. Esto es invaluable jerojasro@343: para ésas ocasiones en la que usted está atorado tratando de recordar jerojasro@343: cómo ejecutar un comando. Si está completamente atorado, simplemente jerojasro@343: ejecute \hgcmd{help}; esto imprimirá una breve lista de comandos, jerojasro@343: junto con una descripción de qué hace cada uno. Si usted solicita jerojasro@343: ayuda sobre un comando específico (como abajo), se imprime información jerojasro@343: más detallada. jerojasro@343: \interaction{tour.help} jerojasro@343: Para un nivel más impresionante de detalle (que usted no va a jerojasro@343: necesitar usualmente) ejecute \hgcmdargs{help}{\hggopt{-v}}. La opción jerojasro@343: \hggopt{-v} es la abreviación para \hggopt{--verbose}, y le indica a jerojasro@343: Mercurial que imprima más información de lo que haría usualmente. jerojasro@343: jerojasro@352: \section{Trabajar con un repositorio} jerojasro@352: jerojasro@352: En Mercurial, todo sucede dentro de un \emph{repositorio}. El jerojasro@362: repositorio para un proyecto contiene todos los ficheros que jerojasro@352: ``pertenecen a'' ése proyecto, junto con un registro histórico de los jerojasro@362: ficheros de ese proyecto. jerojasro@352: jerojasro@352: No hay nada particularmente mágico acerca de un repositorio; es jerojasro@362: simplemente un árbol de directorios en su sistema de ficheros que jerojasro@352: Mercurial trata como especial. Usted puede renombrar o borrar un jerojasro@352: repositorio en el momento que lo desee, usando bien sea la línea de jerojasro@352: comandos o su explorador de ficheros. jerojasro@352: jerojasro@352: \subsection{Hacer una copia local de un repositorio} jerojasro@352: jerojasro@352: \emph{Copiar} un repositorio es sólo ligeramente especial. Aunque jerojasro@362: usted podría usar un programa normal de copia de ficheros para hacer jerojasro@352: una copia del repositorio, es mejor usar el comando integrado que jerojasro@352: Mercurial ofrece. Este comando se llama \hgcmd{clone}\ndt{Del término jerojasro@352: ``clonar'' en inglés.}, porque crea una copia idéntica de un jerojasro@352: repositorio existente. jerojasro@343: \interaction{tour.clone} jerojasro@352: Si nuestro clonado tiene éxito, deberíamos tener un directorio local jerojasro@362: llamado \dirname{hello}. Este directorio contendrá algunos ficheros. jerojasro@343: \interaction{tour.ls} jerojasro@362: Estos ficheros tienen el mismo contenido e historial en nuestro jerojasro@352: repositorio y en el repositorio que clonamos. jerojasro@352: jerojasro@352: Cada repositorio Mercurial está completo, es autocontenido e jerojasro@516: independiente. Contiene su propia copia de los ficheros y el historial jerojasro@352: de un proyecto. Un repositorio clonado recuerda la ubicación de la que jerojasro@352: fue clonado, pero no se comunica con ese repositorio, ni con ningún jerojasro@352: otro, a menos que usted le indique que lo haga. jerojasro@352: jerojasro@352: Lo que esto significa por ahora es que somos libres de experimentar jerojasro@355: con nuestro repositorio, con la tranquilidad de saber que es una jerojasro@355: % TODO figure out what to say instead of sandbox jerojasro@355: ``caja de arena'' privada que no afectará a nadie más. jerojasro@355: jerojasro@355: \subsection{Qué hay en un repositorio?} jerojasro@355: jerojasro@355: Cuando miramos en detalle dentro de un repositorio, podemos ver que jerojasro@355: contiene un directorio llamado \dirname{.hg}. Aquí es donde Mercurial jerojasro@355: mantiene todos los metadatos del repositorio. jerojasro@343: \interaction{tour.ls-a} jerojasro@343: jerojasro@355: Los contenidos del directorio \dirname{.hg} y sus subdirectorios son jerojasro@355: exclusivos de Mercurial. Usted es libre de hacer lo que desee con jerojasro@362: cualquier otro fichero o directorio en el repositorio. jerojasro@343: jerojasro@357: Para introducir algo de terminología, el directorio \dirname{.hg} es jerojasro@362: el repositorio ``real'', y todos los ficheros y directorios que jerojasro@357: coexisten con él están en el \emph{directorio de trabajo}. Una forma jerojasro@357: sencilla de recordar esta distinción es que el \emph{repositorio} jerojasro@357: contiene el \emph{historial} de su proyecto, mientras que el jerojasro@357: \emph{directorio de trabajo} contiene una \emph{instantánea} de su jerojasro@357: proyecto en un punto particular del historial. jerojasro@357: jerojasro@357: \section{Vistazo rápido al historial} jerojasro@357: jerojasro@357: Una de las primeras cosas que se desea hacer con un repositorio nuevo, jerojasro@501: poco conocido, es conocer su historial. El comando \hgcmd{log} nos jerojasro@357: permite ver el mismo. jerojasro@343: \interaction{tour.log} jerojasro@358: Por defecto este programa imprime un párrafo breve por cada cambio al jerojasro@358: proyecto que haya sido grabado. Dentro de la terminología de jerojasro@501: Mercurial, cada uno de estos eventos es llamado \emph{conjunto de jerojasro@358: cambios}, porque pueden contener un registro de cambios a varios jerojasro@362: ficheros. jerojasro@358: jerojasro@358: Los campos de la salida de \hgcmd{log} son los siguientes. jerojasro@343: \begin{itemize} jerojasro@358: \item[\texttt{changeset}]\hspace{-0.5em}\ndt{Conjunto de cambios.} Este campo jerojasro@358: tiene un número, seguido por un jerojasro@358: % TODO digo mejor seguido por un dos puntos ? string => jerojasro@358: % cadena? jerojasro@358: \texttt{:}, seguido por una cadena hexadecimal. Ambos son jerojasro@358: \emph{identificadores} para el conjunto de cambios. Hay dos jerojasro@358: identificadores porque el número es más corto y más fácil de jerojasro@358: recordar que la cadena hexadecimal. jerojasro@358: jerojasro@358: \item[\texttt{user}]\hspace{-0.5em}\ndt{Usuario.} La identidad de la jerojasro@358: persona que creó el conjunto de cambios. Este es un campo en el jerojasro@358: que se puede almacenar cualquier valor, pero en la mayoría de los jerojasro@358: casos contiene el nombre de una persona y su dirección de correo jerojasro@358: electrónico. jerojasro@358: jerojasro@362: \item[\texttt{date}]\hspace{-0.5em}\ndt{Fecha.} La fecha y hora en la jerojasro@362: que el conjunto de cambios fue creado, y la zona horaria en la que jerojasro@362: fue creado. (La fecha y hora son locales a dicha zona horaria; jerojasro@362: ambos muestran la fecha y hora para la persona que creó el jerojasro@501: conjunto de cambios). jerojasro@362: jerojasro@362: \item[\texttt{summary}]\hspace{-0.5em}\ndt{Sumario.} jerojasro@362: La primera línea del texto que usó la persona que creó el conjunto jerojasro@362: de cambios para describir el mismo. jerojasro@343: \end{itemize} jerojasro@362: El texto impreso por \hgcmd{log} es sólo un sumario; omite una gran jerojasro@362: cantidad de detalles. jerojasro@362: jerojasro@362: La figura~\ref{fig:tour-basic:history} es una representación jerojasro@362: gráfica del historial del repositorio \dirname{hello}, para hacer más jerojasro@362: fácil ver en qué dirección está ``fluyendo'' el historial. Volveremos jerojasro@362: a esto varias veces en este capítulo y en los siguientes. jerojasro@343: jerojasro@343: \begin{figure}[ht] jerojasro@343: \centering jerojasro@343: \grafix{tour-history} jerojasro@501: \caption{Historial gráfico del repositorio \dirname{hello}} jerojasro@343: \label{fig:tour-basic:history} jerojasro@343: \end{figure} jerojasro@343: jerojasro@362: \subsection{Conjuntos de cambios, revisiones, y comunicándose con jerojasro@362: otras personas} jerojasro@362: jerojasro@362: %TODO sloppy => desordenado ? TODO hablar del inglés? o de español? jerojasro@362: Ya que el inglés es un lenguaje notablemente desordenado, y el área de jerojasro@362: ciencias de la computación tiene una notable historia de confusión de jerojasro@362: % TODO insertar ? al revés. no sé cómo en un teclado de estos. jerojasro@362: términos (porqué usar sólo un término cuando cuatro pueden servir?), jerojasro@362: el control de revisiones tiene una variedad de frases y palabras que jerojasro@362: tienen el mismo significado. Si usted habla acerca del historial de jerojasro@362: Mercurial con alguien, encontrará que la expresión ``conjunto de jerojasro@362: cambios'' es abreviada a menudo como ``cambio'' o (por escrito) jerojasro@362: ``cset''\ndt{Abreviatura para la expresión ``changeset'' en inglés.}, jerojasro@362: y algunas veces un se hace referencia a un conjunto de cambios como jerojasro@362: una ``revisión'' o ``rev''\ndt{De nuevo, como abreviación para el jerojasro@362: término en inglés para ``revisión'' (``revision'').}. jerojasro@362: jerojasro@362: Si bien no es relevante qué \emph{palabra} use usted para referirse al jerojasro@362: concepto ``conjunto de cambios'', el \emph{identificador} que usted jerojasro@362: use para referise a ``un \emph{conjunto de cambios} particular'' es jerojasro@362: muy importante. Recuerde que el campo \texttt{changeset} en la salida jerojasro@362: de \hgcmd{log} identifica un conjunto de cambios usando tanto un jerojasro@362: número como una cadena hexadecimal. jerojasro@362: jerojasro@343: \begin{itemize} jerojasro@362: \item El número de revisión \emph{sólo es válido dentro del jerojasro@362: repositorio}. jerojasro@362: \item Por otro lado, la cadena hexadecimal es el jerojasro@362: \emph{identificador permanente e inmutable} que siempre jerojasro@362: identificará ése conjunto de cambios en \emph{todas} las jerojasro@362: copias del repositorio. jerojasro@343: \end{itemize} jerojasro@362: La diferencia es importante. Si usted le envía a alguien un correo jerojasro@362: electrónico hablando acerca de la ``revisión~33'', hay una jerojasro@362: probabilidad alta de que la revisión~33 de esa persona \emph{no sea la jerojasro@501: misma suya}. Esto sucede porque el número de revisión depende del jerojasro@362: orden en que llegan los cambios al repositorio, y no hay ninguna jerojasro@362: garantía de que los mismos cambios llegarán en el mismo orden en jerojasro@362: diferentes repositorios. Tres cambios dados $a,b,c$ pueden aparecer en jerojasro@362: un repositorio como $0,1,2$, mientras que en otro aparecen como jerojasro@362: $1,0,2$. jerojasro@362: jerojasro@362: Mercurial usa los números de revisión simplemente como una abreviación jerojasro@362: conveniente. Si usted necesita hablar con alguien acerca de un jerojasro@362: conjunto de cambios, o llevar el registro de un conjunto de cambios jerojasro@362: por alguna otra razón (por ejemplo, en un reporte de fallo), use el jerojasro@362: identificador hexadecimal. jerojasro@343: jerojasro@363: \subsection{Ver revisiones específicas} jerojasro@363: jerojasro@363: Para reducir la salida de \hgcmd{log} a una sola revisión, use la jerojasro@363: opción \hgopt{log}{-r} (o \hgopt{log}{--rev}). Puede usar un número jerojasro@363: de revisión o un identificador hexadecimal de conjunto de cambios, y jerojasro@363: puede pasar tantas revisiones como desee. jerojasro@363: jerojasro@363: \interaction{tour.log-r} jerojasro@363: jerojasro@363: Si desea ver el historial de varias revisiones sin tener que mencionar jerojasro@363: cada una de ellas, puede usar la \emph{notación de rango}; esto le jerojasro@363: permite expresar el concepto ``quiero ver todas las revisiones entre jerojasro@363: $a$ y $b$, inclusive''. jerojasro@343: \interaction{tour.log.range} jerojasro@363: Mercurial también respeta el orden en que usted especifica las jerojasro@363: revisiones, así que \hgcmdargs{log}{-r 2:4} muestra $2,3,4$ mientras jerojasro@363: que \hgcmdargs{log}{-r 4:2} muestra $4,3,2$. jerojasro@363: jerojasro@363: \subsection{Información más detallada} jerojasro@363: Aunque la información presentada por \hgcmd{log} es útil si usted sabe jerojasro@363: de antemano qué está buscando, puede que necesite ver una descripción jerojasro@501: completa del cambio, o una lista de los ficheros que cambiaron, si jerojasro@363: está tratando de averiguar si un conjunto de cambios dado es el que jerojasro@363: usted está buscando. La opción \hggopt{-v} (or \hggopt{--verbose}) del jerojasro@363: comando \hgcmd{log} le da este nivel extra de detalle. jerojasro@343: \interaction{tour.log-v} jerojasro@343: jerojasro@363: Si desea ver tanto la descripción como el contenido de un cambio, jerojasro@363: añada la opción \hgopt{log}{-p} (o \hgopt{log}{--patch}). Esto muestra jerojasro@363: % TODO qué hacemos con diff unificado? convervarlo, por ser la jerojasro@363: % acepción usual? jerojasro@363: el contenido de un cambio como un \emph{diff unificado} (si usted jerojasro@363: nunca ha visto un diff unificado antes, vea la jerojasro@363: sección~\ref{sec:mq:patch} para un vistazo global). jerojasro@343: \interaction{tour.log-vp} jerojasro@343: jerojasro@364: \section{Todo acerca de las opciones para comandos} jerojasro@364: jerojasro@364: Tomemos un breve descanso de la tarea de explorar los comandos de jerojasro@365: Mercurial para hablar de un patrón en la manera en que trabajan; será jerojasro@364: útil tener esto en mente a medida que avanza nuestra gira. jerojasro@364: jerojasro@365: Mercurial tiene un enfoque directo y consistente en el manejo de las jerojasro@364: opciones que usted le puede pasar a los comandos. Se siguen las jerojasro@364: convenciones para opciones que son comunes en sistemas Linux y Unix jerojasro@364: modernos. jerojasro@343: \begin{itemize} jerojasro@364: \item Cada opción tiene un nombre largo. Por ejemplo, el comando jerojasro@364: \hgcmd{log} acepta la opción \hgopt{log}{--rev}, como ya hemos jerojasro@364: visto. jerojasro@364: \item Muchas opciones tienen también un nombre corto. En vez de jerojasro@364: \hgopt{log}{--rev}, podemos usar \hgopt{log}{-r}. (El motivo para jerojasro@364: que algunas opciones no tengan nombres cortos es que dichas jerojasro@364: opciones se usan rara vez.) jerojasro@364: \item Las opciones largas empiezan con dos guiones (p.ej.~\hgopt{log}{--rev}), jerojasro@364: mientras que las opciones cortas empiezan con uno (e.g.~\hgopt{log}{-r}). jerojasro@364: \item El nombre y uso de las opciones es consistente en todos los jerojasro@364: comandos. Por ejemplo, cada comando que le permite pasar un ID de jerojasro@364: conjunto de cambios o un número de revisión acepta tanto la opción jerojasro@364: \hgopt{log}{-r} como la \hgopt{log}{--rev}. jerojasro@343: \end{itemize} jerojasro@364: En los ejemplos en este libro, uso las opciones cortas en vez de las jerojasro@364: largas. Esto sólo muestra mis preferencias, así que no le dé jerojasro@364: significado especial a eso. jerojasro@364: jerojasro@364: Muchos de los comandos que generan salida de algún tipo mostrarán más jerojasro@364: salida cuando se les pase la opción \hggopt{-v} (o jerojasro@364: \hggopt{--verbose}\ndt{Prolijo.}), y menos cuando se les pase la opción \hggopt{-q} jerojasro@364: (o \hggopt{--quiet}\ndt{Silencioso.}). jerojasro@343: jerojasro@366: \section{Hacer y repasar cambios} jerojasro@366: jerojasro@366: Ahora que tenemos una comprensión adecuada sobre cómo revisar el jerojasro@366: historial en Mercurial, hagamos algunos cambios y veamos cómo jerojasro@366: examinarlos. jerojasro@366: jerojasro@366: Lo primero que haremos será aislar nuestro experimento en un jerojasro@366: repositorio propio. Usaremos el comando \hgcmd{clone}, pero no hace jerojasro@501: falta clonar una copia del repositorio remoto. Como ya contamos con jerojasro@366: una copia local del mismo, podemos clonar esa. Esto es mucho más jerojasro@366: rápido que clonar a través de la red, y en la mayoría de los casos jerojasro@366: clonar un repositorio local usa menos espacio en disco también. jerojasro@343: \interaction{tour.reclone} jerojasro@368: A manera de recomendación, es considerado buena práctica mantener una jerojasro@368: copia ``prístina'' de un repositorio remoto a mano, del cual usted jerojasro@368: puede hacer clones temporales para crear cajas de arena para cada jerojasro@368: tarea en la que desee trabajar. Esto le permite trabajar en múltiples jerojasro@368: tareas en paralelo, teniendo cada una de ellas aislada de las otras jerojasro@368: hasta que estén completas y usted esté listo para integrar los cambios jerojasro@368: de vuelta. Como los clones locales son tan baratos, clonar y destruir jerojasro@368: repositorios no consume demasiados recursos, lo que facilita hacerlo jerojasro@368: en cualquier momento. jerojasro@368: jerojasro@371: En nuestro repositorio \dirname{my-hello}, hay un fichero jerojasro@368: \filename{hello.c} que contiene el clásico programa ``hello, jerojasro@368: world''\ndt{Hola, mundo.}. Usaremos el clásico y venerado comando jerojasro@371: \command{sed} para editar este fichero y hacer que imprima una segunda jerojasro@368: línea de salida. (Estoy usando el comando \command{sed} para hacer jerojasro@368: esto sólo porque es fácil escribir un ejemplo automatizado con él. jerojasro@368: Dado que usted no tiene esta restricción, probablemente no querrá usar jerojasro@368: \command{sed}; use su editor de texto preferido para hacer lo mismo). jerojasro@343: \interaction{tour.sed} jerojasro@343: jerojasro@368: El comando \hgcmd{status} de Mercurial nos dice lo que Mercurial sabe jerojasro@371: acerca de los ficheros en el repositorio. jerojasro@343: \interaction{tour.status} jerojasro@371: El comando \hgcmd{status} no imprime nada para algunos ficheros, sólo jerojasro@368: una línea empezando con ``\texttt{M}'' para el fichero jerojasro@368: \filename{hello.c}. A menos que usted lo indique explícitamente, jerojasro@371: \hgcmd{status} no imprimirá nada respecto a los ficheros que no han jerojasro@368: sido modificados. jerojasro@368: jerojasro@368: La ``\texttt{M}'' indica que Mercurial se dio cuenta de que nosotros jerojasro@368: modificamos \filename{hello.c}. No tuvimos que \emph{decirle} a jerojasro@371: Mercurial que íbamos a modificar ese fichero antes de hacerlo, o que jerojasro@368: lo modificamos una vez terminamos de hacerlo; él fue capaz de darse jerojasro@368: cuenta de esto por sí mismo. jerojasro@368: jerojasro@371: Es algo útil saber que hemos modificado el fichero \filename{hello.c}, jerojasro@368: pero preferiríamos saber exactamente \emph{qué} cambios hicimos. jerojasro@368: Para averiguar esto, usamos el comando \hgcmd{diff}. jerojasro@343: \interaction{tour.diff} jerojasro@343: jerojasro@371: \section{Grabar cambios en un nuevo conjunto de cambios} jerojasro@371: jerojasro@371: Podemos modificar, compilar y probar nuestros cambios, y usar jerojasro@371: \hgcmd{status} y \hgcmd{diff} para revisar los mismos, hasta que jerojasro@371: estemos satisfechos con los resultados y lleguemos a un momento en el jerojasro@371: que sea natural que querramos guardar nuestro trabajo en un nuevo jerojasro@371: conjunto de cambios. jerojasro@371: jerojasro@371: El comando \hgcmd{commit} nos permite crear un nuevo conjunto de jerojasro@371: cambios. Nos referiremos usualmente a esto como ``hacer una consigna'' jerojasro@371: o consignar. jerojasro@371: jerojasro@371: \subsection{Definir un nombre de usuario} jerojasro@371: jerojasro@371: Cuando usted trata de ejecutar \hgcmd{commit}\ndt{Hacer una jerojasro@371: consignación} por primera vez, no está garantizado que lo logre. jerojasro@371: Mercurial registra su nombre y dirección en cada cambio que usted jerojasro@371: consigna, para que más adelante otros puedan saber quién es el jerojasro@371: responsable de cada cambio. Mercurial trata de encontrar un nombre de jerojasro@371: % TODO consigna o consignación? jerojasro@371: usuario adecuado con el cual registrar la consignación. Se intenta con jerojasro@371: cada uno de los siguientes métodos, en el orden presentado. jerojasro@343: \begin{enumerate} jerojasro@371: \item Si usted pasa la opción \hgopt{commit}{-u} al comando \hgcmd{commit} jerojasro@371: en la línea de comandos, seguido de un nombre de usuario, se le da a jerojasro@371: esto la máxima precedencia. jerojasro@371: \item A continuación se revisa si usted ha definido la variable de jerojasro@371: entorno \envar{HGUSER}. jerojasro@371: \item Si usted crea un fichero en su directorio personal llamado jerojasro@371: \sfilename{.hgrc}, con una entrada \rcitem{ui}{username}, se usa jerojasro@371: luego. Para revisar cómo debe verse este fichero, refiérase a la jerojasro@371: sección~\ref{sec:tour-basic:username} más abajo. jerojasro@371: \item Si usted ha definido la variable de entorno \envar{EMAIL}, será jerojasro@371: usada a continuación. jerojasro@371: \item Mercurial le pedirá a su sistema buscar su nombre de usuario jerojasro@371: % TODO host => máquina jerojasro@371: local, y el nombre de máquina, y construirá un nombre de usuario a jerojasro@371: partir de estos componentes. Ya que esto generalmente termina jerojasro@371: generando un nombre de usuario no muy útil, se imprimirá una jerojasro@371: advertencia si es necesario hacerlo. jerojasro@343: \end{enumerate} jerojasro@371: Si todos estos procedimientos fallan, Mercurial fallará, e imprimirá jerojasro@371: un mensaje de error. En este caso, no le permitirá hacer la jerojasro@371: consignación hasta que usted defina un nombre de usuario. jerojasro@371: jerojasro@371: Trate de ver la variable de entorno \envar{HGUSER} y la opción jerojasro@371: \hgopt{commit}{-u} del comando \hgcmd{commit} como formas de jerojasro@371: \emph{hacer caso omiso} de la selección de nombre de usuario que jerojasro@371: Mercurial hace normalmente. Para uso normal, la manera más simple y jerojasro@371: sencilla de definir un nombre de usuario para usted es crear un jerojasro@371: fichero \sfilename{.hgrc}; los detalles se encuentran más adelante. jerojasro@371: jerojasro@371: \subsubsection{Crear el fichero de configuración de Mercurial} jerojasro@343: \label{sec:tour-basic:username} jerojasro@343: jerojasro@371: Para definir un nombre de usuario, use su editor de texto favorito jerojasro@371: para crear un fichero llamado \sfilename{.hgrc} en su directorio jerojasro@371: personal. Mercurial usará este fichero para obtener las jerojasro@371: configuraciones personalizadas que usted haya hecho. El contenido jerojasro@371: inicial de su fichero \sfilename{.hgrc} debería verse así. jerojasro@343: \begin{codesample2} jerojasro@371: # Este es un fichero de configuración de Mercurial. jerojasro@343: [ui] jerojasro@371: username = Primernombre Apellido jerojasro@343: \end{codesample2} jerojasro@371: La línea ``\texttt{[ui]}'' define una \emph{section} del fichero de jerojasro@371: configuración, así que usted puede leer la línea ``\texttt{username = jerojasro@371: ...}'' como ``defina el valor del elemento \texttt{username} en la jerojasro@371: sección \texttt{ui}''. jerojasro@371: Una sección continua hasta que empieza otra nueva, o se llega al final jerojasro@371: del fichero. Mercurial ignora las líneas vacías y considera cualquier jerojasro@371: texto desde el caracter ``\texttt{\#}'' hasta el final de la línea jerojasro@371: como un comentario. jerojasro@371: jerojasro@371: \subsubsection{Escoger un nombre de usuario} jerojasro@371: jerojasro@371: Usted puede usar el texto que desee como el valor del campo de jerojasro@371: configuración \texttt{username}, ya que esta información será leída jerojasro@371: por otras personas, e interpretada por Mercurial. La convención que jerojasro@371: sigue la mayoría de la gente es usar su nombre y dirección de correo, jerojasro@371: como en el ejemplo anterior. jerojasro@343: jerojasro@343: \begin{note} jerojasro@371: % TODO web jerojasro@371: El servidor web integrado de Mercurial ofusca las direcciones de jerojasro@371: correo, para dificultar la tarea de las herramientas de jerojasro@371: recolección de direcciones de correo que usan los jerojasro@371: spammers\ndt{Personas que envían correo no solicitado, también jerojasro@371: conocido como correo basura}. Esto reduce la probabilidad de que jerojasro@371: usted empiece a recibir más correo basura si publica un jerojasro@371: repositorio en la red. jerojasro@343: \end{note} jerojasro@343: jerojasro@371: \subsection{Escribir un mensaje de consignación} jerojasro@371: jerojasro@371: Cuando consignamos un cambio, Mercurial nos ubica dentro de un editor jerojasro@371: de texto, para ingresar un mensaje que describa las modificaciones que jerojasro@371: hemos introducido en este conjunto de cambios. Esto es conocido como jerojasro@371: un \emph{mensaje de consignación}. Será un registro de lo que hicimos jerojasro@371: y porqué lo hicimos, y será impreso por \hgcmd{log} una vez hayamos jerojasro@371: hecho la consignación. jerojasro@343: \interaction{tour.commit} jerojasro@343: jerojasro@371: El editor en que \hgcmd{commit} nos ubica contendrá una línea vacía, jerojasro@371: seguida de varias líneas que empiezan con la cadena ``\texttt{HG:}''. jerojasro@343: \begin{codesample2} jerojasro@371: \emph{línea vacía} jerojasro@343: HG: changed hello.c jerojasro@343: \end{codesample2} jerojasro@371: Mercurial ignora las líneas que empiezan con ``\texttt{HG:}''; sólo jerojasro@371: las usa para indicarnos para cuáles ficheros está registrando los jerojasro@371: cambios. Modificar o borrar estas líneas no tiene ningún efecto. jerojasro@371: jerojasro@371: \subsection{Escribir un buen mensaje de consignación} jerojasro@371: jerojasro@371: Ya que por defecto \hgcmd{log} sólo muestra la primera línea de un jerojasro@371: mensaje de consignación, lo mejor es escribir un mensaje cuya primera jerojasro@371: línea tenga significado por sí misma. A continuación se encuentra un jerojasro@371: ejemplo de un mensaje de consignación que \emph{no} sigue esta jerojasro@371: pauta, y debido a ello tiene un sumario que no es legible. jerojasro@343: \begin{codesample2} jerojasro@343: changeset: 73:584af0e231be jerojasro@371: user: Persona Censurada jerojasro@343: date: Tue Sep 26 21:37:07 2006 -0700 jerojasro@371: summary: se incluye buildmeister/commondefs. Añade un módulo jerojasro@343: \end{codesample2} jerojasro@343: jerojasro@371: Con respecto al resto del contenido del mensaje de consignación, no jerojasro@371: hay reglas estrictas-y-rápidas. Mercurial no interpreta ni le da jerojasro@371: importancia a los contenidos del mensaje de consignación, aunque es jerojasro@371: posible que su proyecto tenga políticas que definan una manera jerojasro@371: particular de escribirlo. jerojasro@371: jerojasro@371: Mi preferencia personal es usar mensajes de consignación cortos pero jerojasro@371: informativos, que me digan algo que no puedo inferir con una mirada jerojasro@371: rápida a la salida de \hgcmdargs{log}{--patch}. jerojasro@371: jerojasro@371: \subsection{Cancelar una consignación} jerojasro@371: jerojasro@371: Si usted decide que no desea hacer la consignación mientras está jerojasro@371: editando el mensaje de la misma, simplemente cierre su editor sin jerojasro@371: guardar los cambios al fichero que está editando. Esto hará que no jerojasro@371: pase nada ni en el repositorio ni en el directorio de trabajo. jerojasro@371: jerojasro@371: Si ejecutamos el comando \hgcmd{commit} sin ningún argumento, se jerojasro@371: registran todos los cambios que hemos hecho, como lo indican jerojasro@371: \hgcmd{status} y \hgcmd{diff}. jerojasro@371: jerojasro@371: \subsection{Admirar nuestro trabajo} jerojasro@371: jerojasro@371: Una vez hemos terminado la consignación, podemos usar el comando jerojasro@371: \hgcmd{tip}\ndt{Punta.} para mostrar el conjunto de cambios que acabamos de crear. jerojasro@371: La salida de este comando es idéntica a la de \hgcmd{log}, pero sólo jerojasro@371: muestra la revisión más reciente en el repositorio. jerojasro@343: \interaction{tour.tip} jerojasro@371: Nos referimos a la revisión más reciente en el repositorio como la jerojasro@371: revisión de punta, o simplemente la punta. jerojasro@343: jerojasro@379: \section{Compartir cambios} jerojasro@379: jerojasro@379: Anteriormente mencionamos que los repositorios en Mercurial están auto jerojasro@379: contenidos. Esto quiere decir que el conjunto de cambios que acabamos jerojasro@379: de crear sólo existe en nuestro repositorio \dirname{my-hello}. Veamos jerojasro@379: unas cuantas formas de propagar este cambio a otros repositorios. jerojasro@343: jerojasro@372: \subsection{Jalar cambios desde otro repositorio} jerojasro@343: \label{sec:tour:pull} jerojasro@343: jerojasro@372: Para empezar, clonemos nuestro repositorio \dirname{hello} original, jerojasro@372: el cual no contiene el cambio que acabamos de consignar. Llamaremos a jerojasro@372: este repositorio temporal \dirname{hello-pull}. jerojasro@343: \interaction{tour.clone-pull} jerojasro@343: jerojasro@372: Usaremos el comando \hgcmd{pull} para traer los cambios de jerojasro@372: \dirname{my-hello} y ponerlos en \dirname{hello-pull}. Sin embargo, jerojasro@372: traer cambios desconocidos y aplicarlos en un repositorio es una jerojasro@372: perspectiva que asusta al menos un poco. Mercurial cuenta con el jerojasro@379: comando \hgcmd{incoming}\ndt{Entrante, o cambios entrantes.} para jerojasro@379: decirnos qué cambios \emph{jalaría} el comando \hgcmd{pull} al jerojasro@379: repositorio, sin jalarlos. jerojasro@343: \interaction{tour.incoming} jerojasro@372: (Por supuesto, alguien podría enviar más conjuntos de cambios al jerojasro@372: repositorio en el tiempo que pasa entre la ejecución de jerojasro@372: \hgcmd{incoming} y la ejecución de \hgcmd{pull} para jalar los jerojasro@372: cambios, así que es posible que terminemos jalando cambios que no jerojasro@372: esperábamos.) jerojasro@372: jerojasro@372: Traer cambios al repositorio simplemente es cuestión de ejecutar el jerojasro@372: comando \hgcmd{pull}, indicándole de qué repositorio debe jalarlos. jerojasro@343: \interaction{tour.pull} jerojasro@372: Como puede verse por las salidas antes-y-después de \hgcmd{tip}, hemos jerojasro@372: jalado exitosamente los cambios en nuestro repositorio. Aún falta un jerojasro@372: paso para que podamos ver estos cambios en nuestro directorio de jerojasro@372: trabajo. jerojasro@372: jerojasro@372: \subsection{Actualizar el directorio de trabajo} jerojasro@343: jerojasro@379: Hasta ahora hemos pasado por alto la relación entre un repositorio y jerojasro@379: su directorio de trabajo. El comando \hgcmd{pull} que ejecutamos en la jerojasro@379: sección~\ref{sec:tour:pull} trajo los cambios al repositorio, pero si jerojasro@379: revisamos, no hay rastro de esos cambios en el directorio de trabajo. jerojasro@379: Esto pasa porque \hgcmd{pull} (por defecto) no modifica el directorio de jerojasro@379: trabajo. En vez de eso, usamos el comando jerojasro@379: \hgcmd{update}\ndt{Actualizar.} para hacerlo. jerojasro@343: \interaction{tour.update} jerojasro@343: jerojasro@379: Puede parecer algo raro que \hgcmd{pull} no actualice el directorio de jerojasro@379: trabajo automáticamente. De hecho, hay una buena razón para esto: jerojasro@379: usted puede usar \hgcmd{update} para actualizar el directorio de jerojasro@379: trabajo al estado en que se encontraba en \emph{cualquier revisión} jerojasro@501: del historial del repositorio. Si usted hubiera actualizado el jerojasro@379: directorio de trabajo a una revisión anterior---digamos, para buscar jerojasro@379: el origen de un fallo---y hubiera corrido un \hgcmd{pull} que hubiera jerojasro@379: actualizado el directorio de trabajo automáticamente a la nueva jerojasro@379: revisión, puede que no estuviera particularmente contento. jerojasro@379: jerojasro@379: Sin embargo, como jalar-y-actualizar es una secuencia de operaciones jerojasro@379: muy común, Mercurial le permite combinarlas al pasar la opción jerojasro@379: \hgopt{pull}{-u} jerojasro@379: a \hgcmd{pull}. jerojasro@343: \begin{codesample2} jerojasro@343: hg pull -u jerojasro@343: \end{codesample2} jerojasro@379: Si mira de vuelta la salida de \hgcmd{pull} en la jerojasro@379: sección~\ref{sec:tour:pull} cuando lo ejecutamos sin la opción \hgopt{pull}{-u}, jerojasro@379: verá que el comando imprimió un amable recordatorio de que tenemos que jerojasro@379: encargarnos explícitamente de actualizar el directorio de trabajo: jerojasro@343: \begin{codesample2} jerojasro@343: (run 'hg update' to get a working copy) jerojasro@343: \end{codesample2} jerojasro@343: jerojasro@379: Para averiguar en qué revisión se encuentra el directorio de trabajo, jerojasro@379: use el comando \hgcmd{parents}. jerojasro@343: \interaction{tour.parents} jerojasro@379: Si mira de nuevo la figura~\ref{fig:tour-basic:history}, verá flechas jerojasro@379: conectando cada conjunto de cambios. En cada caso, el nodo del que la flecha jerojasro@379: \emph{sale} es un padre, y el nodo al que la flecha \emph{llega} es jerojasro@379: su hijo. El directorio de trabajo tiene un padre exactamente de la jerojasro@379: misma manera; ése es el conjunto de cambios que contiene actualmente jerojasro@379: el directorio de trabajo. jerojasro@379: jerojasro@379: Para actualizar el conjunto de trabajo a una revisión particular, pase jerojasro@379: un número de revisión o un ID de conjunto de cambios al comando jerojasro@379: \hgcmd{update}. jerojasro@343: \interaction{tour.older} jerojasro@379: Si no indica explícitamente una revisión, \hgcmd{update} actualizará jerojasro@379: hasta la revisión de punta, como se vio en la segunda llamada a jerojasro@379: \hgcmd{update} en el ejemplo anterior. jerojasro@379: jerojasro@379: \subsection{Empujar cambios a otro repositorio} jerojasro@379: jerojasro@379: Mercurial nos permite empujar cambios a otro repositorio, desde el jerojasro@379: % TODO cambié "visitando" por "usando" jerojasro@379: repositorio que estemos usando actualmente. De la misma forma que en jerojasro@379: el ejemplo de \hgcmd{pull} arriba, crearemos un repositorio temporal jerojasro@379: para empujar allí nuestros cambios. jerojasro@343: \interaction{tour.clone-push} jerojasro@379: El comando \hgcmd{outgoing}\ndt{Saliente. Cambios salientes.} nos dice jerojasro@379: qué cambios serían empujados en el otro repositorio. jerojasro@343: \interaction{tour.outgoing} jerojasro@379: Y el comando \hgcmd{push} se encarga de empujar dichos cambios. jerojasro@343: \interaction{tour.push} jerojasro@379: Al igual que \hgcmd{pull}, el comando \hgcmd{push} no actualiza el jerojasro@379: directorio de trabajo del repositorio en el que estamos empujando los jerojasro@379: cambios. (A diferencia de \hgcmd{pull}, \hgcmd{push} no ofrece la jerojasro@379: opción \texttt{-u} para actualizar el directorio de trabajo del otro jerojasro@379: repositorio.) jerojasro@379: jerojasro@379: % TODO poner interrogante de apertura jerojasro@379: Qué pasa si tratamos de jalar o empujar cambios y el repositorio jerojasro@379: receptor ya tiene esos cambios? Nada emocionante. jerojasro@343: \interaction{tour.push.nothing} jerojasro@343: jerojasro@379: \subsection{Compartir cambios a través de una red} jerojasro@379: jerojasro@379: Los comandos que hemos presentando en las pocas secciones anteriores jerojasro@379: no están limitados a trabajar con repositorios locales. Cada uno de jerojasro@379: ellos funciona exactamente de la misma manera a través de una conexión jerojasro@379: % TODO poner ndt para URL jerojasro@379: de red. Simplemente pase una URL en vez de una ruta local. jerojasro@343: \interaction{tour.outgoing.net} jerojasro@379: En este ejemplo, podemos ver qué cambios empujaríamos al repositorio jerojasro@379: remoto, aunque, de manera entendible, el repositorio remoto está jerojasro@379: configurado para no permitir a usuarios anónimos empujar cambios a él. jerojasro@343: \interaction{tour.push.net} jerojasro@343: jerojasro@343: %%% Local Variables: jerojasro@343: %%% mode: latex jerojasro@343: %%% TeX-master: "00book" jerojasro@343: %%% End: