
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
igor@345: explícitamente se lo indique.  La orden \hgcmd{status} le mostrará
igor@359: cuáles ficheros son desconocidos para Mercurial; 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: 
igor@359: \subsection{Nombramiento explicíto 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
igor@345: nombre de un directorio, Mercurial efectua 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: 
igor@359: \subsection{Al eliminar un fichero no se afecta su historia}
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}
igor@353: Al eliminar un fichero \emph{no} se altera de ninguna manera la
igor@353: \emph{historia} del mismo.
igor@353: 
igor@353: Si actualiza su directorio de trabajo a un conjunto de cambios en el
igor@359: cual esl 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@359: lleva un registro indicando que el nuevo archivo 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@359: \subsection{Resultados de copiar un archivo durante una fusión}
igor@359: 
igor@359: Durante una fusión lols cambios ``siguen'' una copia.  Para ilustrar
igor@359: lo que esto significa, haremos un ejemplo.  Comenzaremos con el mini
igor@359: repositorio usual que contiene un solo archivo
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@359: una copia del primer archivo que creamos.
igor@345: \interaction{daily.copy.copy}
igor@345: 
igor@359: Si vemos la salida de la orden \hgcmd{status}, el archivo copiado luce
igor@359: como un archivo que se ha añadido normalmente.
igor@345: \interaction{daily.copy.status}
igor@359: Si usamos la opción \hgopt{status}{-C} de la orden \hgcmd{status},
igor@359: imprimirá otra línea: Ela archivo of output: this is the file that our newly-added
igor@345: file was copied \emph{from}.
igor@345: \interaction{daily.copy.status-copy}
igor@345: 
igor@359: Ahora, en el repositorio que clonamos, hagamos un cambio en
igor@359: paralelo. Adicionaremos una línea de contenido al archivo 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@359: cuando fusionamos.  Por lo tanto si sobre un archivo 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@359: archivo 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@359: del archivo.
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@359: mismo \emph{permanecería} en su copia del archivo.
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
igor@359: fichero oficinal 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@359: archivo 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: 
igor@359: La orden \hgcmd{copy} actua de forma parecida a la orden \command{cp}
igor@359: 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@345: \section{Renaming files}
igor@345: 
igor@345: It's rather more common to need to rename a file than to make a copy
igor@345: of it.  The reason I discussed the \hgcmd{copy} command before talking
igor@345: about renaming files is that Mercurial treats a rename in essentially
igor@345: the same way as a copy.  Therefore, knowing what Mercurial does when
igor@345: you copy a file tells you what to expect when you rename a file.
igor@345: 
igor@345: When you use the \hgcmd{rename} command, Mercurial makes a copy of
igor@345: each source file, then deletes it and marks the file as removed.
igor@345: \interaction{daily.rename.rename}
igor@345: The \hgcmd{status} command shows the newly copied file as added, and
igor@345: the copied-from file as removed.
igor@345: \interaction{daily.rename.status}
igor@345: As with the results of a \hgcmd{copy}, we must use the
igor@345: \hgopt{status}{-C} option to \hgcmd{status} to see that the added file
igor@345: is really being tracked by Mercurial as a copy of the original, now
igor@345: removed, file.
igor@345: \interaction{daily.rename.status-copy}
igor@345: 
igor@345: As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
igor@345: a rename after the fact using the \hgopt{rename}{--after} option.  In
igor@345: most other respects, the behaviour of the \hgcmd{rename} command, and
igor@345: the options it accepts, are similar to the \hgcmd{copy} command.
igor@345: 
igor@345: \subsection{Renaming files and merging changes}
igor@345: 
igor@345: Since Mercurial's rename is implemented as copy-and-remove, the same
igor@345: propagation of changes happens when you merge after a rename as after
igor@345: a copy.
igor@345: 
igor@345: If I modify a file, and you rename it to a new name, and then we merge
igor@345: our respective changes, my modifications to the file under its
igor@345: original name will be propagated into the file under its new name.
igor@345: (This is something you might expect to ``simply work,'' but not all
igor@345: revision control systems actually do this.)
igor@345: 
igor@345: Whereas having changes follow a copy is a feature where you can
igor@345: perhaps nod and say ``yes, that might be useful,'' it should be clear
igor@345: that having them follow a rename is definitely important.  Without
igor@345: this facility, it would simply be too easy for changes to become
igor@345: orphaned when files are renamed.
igor@345: 
igor@345: \subsection{Divergent renames and merging}
igor@345: 
igor@345: The case of diverging names occurs when two developers start with a
igor@345: file---let's call it \filename{foo}---in their respective
igor@345: repositories.
igor@345: 
igor@345: \interaction{rename.divergent.clone}
igor@345: Anne renames the file to \filename{bar}.
igor@345: \interaction{rename.divergent.rename.anne}
igor@345: Meanwhile, Bob renames it to \filename{quux}.
igor@345: \interaction{rename.divergent.rename.bob}
igor@345: 
igor@345: I like to think of this as a conflict because each developer has
igor@345: expressed different intentions about what the file ought to be named.
igor@345: 
igor@345: What do you think should happen when they merge their work?
igor@345: Mercurial's actual behaviour is that it always preserves \emph{both}
igor@345: names when it merges changesets that contain divergent renames.
igor@345: \interaction{rename.divergent.merge}
igor@345: 
igor@345: Notice that Mercurial does warn about the divergent renames, but it
igor@345: leaves it up to you to do something about the divergence after the merge.
igor@345: 
igor@345: \subsection{Convergent renames and merging}
igor@345: 
igor@345: Another kind of rename conflict occurs when two people choose to
igor@345: rename different \emph{source} files to the same \emph{destination}.
igor@345: In this case, Mercurial runs its normal merge machinery, and lets you
igor@345: guide it to a suitable resolution.
igor@345: 
igor@345: \subsection{Other name-related corner cases}
igor@345: 
igor@345: Mercurial has a longstanding bug in which it fails to handle a merge
igor@345: where one side has a file with a given name, while another has a
igor@345: directory with the same name.  This is documented as~\bug{29}.
igor@345: \interaction{issue29.go}
igor@345: 
igor@345: \section{Recovering from mistakes}
igor@345: 
igor@345: Mercurial has some useful commands that will help you to recover from
igor@345: some common mistakes.
igor@345: 
igor@345: The \hgcmd{revert} command lets you undo changes that you have made to
igor@345: your working directory.  For example, if you \hgcmd{add} a file by
igor@345: accident, just run \hgcmd{revert} with the name of the file you added,
igor@345: and while the file won't be touched in any way, it won't be tracked
igor@345: for adding by Mercurial any longer, either.  You can also use
igor@345: \hgcmd{revert} to get rid of erroneous changes to a file.
igor@345: 
igor@345: It's useful to remember that the \hgcmd{revert} command is useful for
igor@345: changes that you have not yet committed.  Once you've committed a
igor@345: change, if you decide it was a mistake, you can still do something
igor@345: about it, though your options may be more limited.
igor@345: 
igor@345: For more information about the \hgcmd{revert} command, and details
igor@345: about how to deal with changes you have already committed, see
igor@345: chapter~\ref{chap:undo}.
igor@345: 
igor@345: %%% Local Variables: 
igor@345: %%% mode: latex
igor@345: %%% TeX-master: "00book"
igor@345: %%% End: 




