igor@345: \chapter{Mercurial día a día} igor@345: \label{chap:daily} igor@345: igor@359: \section{Cómo indicarle a Mercurial qué ficheros seguir} igor@359: igor@359: Mercurial no trabaja con ficheros en su repositorio a menos que usted jerojasro@535: se lo indique explícitamente. La orden \hgcmd{status} le mostrará jerojasro@535: cuáles ficheros son desconocidos para Mercurial; se emplea un igor@359: ``\texttt{?}'' para mostrar tales ficheros. igor@359: igor@359: Para indicarle a Mercurial que tenga en cuenta un fichero, emplee la igor@359: orden \hgcmd{add}. Una vez que haya adicionado el fichero, la línea igor@359: referente al fichero al aplicar la orden \hgcmd{status} para tal igor@359: fichero cambia de ``\texttt{?}'' a ``\texttt{A}''. igor@345: \interaction{daily.files.add} igor@345: igor@359: Después de invocar \hgcmd{commit}, los ficheros que haya adicionado igor@345: antes de consignar no se listarán en la salida de \hgcmd{status}. La igor@345: razón para esto es que \hgcmd{status} solamente le muestra aquellos igor@359: ficheros ``interesantes''---los que usted haya modificado o a aquellos igor@345: sobre los que usted haya indicado a Mercurial hacerles algo---de forma igor@345: predeterminada. Si tiene un repositorio que contiene miles de igor@359: ficheros, inusualmente deseará saber cuáles de ellos están siendo igor@345: seguidos por Mercurial, pero que no han cambiado. (De todas maneras, igor@345: puede obtener tal información; más adelante hablaremos de ello.) igor@345: igor@345: jerojasro@361: Cuando usted añade un fichero, Mercurial no hace nada con él inmediatamente. igor@359: A cambio, tomará una instantánea del estado del fichero la próxima vez igor@345: que usted consigne. Continuará haciendo seguimiento a los cambios que igor@359: haga sobre el fichero cada vez que consigne, hasta que usted lo elimine. igor@359: jerojasro@535: \subsection{Nombramiento explícito e implícito de ficheros} igor@345: igor@345: Mercurial tiene un comportamiento útil en el cual si a una orden, igor@345: le pasa el nombre de un directorio, todas las órdenes lo tratarán como igor@359: ``Deseo operar en cada fichero de este directorio y sus igor@345: subdirectorios''. igor@345: \interaction{daily.files.add-dir} igor@345: Tenga en cuenta que en este ejemplo Mercurial imprimió los nombres de igor@359: los ficheros que se adicionaron, mientras que no lo hizo en el ejemplo igor@359: anterior cuando adicionamos el fichero con nombre \filename{a}. igor@359: igor@359: En el último caso hicimos explícito el nombre del fichero que igor@345: deseábamos adicionar en la línea de órdenes, y Mercurial asume en igor@345: tales casos que usted sabe lo que está haciendo y no imprime igor@345: información alguna. igor@345: igor@359: Cuando hacemos \emph{implícitos} los nombres de los ficheros dando el jerojasro@535: nombre de un directorio, Mercurial efectúa un paso extra al imprimir igor@359: el nombre de cada fichero con el que va a hacer algo. Esto para igor@345: aclarar lo que está sucediendo, y reducir en lo posible una sorpresa igor@345: silenciosa pero fatal. Este comportamiento es común a la mayoría de igor@345: órdenes en Mercurial. igor@345: igor@359: \subsection{Nota al margen:Mercurial trata ficheros, no directorios} igor@345: igor@345: Mercurial no da seguimiento a la información de los directorios. En igor@359: lugar de eso tiene en cuenta las rutas de los ficheros. Antes de igor@359: crear un fichero, primero crea todos los directorios que hagan falta igor@359: para completar la ruta del fichero. Después de borrar un fichero, igor@345: borra todos los directorios vacíos que estuvieran en la ruta del igor@359: fichero borrado. Suena como una diferencia trivial, pero tiene una igor@345: consecuencia práctica menor: no es posible representar un directorio igor@345: completamente vacío en Mercurial. igor@345: igor@345: Los directorios vacíos son inusualmente útiles, hay soluciones igor@345: alternativas no intrusivas que puede emplear para obtener el efecto igor@345: apropiado. Los desarrolladores de Mercurial pensaron que la igor@345: complejidad necesaria para administrar directorios vacíos no valía la igor@345: pena frente al beneficio limitado que esta característica podría traer. igor@345: igor@345: Si necesita un directorio vacío en su repositorio, hay algunas formas igor@345: de lograrlo. Una es crear un directorio, después hacer \hgcmd{add} a igor@359: un fichero ``escondido'' dentro de ese directorio. En sistemas tipo igor@359: Unix, cualquier fichero cuyo nombre comience con un punto igor@345: (``\texttt{.}'') se trata como escondido por la mayoría de igor@345: herramientas GUI. Esta aproximación se ilustra en la figura~\ref{ex:daily:hidden}. igor@345: igor@345: \begin{figure}[ht] igor@345: \interaction{daily.files.hidden} igor@359: \caption{Simular un directorio vacío con un fichero escondido} igor@345: \label{ex:daily:hidden} igor@345: \end{figure} igor@345: igor@359: Otra forma de abordar la necesidad de un fichero vacío es crear igor@345: simplemente uno en sus guiones de construcción antes de ser necesarios. igor@345: igor@359: \section{Cómo dejar de hacer seguimiento a un fichero} igor@359: igor@359: Si decide que un fichero no pertenece a su repositorio, use la orden igor@359: \hgcmd{remove}; se borrará el fichero y le indicará a Mercurial que igor@359: deje de hacerle seguimiento. Los ficheros eliminados se representan igor@353: con ``\texttt{R}'' al usar \hgcmd{status}. igor@345: \interaction{daily.files.remove} igor@345: igor@359: Después de hacer \hgcmd{remove} a un fichero, Mercurial dejará de igor@359: hacer seguimiento al mismo, incluso si recrea el fichero con el mismo igor@359: nombre en su directorio de trabajo. Si decide recrear un fichero con igor@353: el mismo nombre y desea que Mercurial le haga seguimiento, basta con igor@359: hacerle \hgcmd{add}. Mercurial sabrá que el fichero recientemente igor@359: adicionado no está relacionado con el fichero anterior que tenía el igor@353: mismo nombre. igor@353: jerojasro@516: \subsection{Al eliminar un fichero no se afecta su historial} igor@359: igor@359: Es preciso tener en cuenta que al eliminar un fichero se tiene igor@353: dos efectos solamente. igor@345: \begin{itemize} igor@353: \item Se elimina la versión actual del fichero del directorio de igor@353: trabajo. igor@353: \item Mercurial deja de hacer seguimiento a los cambios del fichero igor@353: desde la próxima consignación. igor@345: \end{itemize} jerojasro@516: Al eliminar un fichero \emph{no} se altera de ninguna manera el jerojasro@516: \emph{historial} del mismo. igor@353: igor@353: Si actualiza su directorio de trabajo a un conjunto de cambios en el jerojasro@535: cual el fichero que eliminó aún era tenido en cuenta, reaparecerá en igor@353: el directorio de trabajo, con los contenidos que este tenía cuando se igor@353: consignó tal conjunto de cambios. Si usted actualiza el directorio de igor@359: trabajo a un conjunto de cambios posterior en el cual el fichero había igor@353: sido eliminado, Mercurial lo eliminará de nuevo del directorio de igor@353: trabajo. igor@345: igor@359: \subsection{Ficheros perdidos} igor@359: igor@359: Mercurial considera como \emph{perdido} un fichero que usted borró, igor@359: pero para el que no se usó \hgcmd{remove}. Los ficheros perdidos se igor@353: representan con ``\texttt{!}'' al visualizar \hgcmd{status}. igor@359: Las órdenes de Mercurial generalmente no harán nada con los ficheros igor@353: perdidos. igor@345: \interaction{daily.files.missing} igor@345: igor@359: Si su repositorio contiene un fichero que \hgcmd{status} reporta como igor@353: perdido, y desea que el mismo se vaya, se puede usar igor@353: \hgcmdargs{remove}{\hgopt{remove}{--after}} posteriormente para igor@359: indicarle a Mercurial que usted deseaba borrar tal fichero. igor@345: \interaction{daily.files.remove-after} igor@345: igor@353: Por otro lado, si borró un fichero perdido por accidente, puede usar igor@353: \hgcmdargs{revert}{\emph{nombre de fichero}} para recuperar el igor@353: fichero. Reaparecerá sin modificaciones. igor@345: \interaction{daily.files.recover-missing} igor@345: igor@353: \subsection{Nota al margen: ¿Por qué decirle explícitamente a Mercurial igor@359: que elimine un fichero?} igor@353: igor@353: Es posible que se haya preguntado por qué Mercurial exige que usted le igor@359: indique explícitamente que está borrando un fichero. Al principio del igor@359: desarrollo de Mercurial, este permitía que usted borrara el fichero igor@359: sin más; Mercurial se daría cuanta de la ausencia del fichero igor@353: automáticamente después de la ejecución de \hgcmd{commit}, y dejaba de igor@359: hacer seguimiento al fichero. En la práctica, resultaba muy sencillo igor@359: borrar un fichero accidentalmente sin darse cuenta. igor@359: igor@359: \subsection{Atajo útil---agregar y eliminar ficheros en un solo paso} igor@353: igor@353: Mercurial ofrece una orden combinada, \hgcmd{addremove}, que agrega igor@359: los ficheros que no tienen seguimiento y marca los ficheros faltantes igor@353: como eliminados. igor@345: \interaction{daily.files.addremove} igor@353: La orden \hgcmd{commit} su puede usar con la opción \hgopt{commit}{-A} igor@353: que aplica el agregar-eliminar, seguido inmediatamente de una igor@353: consignación. igor@345: \interaction{daily.files.commit-addremove} igor@345: igor@359: \section{Copiar ficheros} igor@359: igor@359: Mercurial ofrece la orden \hgcmd{copy} para hacer una nueva copia de jerojasro@369: un fichero. Cuando se copia un fichero con esta orden, Mercurial igor@378: lleva un registro indicando que el nuevo fichero es una copia del jerojasro@369: fichero original. Trata de forma especial los ficheros copiados cuando igor@359: usted hace una fusión con el trabajo de alguien más. igor@359: igor@378: \subsection{Resultados de copiar un fichero durante una fusión} igor@359: jerojasro@421: Durante una fusión los cambios ``siguen'' una copia. Para ilustrar igor@359: lo que esto significa, haremos un ejemplo. Comenzaremos con el mini igor@378: repositorio usual que contiene un solo fichero igor@345: \interaction{daily.copy.init} igor@359: Debemos trabajar algo en paralelo, de forma que tengamos algo para igor@359: fusionar. Aquí clonamos el repositorio. igor@345: \interaction{daily.copy.clone} igor@359: De vuelta en el repositorio, usemos la orden \hgcmd{copy} para hacer igor@378: una copia del primer fichero que creamos. igor@345: \interaction{daily.copy.copy} igor@345: igor@378: Si vemos la salida de la orden \hgcmd{status}, el fichero copiado luce igor@378: como un fichero que se ha añadido normalmente. igor@345: \interaction{daily.copy.status} jerojasro@535: Pero si usamos la opción \hgopt{status}{-C} de la orden \hgcmd{status}, jerojasro@535: imprimirá otra línea: el fichero \emph{desde} el cual fue copiado nuestro jerojasro@535: fichero recién añadido. igor@345: \interaction{daily.copy.status-copy} igor@345: igor@359: Ahora, en el repositorio que clonamos, hagamos un cambio en igor@378: paralelo. Adicionaremos una línea de contenido al fichero original que igor@359: creamos. igor@345: \interaction{daily.copy.other} igor@359: Hemos modificado el fichero \filename{file} en este igor@359: repositorio. Cuando jalemos los cambios del primer repositorio y igor@359: fusionemos las dos cabezas, Mercurial propagará los cambios que hemos igor@359: hecho localmente en \filename{file} a su copia, \filename{new-file}. igor@345: \interaction{daily.copy.merge} igor@345: igor@359: \subsection{¿Por qué los cambios se reflejan en las copias?} igor@345: \label{sec:daily:why-copy} igor@345: igor@359: Este comportamiento de cambios en ficheros que se propagan a las igor@359: copias de los ficheros parecería esotérico, pero en la mayoría de igor@359: casos es absolutamente deseable. igor@359: igor@359: Es indispensable recordar que esta propagación \emph{solamente} sucede igor@378: cuando fusionamos. Por lo tanto si sobre un fichero se usa igor@359: \hgcmd{copy}, y se modifica el fichero original durante el curso igor@359: normal de su trabajo, nada pasará. igor@359: igor@359: Lo segundo a tener en cuenta es que las modificaciones solamente se igor@359: propagarán en las copias únicamente si los repositorios de los cuales igor@359: está jalando los cambios \emph{no saben} de la copia. igor@359: igor@359: Explicaremos a continuación la razón de este comportamiento de igor@359: Mercurial. Digamos que yo he aplicado un arreglo de un fallo importante a un igor@378: fichero fuente y consigné los cambios. Por otro lado, usted decidió hacer igor@359: \hgcmd{copy} sobre el fichero en su repositorio, sin saber acerca del igor@359: fallo o sin ver el arreglo, y ha comenzado a trabajar sobre su copia igor@378: del fichero. igor@359: igor@359: Si jala y fusiona mis cambios y Mercurial \emph{no hubiera} propagado igor@359: los cambios en las copias, su fichero fuente tendría el fallo, a menos igor@359: que usted haya recordado propagar el arreglo del fallo a mano, el igor@378: mismo \emph{permanecería} en su copia del fichero. igor@359: igor@359: Mercurial previene esta clase de problemas, gracias a la propagación igor@359: automática del cambio que arregló el fallo del fichero original. Hasta igor@359: donde sé, Mercurial es el \emph{único} sistema de control de igor@359: revisiones que propaga los cambios en las copias de esta forma. igor@359: igor@359: Cuando su historial de cambios tiene un registro de la copia y la igor@359: subsecuente fusión, usualmente no es necesario propagar los cambios el jerojasro@535: fichero original a las copias del mismo, y por esta razón Mercurial igor@359: propaga únicamente los cambios en las copias hasta este punto y no más igor@359: allá. igor@359: igor@359: igor@359: \subsection{Cómo hacer que los cambios \emph{no} sigan a la copia?} igor@359: igor@359: Si por algún motivo usted decide que esta característica de igor@359: propagación automática de cambios en las copias no es para usted, use igor@359: la orden usual de sus sistema para copiar ficheros (En sistemas tipo igor@359: Unix, es \command{cp}), posteriormente use \hgcmd{add} sobre la nueva igor@359: copia hecha a mano. Antes de hacerlo, de todas maneras, relea la igor@359: sección~\ref{sec:daily:why-copy}, y tome una decisión asegurándose que igor@359: este comportamiento no es el apropiado para su caso específico. igor@359: igor@359: \subsection{Comportamiento de la orden \hgcmd{copy}} igor@359: igor@359: Cuando usa la orden \hgcmd{copy}, Mercurial hace una copia de cada igor@378: fichero fuente del directorio actual. Esto significa que si usted hace igor@359: modificaciones a un fichero, y le aplica \hgcmd{copy} sin haber igor@359: consignado primero los cambios, la nueva copia contendrá también las igor@359: modificaciones que haya hecho hasta ese punto. (Este comportamiento me igor@359: parece poco intuitivo, y por tal motivo lo menciono.) igor@359: jerojasro@535: La orden \hgcmd{copy} actúa de forma parecida a la orden \command{cp} jerojasro@520: de Unix (puede usar el alias \hgcmd{cp} si le es más cómodo). El igor@359: último argumento es el \emph{destino}, y todos los argumentos previos igor@359: son las \emph{fuentes}. Si solamente indica un fichero como la igor@359: fuente, y el destino no existe, se crea un fichero nuevo con ese nombre. igor@345: \interaction{daily.copy.simple} igor@359: Si el destino es un directorio, Mercurial copia las fuentes en este. igor@345: \interaction{daily.copy.dir-dest} igor@359: La copia de un directorio es recursiva, y preserva la estructura del igor@359: directorio fuente. igor@345: \interaction{daily.copy.dir-src} igor@359: Si tanto la fuente como el destino son directorios, la estructura de igor@359: la fuente se recrea en el directorio destino. igor@345: \interaction{daily.copy.dir-src-dest} igor@345: igor@359: De la misma forma como la orden \hgcmd{rename}, si copia un fichero igor@359: manualmente y desea que Mercurial sepa que ha copiado un fichero, igor@359: basta con aplicar la opción \hgopt{copy}{--after} a la orden igor@359: \hgcmd{copy}. igor@345: \interaction{daily.copy.after} igor@345: igor@373: \section{Renombrar ficheros} igor@373: igor@373: La necesidad de renombrar un fichero es más común que hacer una copia igor@373: del fichero. La razón por la cual discutí la orden \hgcmd{copy} antes igor@373: de hablar acerca de cambiar el nombre de los ficheros, es que igor@378: Mercurial trata el renombrar un fichero de la misma forma que una igor@373: copia. Por lo tanto, saber lo que hace Mercurial cuando usted copia igor@378: un fichero, le indica qué esperar cuando renombra un fichero. igor@373: igor@373: Cuando usa la orden \hgcmd{rename}, Mercurial hace una copia de cada igor@378: fichero fuente, lo borra y lo marca como fichero eliminado. igor@345: \interaction{daily.rename.rename} igor@373: La orden \hgcmd{status} muestra la nueva copia del fichero como igor@373: añadido y el fichero inicial de la copia, como eliminado. igor@345: \interaction{daily.rename.status} igor@373: De la misma forma como se usa la orden \hgcmd{copy}, debemos usar la igor@373: opción \hgopt{status}{-C} de la orden \hgcmd{status} para verificar igor@378: que el fichero añadido realmente comienza a ser seguido por Mercurial igor@373: como una copia del fichero original, ahora eliminado. igor@345: \interaction{daily.rename.status-copy} igor@345: igor@373: Igual que con \hgcmd{remove} y \hgcmd{copy}, puede indicársele a igor@373: Mercurial acerca de un renombramiento inmediato con la opción igor@373: \hgopt{rename}{--after}. El comportamiento de la orden igor@373: \hgcmd{rename} y las opciones que acepta, son similares a la orden igor@373: \hgcmd{copy} en casi todo. igor@373: igor@373: \subsection{Renombrar ficheros y fusionar cambios} igor@373: igor@373: Dado que el renombrar de Mercurial se implementa como un igor@373: copiar-y-eliminar, la misma propagación de cambios ocurre cuando usted igor@373: fusiona después de renombrar como después de hacer una copia. igor@373: igor@378: Si Yo modifico un fichero y usted lo renombra a un nuevo fichero, y igor@373: posteriormente fusionamos nuestros cambios respectivos, mi igor@373: modificación al fichero bajo su nombre original se propagará en el igor@373: fichero con el nuevo nombre. (Es lo que se esperaría como ``lo hace,'' igor@373: pero, no todos los sistemas de control de revisiones lo logran.) igor@373: igor@373: El hecho de que los cambios sigan la copia es una característica que igor@373: puede subestimar diciendo ``si, puede ser útil,'' debería ser claro igor@373: que el seguimiento de cambios de un renombramiento es importante igor@373: definitivamente. Sin esto, sería muy sencillo que los cambios se igor@378: volvieran huérfanos cuando los ficheros se renombran. igor@373: igor@373: \subsection{Cambios de nombre divergentes y fusión} igor@373: igor@373: El caso de renombramiento con nombres divergentes ocurre cuando dos igor@373: desarrolladores comienzan con un fichero---llamémoslo igor@373: \filename{foo}---en sus repositorios respectivos. igor@345: igor@345: \interaction{rename.divergent.clone} igor@373: Ana renombra el fichero a \filename{bar}. igor@345: \interaction{rename.divergent.rename.anne} igor@373: Mientras que Roberto lo renombra como \filename{quux}. igor@345: \interaction{rename.divergent.rename.bob} igor@345: igor@373: Veo esto como un conflicto porque cada desarrollador ha expresado igor@373: intenciones diferentes acerca de cómo considera debería haberse igor@373: renombrado el fichero. igor@373: jerojasro@535: ¿Qué cree que debería pasar cuando fusionen su trabajo? igor@373: El comportamiento de Mercurial es que siempre preserva \emph{ambos} igor@373: nombres cuando fusiona los conjuntos de cambios que contienen nombres igor@373: divergentes. igor@345: \interaction{rename.divergent.merge} igor@345: igor@373: Tenga en cuenta que Mercurial le advierte acerca de nombres igor@373: divergentes, pero deja que usted decida qué hacer con la divergencia igor@373: después de la fusión. igor@373: igor@373: \subsection{Cambios de nombre convergentes y fusión} igor@373: igor@373: Otra clase de conflicto al cambiar el nombre ocurre cuando dos igor@373: personas eligen renombrar diferentes ficheros \emph{fuente} al mismo igor@373: \emph{destino}. En este caso Mercurial aplica su maquinaria de fusión igor@373: usual, y le permite a usted guiarlo a una solución adecuada. igor@373: igor@373: \subsection{Otros casos límites relacionados con renombramientos} igor@373: igor@373: Mercurial tiene un fallo de mucho tiempo en el cual no es capaz de igor@378: fusionar cuando por un lado hay un fichero con un nombre dado, igor@373: mientras que en otro hay un directorio con el mismo nombre. Esto está igor@373: documentado como~\bug{29}. igor@345: \interaction{issue29.go} igor@345: igor@373: \section{Recuperarse de equivocaciones} igor@373: igor@373: Mercurial tiene unas órdenes poderosas que le ayudarán a recuperarse igor@373: de equivocaciones comunes. igor@373: igor@373: La orden \hgcmd{revert} le permite deshacer cambios que haya hecho a igor@373: su directorio de trabajo. Por ejemplo, Si aplicó \hgcmd{add} a un igor@373: fichero por accidente, ejecute \hgcmd{revert} con el nombre del jerojasro@535: fichero que añadió, y en tanto que el fichero no haya sido tocado de igor@373: forma alguna, no será adicionado, ni seguido por Mercurial. También igor@373: puede usar \hgcmd{revert} para deshacerse de cambios erróneos a un igor@373: fichero. igor@373: igor@373: Tenga en cuenta que la orden \hgcmd{revert} se usa para cambios que no igor@373: han sido consignados. Cuando haya consignado un cambio, si decide que igor@373: era un error, puede hacer algo todavía, pero sus opciones pueden ser igor@373: más limitadas. igor@373: igor@373: Para obtener información acerca de la orden \hgcmd{revert} y detalles igor@373: de cómo tratar con cambios consignados, vea el capítulo~\ref{chap:undo}. igor@345: igor@345: %%% Local Variables: igor@345: %%% mode: latex igor@345: %%% TeX-master: "00book" igor@345: %%% End: