hgbook

annotate en/ch05-daily.tex @ 558:8631da51309b

Slow progress on XML conversion
author Bryan O'Sullivan <bos@serpentine.com>
date Mon Feb 09 23:25:40 2009 -0800 (2009-02-09)
parents 5cd47f721686
children
rev   line source
bos@42 1 \chapter{Mercurial in daily use}
bos@42 2 \label{chap:daily}
bos@42 3
bos@117 4 \section{Telling Mercurial which files to track}
bos@42 5
bos@42 6 Mercurial does not work with files in your repository unless you tell
bos@42 7 it to manage them. The \hgcmd{status} command will tell you which
bos@42 8 files Mercurial doesn't know about; it uses a ``\texttt{?}'' to
bos@42 9 display such files.
bos@42 10
bos@42 11 To tell Mercurial to track a file, use the \hgcmd{add} command. Once
bos@42 12 you have added a file, the entry in the output of \hgcmd{status} for
bos@42 13 that file changes from ``\texttt{?}'' to ``\texttt{A}''.
bos@117 14 \interaction{daily.files.add}
bos@42 15
bos@42 16 After you run a \hgcmd{commit}, the files that you added before the
bos@42 17 commit will no longer be listed in the output of \hgcmd{status}. The
bos@42 18 reason for this is that \hgcmd{status} only tells you about
bos@117 19 ``interesting'' files---those that you have modified or told Mercurial
bos@117 20 to do something with---by default. If you have a repository that
bos@42 21 contains thousands of files, you will rarely want to know about files
bos@42 22 that Mercurial is tracking, but that have not changed. (You can still
bos@42 23 get this information; we'll return to this later.)
bos@42 24
bos@117 25 Once you add a file, Mercurial doesn't do anything with it
bos@117 26 immediately. Instead, it will take a snapshot of the file's state the
bos@117 27 next time you perform a commit. It will then continue to track the
bos@117 28 changes you make to the file every time you commit, until you remove
bos@117 29 the file.
bos@117 30
bos@117 31 \subsection{Explicit versus implicit file naming}
bos@117 32
bos@117 33 A useful behaviour that Mercurial has is that if you pass the name of
bos@117 34 a directory to a command, every Mercurial command will treat this as
bos@117 35 ``I want to operate on every file in this directory and its
bos@117 36 subdirectories''.
bos@117 37 \interaction{daily.files.add-dir}
bos@117 38 Notice in this example that Mercurial printed the names of the files
bos@117 39 it added, whereas it didn't do so when we added the file named
bos@117 40 \filename{a} in the earlier example.
bos@117 41
bos@117 42 What's going on is that in the former case, we explicitly named the
bos@117 43 file to add on the command line, so the assumption that Mercurial
steve@178 44 makes in such cases is that you know what you were doing, and it
bos@117 45 doesn't print any output.
bos@117 46
bos@117 47 However, when we \emph{imply} the names of files by giving the name of
bos@117 48 a directory, Mercurial takes the extra step of printing the name of
bos@117 49 each file that it does something with. This makes it more clear what
bos@117 50 is happening, and reduces the likelihood of a silent and nasty
bos@117 51 surprise. This behaviour is common to most Mercurial commands.
bos@117 52
bos@117 53 \subsection{Aside: Mercurial tracks files, not directories}
bos@42 54
bos@42 55 Mercurial does not track directory information. Instead, it tracks
bos@117 56 the path to a file. Before creating a file, it first creates any
bos@117 57 missing directory components of the path. After it deletes a file, it
bos@117 58 then deletes any empty directories that were in the deleted file's
bos@117 59 path. This sounds like a trivial distinction, but it has one minor
bos@42 60 practical consequence: it is not possible to represent a completely
bos@42 61 empty directory in Mercurial.
bos@42 62
bos@42 63 Empty directories are rarely useful, and there are unintrusive
bos@42 64 workarounds that you can use to achieve an appropriate effect. The
bos@42 65 developers of Mercurial thus felt that the complexity that would be
bos@42 66 required to manage empty directories was not worth the limited benefit
bos@42 67 this feature would bring.
bos@42 68
bos@42 69 If you need an empty directory in your repository, there are a few
bos@42 70 ways to achieve this. One is to create a directory, then \hgcmd{add} a
bos@42 71 ``hidden'' file to that directory. On Unix-like systems, any file
bos@42 72 name that begins with a period (``\texttt{.}'') is treated as hidden
bos@42 73 by most commands and GUI tools. This approach is illustrated in
bos@43 74 figure~\ref{ex:daily:hidden}.
bos@42 75
bos@42 76 \begin{figure}[ht]
bos@43 77 \interaction{daily.files.hidden}
bos@43 78 \caption{Simulating an empty directory using a hidden file}
bos@43 79 \label{ex:daily:hidden}
bos@42 80 \end{figure}
bos@42 81
bos@42 82 Another way to tackle a need for an empty directory is to simply
bos@42 83 create one in your automated build scripts before they will need it.
bos@42 84
bos@117 85 \section{How to stop tracking a file}
bos@117 86
bos@117 87 Once you decide that a file no longer belongs in your repository, use
bos@42 88 the \hgcmd{remove} command; this deletes the file, and tells Mercurial
bos@43 89 to stop tracking it. A removed file is represented in the output of
bos@43 90 \hgcmd{status} with a ``\texttt{R}''.
bos@117 91 \interaction{daily.files.remove}
bos@117 92
bos@118 93 After you \hgcmd{remove} a file, Mercurial will no longer track
bos@118 94 changes to that file, even if you recreate a file with the same name
bos@118 95 in your working directory. If you do recreate a file with the same
bos@118 96 name and want Mercurial to track the new file, simply \hgcmd{add} it.
bos@118 97 Mercurial will know that the newly added file is not related to the
bos@118 98 old file of the same name.
bos@118 99
bos@118 100 \subsection{Removing a file does not affect its history}
bos@118 101
bos@118 102 It is important to understand that removing a file has only two
bos@118 103 effects.
bos@118 104 \begin{itemize}
bos@118 105 \item It removes the current version of the file from the working
bos@118 106 directory.
bos@118 107 \item It stops Mercurial from tracking changes to the file, from the
bos@118 108 time of the next commit.
bos@118 109 \end{itemize}
bos@118 110 Removing a file \emph{does not} in any way alter the \emph{history} of
bos@118 111 the file.
bos@118 112
bos@118 113 If you update the working directory to a changeset in which a file
bos@118 114 that you have removed was still tracked, it will reappear in the
bos@118 115 working directory, with the contents it had when you committed that
bos@118 116 changeset. If you then update the working directory to a later
bos@118 117 changeset, in which the file had been removed, Mercurial will once
bos@118 118 again remove the file from the working directory.
bos@118 119
bos@117 120 \subsection{Missing files}
bos@42 121
bos@43 122 Mercurial considers a file that you have deleted, but not used
bos@43 123 \hgcmd{remove} to delete, to be \emph{missing}. A missing file is
bos@43 124 represented with ``\texttt{!}'' in the output of \hgcmd{status}.
bos@117 125 Mercurial commands will not generally do anything with missing files.
bos@117 126 \interaction{daily.files.missing}
bos@117 127
bos@117 128 If your repository contains a file that \hgcmd{status} reports as
bos@117 129 missing, and you want the file to stay gone, you can run
bos@117 130 \hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to
bos@117 131 tell Mercurial that you really did mean to remove the file.
bos@117 132 \interaction{daily.files.remove-after}
bos@117 133
bos@117 134 On the other hand, if you deleted the missing file by accident, use
bos@117 135 \hgcmdargs{revert}{\emph{filename}} to recover the file. It will
bos@117 136 reappear, in unmodified form.
bos@117 137 \interaction{daily.files.recover-missing}
bos@117 138
bos@551 139 \subsection{Aside: why tell Mercurial explicitly to remove a file?}
bos@117 140
bos@117 141 You might wonder why Mercurial requires you to explicitly tell it that
bos@117 142 you are deleting a file. Early during the development of Mercurial,
bos@117 143 it let you delete a file however you pleased; Mercurial would notice
bos@117 144 the absence of the file automatically when you next ran a
bos@117 145 \hgcmd{commit}, and stop tracking the file. In practice, this made it
bos@117 146 too easy to accidentally remove a file without noticing.
bos@117 147
bos@551 148 \subsection{Useful shorthand---adding and removing files in one step}
bos@42 149
bos@43 150 Mercurial offers a combination command, \hgcmd{addremove}, that adds
bos@117 151 untracked files and marks missing files as removed.
bos@117 152 \interaction{daily.files.addremove}
bos@117 153 The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option
bos@117 154 that performs this same add-and-remove, immediately followed by a
bos@117 155 commit.
bos@117 156 \interaction{daily.files.commit-addremove}
bos@117 157
bos@117 158 \section{Copying files}
bos@117 159
bos@117 160 Mercurial provides a \hgcmd{copy} command that lets you make a new
bos@117 161 copy of a file. When you copy a file using this command, Mercurial
bos@117 162 makes a record of the fact that the new file is a copy of the original
bos@117 163 file. It treats these copied files specially when you merge your work
bos@117 164 with someone else's.
bos@117 165
bos@121 166 \subsection{The results of copying during a merge}
bos@121 167
bos@117 168 What happens during a merge is that changes ``follow'' a copy. To
bos@117 169 best illustrate what this means, let's create an example. We'll start
bos@117 170 with the usual tiny repository that contains a single file.
bos@117 171 \interaction{daily.copy.init}
bos@117 172 We need to do some work in parallel, so that we'll have something to
bos@117 173 merge. So let's clone our repository.
bos@117 174 \interaction{daily.copy.clone}
bos@117 175 Back in our initial repository, let's use the \hgcmd{copy} command to
bos@117 176 make a copy of the first file we created.
bos@117 177 \interaction{daily.copy.copy}
bos@117 178
bos@117 179 If we look at the output of the \hgcmd{status} command afterwards, the
bos@117 180 copied file looks just like a normal added file.
bos@117 181 \interaction{daily.copy.status}
bos@117 182 But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it
bos@117 183 prints another line of output: this is the file that our newly-added
bos@117 184 file was copied \emph{from}.
bos@117 185 \interaction{daily.copy.status-copy}
bos@117 186
bos@117 187 Now, back in the repository we cloned, let's make a change in
bos@117 188 parallel. We'll add a line of content to the original file that we
bos@117 189 created.
bos@117 190 \interaction{daily.copy.other}
bos@117 191 Now we have a modified \filename{file} in this repository. When we
bos@117 192 pull the changes from the first repository, and merge the two heads,
bos@117 193 Mercurial will propagate the changes that we made locally to
bos@117 194 \filename{file} into its copy, \filename{new-file}.
bos@117 195 \interaction{daily.copy.merge}
bos@117 196
bos@117 197 \subsection{Why should changes follow copies?}
bos@117 198 \label{sec:daily:why-copy}
bos@117 199
bos@117 200 This behaviour, of changes to a file propagating out to copies of the
bos@117 201 file, might seem esoteric, but in most cases it's highly desirable.
bos@117 202
bos@117 203 First of all, remember that this propagation \emph{only} happens when
bos@117 204 you merge. So if you \hgcmd{copy} a file, and subsequently modify the
bos@117 205 original file during the normal course of your work, nothing will
bos@117 206 happen.
bos@117 207
bos@117 208 The second thing to know is that modifications will only propagate
bos@117 209 across a copy as long as the repository that you're pulling changes
bos@117 210 from \emph{doesn't know} about the copy.
bos@117 211
bos@117 212 The reason that Mercurial does this is as follows. Let's say I make
bos@117 213 an important bug fix in a source file, and commit my changes.
bos@117 214 Meanwhile, you've decided to \hgcmd{copy} the file in your repository,
bos@117 215 without knowing about the bug or having seen the fix, and you have
bos@117 216 started hacking on your copy of the file.
bos@117 217
bos@117 218 If you pulled and merged my changes, and Mercurial \emph{didn't}
bos@117 219 propagate changes across copies, your source file would now contain
bos@117 220 the bug, and unless you remembered to propagate the bug fix by hand,
bos@117 221 the bug would \emph{remain} in your copy of the file.
bos@117 222
bos@117 223 By automatically propagating the change that fixed the bug from the
bos@117 224 original file to the copy, Mercurial prevents this class of problem.
bos@117 225 To my knowledge, Mercurial is the \emph{only} revision control system
bos@117 226 that propagates changes across copies like this.
bos@117 227
bos@117 228 Once your change history has a record that the copy and subsequent
bos@117 229 merge occurred, there's usually no further need to propagate changes
bos@117 230 from the original file to the copied file, and that's why Mercurial
bos@117 231 only propagates changes across copies until this point, and no
bos@117 232 further.
bos@117 233
bos@117 234 \subsection{How to make changes \emph{not} follow a copy}
bos@117 235
bos@117 236 If, for some reason, you decide that this business of automatically
bos@117 237 propagating changes across copies is not for you, simply use your
bos@117 238 system's normal file copy command (on Unix-like systems, that's
bos@117 239 \command{cp}) to make a copy of a file, then \hgcmd{add} the new copy
bos@117 240 by hand. Before you do so, though, please do reread
bos@117 241 section~\ref{sec:daily:why-copy}, and make an informed decision that
bos@117 242 this behaviour is not appropriate to your specific case.
bos@117 243
bos@117 244 \subsection{Behaviour of the \hgcmd{copy} command}
bos@117 245
bos@118 246 When you use the \hgcmd{copy} command, Mercurial makes a copy of each
bos@118 247 source file as it currently stands in the working directory. This
bos@181 248 means that if you make some modifications to a file, then \hgcmd{copy}
bos@181 249 it without first having committed those changes, the new copy will
bos@181 250 also contain the modifications you have made up until that point. (I
bos@181 251 find this behaviour a little counterintuitive, which is why I mention
bos@181 252 it here.)
bos@118 253
bos@117 254 The \hgcmd{copy} command acts similarly to the Unix \command{cp}
bos@118 255 command (you can use the \hgcmd{cp} alias if you prefer). The last
bos@118 256 argument is the \emph{destination}, and all prior arguments are
bos@118 257 \emph{sources}. If you pass it a single file as the source, and the
bos@118 258 destination does not exist, it creates a new file with that name.
bos@117 259 \interaction{daily.copy.simple}
bos@117 260 If the destination is a directory, Mercurial copies its sources into
bos@117 261 that directory.
bos@117 262 \interaction{daily.copy.dir-dest}
bos@117 263 Copying a directory is recursive, and preserves the directory
bos@117 264 structure of the source.
bos@117 265 \interaction{daily.copy.dir-src}
bos@117 266 If the source and destination are both directories, the source tree is
bos@117 267 recreated in the destination directory.
bos@117 268 \interaction{daily.copy.dir-src-dest}
bos@117 269
bos@118 270 As with the \hgcmd{rename} command, if you copy a file manually and
bos@118 271 then want Mercurial to know that you've copied the file, simply use
bos@236 272 the \hgopt{copy}{--after} option to \hgcmd{copy}.
bos@118 273 \interaction{daily.copy.after}
bos@118 274
bos@117 275 \section{Renaming files}
bos@43 276
bos@118 277 It's rather more common to need to rename a file than to make a copy
bos@118 278 of it. The reason I discussed the \hgcmd{copy} command before talking
bos@118 279 about renaming files is that Mercurial treats a rename in essentially
bos@118 280 the same way as a copy. Therefore, knowing what Mercurial does when
bos@118 281 you copy a file tells you what to expect when you rename a file.
bos@118 282
bos@118 283 When you use the \hgcmd{rename} command, Mercurial makes a copy of
bos@118 284 each source file, then deletes it and marks the file as removed.
bos@118 285 \interaction{daily.rename.rename}
bos@118 286 The \hgcmd{status} command shows the newly copied file as added, and
bos@118 287 the copied-from file as removed.
bos@118 288 \interaction{daily.rename.status}
bos@118 289 As with the results of a \hgcmd{copy}, we must use the
bos@118 290 \hgopt{status}{-C} option to \hgcmd{status} to see that the added file
bos@118 291 is really being tracked by Mercurial as a copy of the original, now
bos@118 292 removed, file.
bos@118 293 \interaction{daily.rename.status-copy}
bos@118 294
bos@118 295 As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
bos@118 296 a rename after the fact using the \hgopt{rename}{--after} option. In
bos@118 297 most other respects, the behaviour of the \hgcmd{rename} command, and
bos@118 298 the options it accepts, are similar to the \hgcmd{copy} command.
bos@118 299
bos@118 300 \subsection{Renaming files and merging changes}
bos@118 301
bos@118 302 Since Mercurial's rename is implemented as copy-and-remove, the same
bos@118 303 propagation of changes happens when you merge after a rename as after
bos@118 304 a copy.
bos@118 305
bos@156 306 If I modify a file, and you rename it to a new name, and then we merge
bos@156 307 our respective changes, my modifications to the file under its
bos@156 308 original name will be propagated into the file under its new name.
bos@156 309 (This is something you might expect to ``simply work,'' but not all
bos@156 310 revision control systems actually do this.)
bos@43 311
bos@121 312 Whereas having changes follow a copy is a feature where you can
bos@121 313 perhaps nod and say ``yes, that might be useful,'' it should be clear
bos@121 314 that having them follow a rename is definitely important. Without
bos@121 315 this facility, it would simply be too easy for changes to become
bos@121 316 orphaned when files are renamed.
bos@121 317
bos@156 318 \subsection{Divergent renames and merging}
bos@156 319
bos@156 320 The case of diverging names occurs when two developers start with a
bos@156 321 file---let's call it \filename{foo}---in their respective
bos@156 322 repositories.
bos@156 323
bos@156 324 \interaction{rename.divergent.clone}
bos@156 325 Anne renames the file to \filename{bar}.
bos@156 326 \interaction{rename.divergent.rename.anne}
bos@156 327 Meanwhile, Bob renames it to \filename{quux}.
bos@156 328 \interaction{rename.divergent.rename.bob}
bos@156 329
bos@156 330 I like to think of this as a conflict because each developer has
bos@156 331 expressed different intentions about what the file ought to be named.
bos@156 332
bos@156 333 What do you think should happen when they merge their work?
bos@156 334 Mercurial's actual behaviour is that it always preserves \emph{both}
bos@156 335 names when it merges changesets that contain divergent renames.
bos@156 336 \interaction{rename.divergent.merge}
bos@156 337
bos@273 338 Notice that Mercurial does warn about the divergent renames, but it
bos@273 339 leaves it up to you to do something about the divergence after the merge.
bos@156 340
bos@156 341 \subsection{Convergent renames and merging}
bos@156 342
bos@156 343 Another kind of rename conflict occurs when two people choose to
bos@156 344 rename different \emph{source} files to the same \emph{destination}.
bos@156 345 In this case, Mercurial runs its normal merge machinery, and lets you
bos@156 346 guide it to a suitable resolution.
bos@156 347
bos@156 348 \subsection{Other name-related corner cases}
bos@156 349
bos@156 350 Mercurial has a longstanding bug in which it fails to handle a merge
bos@156 351 where one side has a file with a given name, while another has a
bos@156 352 directory with the same name. This is documented as~\bug{29}.
bos@156 353 \interaction{issue29.go}
bos@121 354
bos@180 355 \section{Recovering from mistakes}
bos@180 356
bos@180 357 Mercurial has some useful commands that will help you to recover from
bos@180 358 some common mistakes.
bos@180 359
bos@180 360 The \hgcmd{revert} command lets you undo changes that you have made to
bos@180 361 your working directory. For example, if you \hgcmd{add} a file by
bos@180 362 accident, just run \hgcmd{revert} with the name of the file you added,
bos@180 363 and while the file won't be touched in any way, it won't be tracked
bos@180 364 for adding by Mercurial any longer, either. You can also use
bos@180 365 \hgcmd{revert} to get rid of erroneous changes to a file.
bos@180 366
bos@180 367 It's useful to remember that the \hgcmd{revert} command is useful for
bos@180 368 changes that you have not yet committed. Once you've committed a
bos@180 369 change, if you decide it was a mistake, you can still do something
bos@180 370 about it, though your options may be more limited.
bos@180 371
bos@180 372 For more information about the \hgcmd{revert} command, and details
bos@180 373 about how to deal with changes you have already committed, see
bos@182 374 chapter~\ref{chap:undo}.
bos@180 375
bos@42 376 %%% Local Variables:
bos@42 377 %%% mode: latex
bos@42 378 %%% TeX-master: "00book"
bos@42 379 %%% End: