view es/daily.tex @ 453:11d7896cd2ac

Merging changes from jerojasro
author Igor TAmara <igor@tamarapatino.org>
date Wed, 22 Oct 2008 01:51:33 -0500
parents d8596cd12b41
children 854a70fc05c6
line wrap: on
line source

\chapter{Mercurial día a día}
\label{chap:daily}

\section{Cómo indicarle a Mercurial qué archivos seguir}

Mercurial no trabaja con archivos en su repositorio a menos que usted
explícitamente se lo indique.  La orden \hgcmd{status} le mostrará
cuáles archivos son desconocidos para Mercurial; emplea un
``\texttt{?}'' para mostrar tales archivos.

Para indicarle a Mercurial que tenga en cuenta un archivo, emplee la
orden \hgcmd{add}. Una vez que haya adicionado el archivo, la línea
referente al archivo al aplicar la orden \hgcmd{status} para tal
archivo cambia de ``\texttt{?}'' a ``\texttt{A}''.
\interaction{daily.files.add}

Después de invocar \hgcmd{commit}, los archivos que haya adicionado
antes de consignar no se listarán en la salida de \hgcmd{status}.  La
razón para esto es que \hgcmd{status} solamente le muestra aquellos
archivos ``interesantes''---los que usted haya modificado o a aquellos
sobre los que usted haya indicado a Mercurial hacerles algo---de forma
predeterminada. Si tiene un repositorio que contiene miles de
archivos, inusualmente deseará saber cuáles de ellos están siendo
seguidos por Mercurial, pero que no han cambiado.  (De todas maneras,
puede obtener tal información; más adelante hablaremos de ello.)


Cuando usted añade un archivo, Mercurial no hace nada con el inmediatamente.
A cambio, tomará una instantánea del estado del archivo la próxima vez
que usted consigne. Continuará haciendo seguimiento a los cambios que
haga sobre el archivo cada vez que consigne, hasta que usted lo elimine.

\subsection{Nombramiento explicíto e implícito de archivos}

Mercurial tiene un comportamiento útil en el cual si a una orden,
le pasa el nombre de un directorio, todas las órdenes lo tratarán como
``Deseo operar en cada archivo de este directorio y sus 
subdirectorios''.
\interaction{daily.files.add-dir}
Tenga en cuenta que en este ejemplo Mercurial imprimió los nombres de
los archivos que se adicionaron, mientras que no lo hizo en el ejemplo
anterior cuando adicionamos el archivo con nombre \filename{a}.

En el último caso hicimos explícito el nombre del archivo que
deseábamos adicionar en la línea de órdenes, y Mercurial asume en
tales casos que usted sabe lo que está haciendo y no imprime
información alguna.

Cuando hacemos \emph{implícitos} los nombres de los archivos dando el
nombre de un directorio, Mercurial efectua un paso extra al imprimir
el nombre de cada archivo con el que va a hacer algo.  Esto para
aclarar lo que está sucediendo, y reducir en lo posible una sorpresa
silenciosa pero fatal.  Este comportamiento es común a la mayoría de
órdenes en Mercurial.

\subsection{Nota al margen:Mercurial trata archivos, no directorios}

Mercurial no da seguimiento a la información de los directorios.  En
lugar de eso tiene en cuenta las rutas de los archivos.  Antes  de
crear un archivo, primero crea todos los directorios que hagan falta
para completar la ruta del archivo. Después de borrar un archivo,
borra todos los directorios vacíos que estuvieran en la ruta del
archivo borrado. Suena como una diferencia trivial, pero tiene una
consecuencia práctica menor: no es posible representar un directorio
completamente vacío en Mercurial.

Los directorios vacíos son inusualmente útiles, hay soluciones
alternativas no intrusivas que puede emplear para obtener el efecto
apropiado. Los desarrolladores de Mercurial pensaron que la
complejidad necesaria para administrar directorios vacíos no valía la
pena frente al beneficio limitado que esta característica podría traer.

Si necesita un directorio vacío en su repositorio, hay algunas formas
de lograrlo. Una es crear un directorio, después hacer \hgcmd{add} a
un archivo ``escondido'' dentro de ese directorio. En sistemas tipo
Unix, cualquier archivo cuyo nombre comience con un punto
(``\texttt{.}'') se trata como escondido por la mayoría de
herramientas GUI. Esta aproximación se ilustra en la figura~\ref{ex:daily:hidden}.

\begin{figure}[ht]
  \interaction{daily.files.hidden}
  \caption{Simular un directorio vacío con un archivo escondido}
  \label{ex:daily:hidden}
\end{figure}

Otra forma de abordar la necesidad de un archivo vacío es crear
simplemente uno en sus guiones de construcción antes de ser necesarios.

\section{Cómo dejar de hacer seguimiento a un archivo}

Si decide que un archivo no pertenece a su repositorio, use la orden
\hgcmd{remove}; se borrará el archivo y le indicará a Mercurial que
deje de hacerle seguimiento.  Los archivos eliminados se representan
con ``\texttt{R}'' al usar \hgcmd{status}.
\interaction{daily.files.remove}

Después de hacer \hgcmd{remove} a un archivo, Mercurial dejará de
hacer seguimiento al mismo, incluso si recrea el archivo con el mismo
nombre en su directorio de trabajo. Si decide recrear un archivo con
el mismo nombre y desea que Mercurial le haga seguimiento, basta con
hacerle \hgcmd{add}. Mercurial sabrá que el archivo recientemente
adicionado no está relacionado con el archivo anterior que tenía el
mismo nombre.

\subsection{Al eliminar un archivo no se afecta su historia}

Es preciso tener en cuenta que al eliminar un archivo se tiene
dos efectos solamente.
\begin{itemize}
\item Se elimina la versión actual del fichero del directorio de 
trabajo.
\item Mercurial deja de hacer seguimiento a los cambios del fichero
  desde la próxima consignación.
\end{itemize}
Al eliminar un fichero \emph{no} se altera de ninguna manera la
\emph{historia} del mismo.

Si actualiza su directorio de trabajo a un conjunto de cambios en el
cual esl archivo que eliminó aún era tenido en cuenta, reaparecerá en
el directorio de trabajo, con los contenidos que este tenía cuando se
consignó tal conjunto de cambios.  Si usted actualiza el directorio de
trabajo a un conjunto de cambios posterior en el cual el archivo había
sido eliminado, Mercurial lo eliminará de nuevo del directorio de
trabajo.

\subsection{Archivos perdidos}

Mercurial considera como \emph{perdido} un archivo que usted borró,
pero para el que no se usó \hgcmd{remove}.  Los archivos perdidos se
representan con ``\texttt{!}'' al visualizar \hgcmd{status}.
Las órdenes de Mercurial generalmente no harán nada con los archivos
perdidos.
\interaction{daily.files.missing}

Si su repositorio contiene un archivo que \hgcmd{status} reporta como
perdido, y desea que el mismo se vaya, se puede usar 
\hgcmdargs{remove}{\hgopt{remove}{--after}} posteriormente para
indicarle a Mercurial que usted deseaba borrar tal archivo.
\interaction{daily.files.remove-after}

Por otro lado, si borró un fichero perdido por accidente, puede usar
\hgcmdargs{revert}{\emph{nombre de fichero}} para recuperar el
fichero. Reaparecerá sin modificaciones.
\interaction{daily.files.recover-missing}

\subsection{Nota al margen: ¿Por qué decirle explícitamente a Mercurial
  que elimine un archivo?}

Es posible que se haya preguntado por qué Mercurial exige que usted le
indique explícitamente que está borrando un archivo. Al principio del
desarrollo de Mercurial, este permitía que usted borrara el archivo
sin más; Mercurial se daría cuanta de la ausencia del archivo
automáticamente después de la ejecución de \hgcmd{commit}, y dejaba de
hacer seguimiento al archivo.  En la práctica, resultaba muy sencillo
borrar un archivo accidentalmente sin darse cuenta.

\subsection{Atajo útil---agregar y eliminar archivos en un solo paso}

Mercurial ofrece una orden combinada, \hgcmd{addremove}, que agrega
los archivos que no tienen seguimiento y marca los archivos faltantes
como eliminados.
\interaction{daily.files.addremove}
La orden \hgcmd{commit} su puede usar con la opción \hgopt{commit}{-A} 
que aplica el agregar-eliminar, seguido inmediatamente de una
consignación.
\interaction{daily.files.commit-addremove}

\section{Copying files}

Mercurial provides a \hgcmd{copy} command that lets you make a new
copy of a file.  When you copy a file using this command, Mercurial
makes a record of the fact that the new file is a copy of the original
file.  It treats these copied files specially when you merge your work
with someone else's.

\subsection{The results of copying during a merge}

What happens during a merge is that changes ``follow'' a copy.  To
best illustrate what this means, let's create an example.  We'll start
with the usual tiny repository that contains a single file.
\interaction{daily.copy.init}
We need to do some work in parallel, so that we'll have something to
merge.  So let's clone our repository.
\interaction{daily.copy.clone}
Back in our initial repository, let's use the \hgcmd{copy} command to
make a copy of the first file we created.
\interaction{daily.copy.copy}

If we look at the output of the \hgcmd{status} command afterwards, the
copied file looks just like a normal added file.
\interaction{daily.copy.status}
But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it
prints another line of output: this is the file that our newly-added
file was copied \emph{from}.
\interaction{daily.copy.status-copy}

Now, back in the repository we cloned, let's make a change in
parallel.  We'll add a line of content to the original file that we
created.
\interaction{daily.copy.other}
Now we have a modified \filename{file} in this repository.  When we
pull the changes from the first repository, and merge the two heads,
Mercurial will propagate the changes that we made locally to
\filename{file} into its copy, \filename{new-file}.
\interaction{daily.copy.merge}

\subsection{Why should changes follow copies?}
\label{sec:daily:why-copy}

This behaviour, of changes to a file propagating out to copies of the
file, might seem esoteric, but in most cases it's highly desirable.

First of all, remember that this propagation \emph{only} happens when
you merge.  So if you \hgcmd{copy} a file, and subsequently modify the
original file during the normal course of your work, nothing will
happen.

The second thing to know is that modifications will only propagate
across a copy as long as the repository that you're pulling changes
from \emph{doesn't know} about the copy.

The reason that Mercurial does this is as follows.  Let's say I make
an important bug fix in a source file, and commit my changes.
Meanwhile, you've decided to \hgcmd{copy} the file in your repository,
without knowing about the bug or having seen the fix, and you have
started hacking on your copy of the file.

If you pulled and merged my changes, and Mercurial \emph{didn't}
propagate changes across copies, your source file would now contain
the bug, and unless you remembered to propagate the bug fix by hand,
the bug would \emph{remain} in your copy of the file.

By automatically propagating the change that fixed the bug from the
original file to the copy, Mercurial prevents this class of problem.
To my knowledge, Mercurial is the \emph{only} revision control system
that propagates changes across copies like this.

Once your change history has a record that the copy and subsequent
merge occurred, there's usually no further need to propagate changes
from the original file to the copied file, and that's why Mercurial
only propagates changes across copies until this point, and no
further.

\subsection{How to make changes \emph{not} follow a copy}

If, for some reason, you decide that this business of automatically
propagating changes across copies is not for you, simply use your
system's normal file copy command (on Unix-like systems, that's
\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy
by hand.  Before you do so, though, please do reread
section~\ref{sec:daily:why-copy}, and make an informed decision that
this behaviour is not appropriate to your specific case.

\subsection{Behaviour of the \hgcmd{copy} command}

When you use the \hgcmd{copy} command, Mercurial makes a copy of each
source file as it currently stands in the working directory.  This
means that if you make some modifications to a file, then \hgcmd{copy}
it without first having committed those changes, the new copy will
also contain the modifications you have made up until that point.  (I
find this behaviour a little counterintuitive, which is why I mention
it here.)

The \hgcmd{copy} command acts similarly to the Unix \command{cp}
command (you can use the \hgcmd{cp} alias if you prefer).  The last
argument is the \emph{destination}, and all prior arguments are
\emph{sources}.  If you pass it a single file as the source, and the
destination does not exist, it creates a new file with that name.
\interaction{daily.copy.simple}
If the destination is a directory, Mercurial copies its sources into
that directory.
\interaction{daily.copy.dir-dest}
Copying a directory is recursive, and preserves the directory
structure of the source.
\interaction{daily.copy.dir-src}
If the source and destination are both directories, the source tree is
recreated in the destination directory.
\interaction{daily.copy.dir-src-dest}

As with the \hgcmd{rename} command, if you copy a file manually and
then want Mercurial to know that you've copied the file, simply use
the \hgopt{copy}{--after} option to \hgcmd{copy}.
\interaction{daily.copy.after}

\section{Renaming files}

It's rather more common to need to rename a file than to make a copy
of it.  The reason I discussed the \hgcmd{copy} command before talking
about renaming files is that Mercurial treats a rename in essentially
the same way as a copy.  Therefore, knowing what Mercurial does when
you copy a file tells you what to expect when you rename a file.

When you use the \hgcmd{rename} command, Mercurial makes a copy of
each source file, then deletes it and marks the file as removed.
\interaction{daily.rename.rename}
The \hgcmd{status} command shows the newly copied file as added, and
the copied-from file as removed.
\interaction{daily.rename.status}
As with the results of a \hgcmd{copy}, we must use the
\hgopt{status}{-C} option to \hgcmd{status} to see that the added file
is really being tracked by Mercurial as a copy of the original, now
removed, file.
\interaction{daily.rename.status-copy}

As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
a rename after the fact using the \hgopt{rename}{--after} option.  In
most other respects, the behaviour of the \hgcmd{rename} command, and
the options it accepts, are similar to the \hgcmd{copy} command.

\subsection{Renaming files and merging changes}

Since Mercurial's rename is implemented as copy-and-remove, the same
propagation of changes happens when you merge after a rename as after
a copy.

If I modify a file, and you rename it to a new name, and then we merge
our respective changes, my modifications to the file under its
original name will be propagated into the file under its new name.
(This is something you might expect to ``simply work,'' but not all
revision control systems actually do this.)

Whereas having changes follow a copy is a feature where you can
perhaps nod and say ``yes, that might be useful,'' it should be clear
that having them follow a rename is definitely important.  Without
this facility, it would simply be too easy for changes to become
orphaned when files are renamed.

\subsection{Divergent renames and merging}

The case of diverging names occurs when two developers start with a
file---let's call it \filename{foo}---in their respective
repositories.

\interaction{rename.divergent.clone}
Anne renames the file to \filename{bar}.
\interaction{rename.divergent.rename.anne}
Meanwhile, Bob renames it to \filename{quux}.
\interaction{rename.divergent.rename.bob}

I like to think of this as a conflict because each developer has
expressed different intentions about what the file ought to be named.

What do you think should happen when they merge their work?
Mercurial's actual behaviour is that it always preserves \emph{both}
names when it merges changesets that contain divergent renames.
\interaction{rename.divergent.merge}

Notice that Mercurial does warn about the divergent renames, but it
leaves it up to you to do something about the divergence after the merge.

\subsection{Convergent renames and merging}

Another kind of rename conflict occurs when two people choose to
rename different \emph{source} files to the same \emph{destination}.
In this case, Mercurial runs its normal merge machinery, and lets you
guide it to a suitable resolution.

\subsection{Other name-related corner cases}

Mercurial has a longstanding bug in which it fails to handle a merge
where one side has a file with a given name, while another has a
directory with the same name.  This is documented as~\bug{29}.
\interaction{issue29.go}

\section{Recovering from mistakes}

Mercurial has some useful commands that will help you to recover from
some common mistakes.

The \hgcmd{revert} command lets you undo changes that you have made to
your working directory.  For example, if you \hgcmd{add} a file by
accident, just run \hgcmd{revert} with the name of the file you added,
and while the file won't be touched in any way, it won't be tracked
for adding by Mercurial any longer, either.  You can also use
\hgcmd{revert} to get rid of erroneous changes to a file.

It's useful to remember that the \hgcmd{revert} command is useful for
changes that you have not yet committed.  Once you've committed a
change, if you decide it was a mistake, you can still do something
about it, though your options may be more limited.

For more information about the \hgcmd{revert} command, and details
about how to deal with changes you have already committed, see
chapter~\ref{chap:undo}.

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "00book"
%%% End: