hgbook
annotate en/daily.tex @ 307:fb5c0d56d7f1
Fix test 'tour'.
Executing 'tour' test now creates some files in /tmp to store the
revision numbers as they are created on the fly and appear in the output
files. When SVG files are to be converted to PNG or EPS files within the
Makefile, a tool 'fixsvg' will be invoked to substitute some placeholder
markup by the real version number which fits to the test output, before
the final conversion takes place.
Executing 'tour' test now creates some files in /tmp to store the
revision numbers as they are created on the fly and appear in the output
files. When SVG files are to be converted to PNG or EPS files within the
Makefile, a tool 'fixsvg' will be invoked to substitute some placeholder
markup by the real version number which fits to the test output, before
the final conversion takes place.
author | Guido Ostkamp <hg@ostkamp.fastmail.fm> |
---|---|
date | Wed Aug 20 22:15:35 2008 +0200 (2008-08-20) |
parents | abebe72451d6 |
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@117 | 139 \subsection{Aside: why tell Mercurial explicitly to |
bos@117 | 140 remove a file?} |
bos@117 | 141 |
bos@117 | 142 You might wonder why Mercurial requires you to explicitly tell it that |
bos@117 | 143 you are deleting a file. Early during the development of Mercurial, |
bos@117 | 144 it let you delete a file however you pleased; Mercurial would notice |
bos@117 | 145 the absence of the file automatically when you next ran a |
bos@117 | 146 \hgcmd{commit}, and stop tracking the file. In practice, this made it |
bos@117 | 147 too easy to accidentally remove a file without noticing. |
bos@117 | 148 |
bos@117 | 149 \subsection{Useful shorthand---adding and removing files |
bos@117 | 150 in one step} |
bos@42 | 151 |
bos@43 | 152 Mercurial offers a combination command, \hgcmd{addremove}, that adds |
bos@117 | 153 untracked files and marks missing files as removed. |
bos@117 | 154 \interaction{daily.files.addremove} |
bos@117 | 155 The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option |
bos@117 | 156 that performs this same add-and-remove, immediately followed by a |
bos@117 | 157 commit. |
bos@117 | 158 \interaction{daily.files.commit-addremove} |
bos@117 | 159 |
bos@117 | 160 \section{Copying files} |
bos@117 | 161 |
bos@117 | 162 Mercurial provides a \hgcmd{copy} command that lets you make a new |
bos@117 | 163 copy of a file. When you copy a file using this command, Mercurial |
bos@117 | 164 makes a record of the fact that the new file is a copy of the original |
bos@117 | 165 file. It treats these copied files specially when you merge your work |
bos@117 | 166 with someone else's. |
bos@117 | 167 |
bos@121 | 168 \subsection{The results of copying during a merge} |
bos@121 | 169 |
bos@117 | 170 What happens during a merge is that changes ``follow'' a copy. To |
bos@117 | 171 best illustrate what this means, let's create an example. We'll start |
bos@117 | 172 with the usual tiny repository that contains a single file. |
bos@117 | 173 \interaction{daily.copy.init} |
bos@117 | 174 We need to do some work in parallel, so that we'll have something to |
bos@117 | 175 merge. So let's clone our repository. |
bos@117 | 176 \interaction{daily.copy.clone} |
bos@117 | 177 Back in our initial repository, let's use the \hgcmd{copy} command to |
bos@117 | 178 make a copy of the first file we created. |
bos@117 | 179 \interaction{daily.copy.copy} |
bos@117 | 180 |
bos@117 | 181 If we look at the output of the \hgcmd{status} command afterwards, the |
bos@117 | 182 copied file looks just like a normal added file. |
bos@117 | 183 \interaction{daily.copy.status} |
bos@117 | 184 But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it |
bos@117 | 185 prints another line of output: this is the file that our newly-added |
bos@117 | 186 file was copied \emph{from}. |
bos@117 | 187 \interaction{daily.copy.status-copy} |
bos@117 | 188 |
bos@117 | 189 Now, back in the repository we cloned, let's make a change in |
bos@117 | 190 parallel. We'll add a line of content to the original file that we |
bos@117 | 191 created. |
bos@117 | 192 \interaction{daily.copy.other} |
bos@117 | 193 Now we have a modified \filename{file} in this repository. When we |
bos@117 | 194 pull the changes from the first repository, and merge the two heads, |
bos@117 | 195 Mercurial will propagate the changes that we made locally to |
bos@117 | 196 \filename{file} into its copy, \filename{new-file}. |
bos@117 | 197 \interaction{daily.copy.merge} |
bos@117 | 198 |
bos@117 | 199 \subsection{Why should changes follow copies?} |
bos@117 | 200 \label{sec:daily:why-copy} |
bos@117 | 201 |
bos@117 | 202 This behaviour, of changes to a file propagating out to copies of the |
bos@117 | 203 file, might seem esoteric, but in most cases it's highly desirable. |
bos@117 | 204 |
bos@117 | 205 First of all, remember that this propagation \emph{only} happens when |
bos@117 | 206 you merge. So if you \hgcmd{copy} a file, and subsequently modify the |
bos@117 | 207 original file during the normal course of your work, nothing will |
bos@117 | 208 happen. |
bos@117 | 209 |
bos@117 | 210 The second thing to know is that modifications will only propagate |
bos@117 | 211 across a copy as long as the repository that you're pulling changes |
bos@117 | 212 from \emph{doesn't know} about the copy. |
bos@117 | 213 |
bos@117 | 214 The reason that Mercurial does this is as follows. Let's say I make |
bos@117 | 215 an important bug fix in a source file, and commit my changes. |
bos@117 | 216 Meanwhile, you've decided to \hgcmd{copy} the file in your repository, |
bos@117 | 217 without knowing about the bug or having seen the fix, and you have |
bos@117 | 218 started hacking on your copy of the file. |
bos@117 | 219 |
bos@117 | 220 If you pulled and merged my changes, and Mercurial \emph{didn't} |
bos@117 | 221 propagate changes across copies, your source file would now contain |
bos@117 | 222 the bug, and unless you remembered to propagate the bug fix by hand, |
bos@117 | 223 the bug would \emph{remain} in your copy of the file. |
bos@117 | 224 |
bos@117 | 225 By automatically propagating the change that fixed the bug from the |
bos@117 | 226 original file to the copy, Mercurial prevents this class of problem. |
bos@117 | 227 To my knowledge, Mercurial is the \emph{only} revision control system |
bos@117 | 228 that propagates changes across copies like this. |
bos@117 | 229 |
bos@117 | 230 Once your change history has a record that the copy and subsequent |
bos@117 | 231 merge occurred, there's usually no further need to propagate changes |
bos@117 | 232 from the original file to the copied file, and that's why Mercurial |
bos@117 | 233 only propagates changes across copies until this point, and no |
bos@117 | 234 further. |
bos@117 | 235 |
bos@117 | 236 \subsection{How to make changes \emph{not} follow a copy} |
bos@117 | 237 |
bos@117 | 238 If, for some reason, you decide that this business of automatically |
bos@117 | 239 propagating changes across copies is not for you, simply use your |
bos@117 | 240 system's normal file copy command (on Unix-like systems, that's |
bos@117 | 241 \command{cp}) to make a copy of a file, then \hgcmd{add} the new copy |
bos@117 | 242 by hand. Before you do so, though, please do reread |
bos@117 | 243 section~\ref{sec:daily:why-copy}, and make an informed decision that |
bos@117 | 244 this behaviour is not appropriate to your specific case. |
bos@117 | 245 |
bos@117 | 246 \subsection{Behaviour of the \hgcmd{copy} command} |
bos@117 | 247 |
bos@118 | 248 When you use the \hgcmd{copy} command, Mercurial makes a copy of each |
bos@118 | 249 source file as it currently stands in the working directory. This |
bos@181 | 250 means that if you make some modifications to a file, then \hgcmd{copy} |
bos@181 | 251 it without first having committed those changes, the new copy will |
bos@181 | 252 also contain the modifications you have made up until that point. (I |
bos@181 | 253 find this behaviour a little counterintuitive, which is why I mention |
bos@181 | 254 it here.) |
bos@118 | 255 |
bos@117 | 256 The \hgcmd{copy} command acts similarly to the Unix \command{cp} |
bos@118 | 257 command (you can use the \hgcmd{cp} alias if you prefer). The last |
bos@118 | 258 argument is the \emph{destination}, and all prior arguments are |
bos@118 | 259 \emph{sources}. If you pass it a single file as the source, and the |
bos@118 | 260 destination does not exist, it creates a new file with that name. |
bos@117 | 261 \interaction{daily.copy.simple} |
bos@117 | 262 If the destination is a directory, Mercurial copies its sources into |
bos@117 | 263 that directory. |
bos@117 | 264 \interaction{daily.copy.dir-dest} |
bos@117 | 265 Copying a directory is recursive, and preserves the directory |
bos@117 | 266 structure of the source. |
bos@117 | 267 \interaction{daily.copy.dir-src} |
bos@117 | 268 If the source and destination are both directories, the source tree is |
bos@117 | 269 recreated in the destination directory. |
bos@117 | 270 \interaction{daily.copy.dir-src-dest} |
bos@117 | 271 |
bos@118 | 272 As with the \hgcmd{rename} command, if you copy a file manually and |
bos@118 | 273 then want Mercurial to know that you've copied the file, simply use |
bos@236 | 274 the \hgopt{copy}{--after} option to \hgcmd{copy}. |
bos@118 | 275 \interaction{daily.copy.after} |
bos@118 | 276 |
bos@117 | 277 \section{Renaming files} |
bos@43 | 278 |
bos@118 | 279 It's rather more common to need to rename a file than to make a copy |
bos@118 | 280 of it. The reason I discussed the \hgcmd{copy} command before talking |
bos@118 | 281 about renaming files is that Mercurial treats a rename in essentially |
bos@118 | 282 the same way as a copy. Therefore, knowing what Mercurial does when |
bos@118 | 283 you copy a file tells you what to expect when you rename a file. |
bos@118 | 284 |
bos@118 | 285 When you use the \hgcmd{rename} command, Mercurial makes a copy of |
bos@118 | 286 each source file, then deletes it and marks the file as removed. |
bos@118 | 287 \interaction{daily.rename.rename} |
bos@118 | 288 The \hgcmd{status} command shows the newly copied file as added, and |
bos@118 | 289 the copied-from file as removed. |
bos@118 | 290 \interaction{daily.rename.status} |
bos@118 | 291 As with the results of a \hgcmd{copy}, we must use the |
bos@118 | 292 \hgopt{status}{-C} option to \hgcmd{status} to see that the added file |
bos@118 | 293 is really being tracked by Mercurial as a copy of the original, now |
bos@118 | 294 removed, file. |
bos@118 | 295 \interaction{daily.rename.status-copy} |
bos@118 | 296 |
bos@118 | 297 As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about |
bos@118 | 298 a rename after the fact using the \hgopt{rename}{--after} option. In |
bos@118 | 299 most other respects, the behaviour of the \hgcmd{rename} command, and |
bos@118 | 300 the options it accepts, are similar to the \hgcmd{copy} command. |
bos@118 | 301 |
bos@118 | 302 \subsection{Renaming files and merging changes} |
bos@118 | 303 |
bos@118 | 304 Since Mercurial's rename is implemented as copy-and-remove, the same |
bos@118 | 305 propagation of changes happens when you merge after a rename as after |
bos@118 | 306 a copy. |
bos@118 | 307 |
bos@156 | 308 If I modify a file, and you rename it to a new name, and then we merge |
bos@156 | 309 our respective changes, my modifications to the file under its |
bos@156 | 310 original name will be propagated into the file under its new name. |
bos@156 | 311 (This is something you might expect to ``simply work,'' but not all |
bos@156 | 312 revision control systems actually do this.) |
bos@43 | 313 |
bos@121 | 314 Whereas having changes follow a copy is a feature where you can |
bos@121 | 315 perhaps nod and say ``yes, that might be useful,'' it should be clear |
bos@121 | 316 that having them follow a rename is definitely important. Without |
bos@121 | 317 this facility, it would simply be too easy for changes to become |
bos@121 | 318 orphaned when files are renamed. |
bos@121 | 319 |
bos@156 | 320 \subsection{Divergent renames and merging} |
bos@156 | 321 |
bos@156 | 322 The case of diverging names occurs when two developers start with a |
bos@156 | 323 file---let's call it \filename{foo}---in their respective |
bos@156 | 324 repositories. |
bos@156 | 325 |
bos@156 | 326 \interaction{rename.divergent.clone} |
bos@156 | 327 Anne renames the file to \filename{bar}. |
bos@156 | 328 \interaction{rename.divergent.rename.anne} |
bos@156 | 329 Meanwhile, Bob renames it to \filename{quux}. |
bos@156 | 330 \interaction{rename.divergent.rename.bob} |
bos@156 | 331 |
bos@156 | 332 I like to think of this as a conflict because each developer has |
bos@156 | 333 expressed different intentions about what the file ought to be named. |
bos@156 | 334 |
bos@156 | 335 What do you think should happen when they merge their work? |
bos@156 | 336 Mercurial's actual behaviour is that it always preserves \emph{both} |
bos@156 | 337 names when it merges changesets that contain divergent renames. |
bos@156 | 338 \interaction{rename.divergent.merge} |
bos@156 | 339 |
bos@273 | 340 Notice that Mercurial does warn about the divergent renames, but it |
bos@273 | 341 leaves it up to you to do something about the divergence after the merge. |
bos@156 | 342 |
bos@156 | 343 \subsection{Convergent renames and merging} |
bos@156 | 344 |
bos@156 | 345 Another kind of rename conflict occurs when two people choose to |
bos@156 | 346 rename different \emph{source} files to the same \emph{destination}. |
bos@156 | 347 In this case, Mercurial runs its normal merge machinery, and lets you |
bos@156 | 348 guide it to a suitable resolution. |
bos@156 | 349 |
bos@156 | 350 \subsection{Other name-related corner cases} |
bos@156 | 351 |
bos@156 | 352 Mercurial has a longstanding bug in which it fails to handle a merge |
bos@156 | 353 where one side has a file with a given name, while another has a |
bos@156 | 354 directory with the same name. This is documented as~\bug{29}. |
bos@156 | 355 \interaction{issue29.go} |
bos@121 | 356 |
bos@180 | 357 \section{Recovering from mistakes} |
bos@180 | 358 |
bos@180 | 359 Mercurial has some useful commands that will help you to recover from |
bos@180 | 360 some common mistakes. |
bos@180 | 361 |
bos@180 | 362 The \hgcmd{revert} command lets you undo changes that you have made to |
bos@180 | 363 your working directory. For example, if you \hgcmd{add} a file by |
bos@180 | 364 accident, just run \hgcmd{revert} with the name of the file you added, |
bos@180 | 365 and while the file won't be touched in any way, it won't be tracked |
bos@180 | 366 for adding by Mercurial any longer, either. You can also use |
bos@180 | 367 \hgcmd{revert} to get rid of erroneous changes to a file. |
bos@180 | 368 |
bos@180 | 369 It's useful to remember that the \hgcmd{revert} command is useful for |
bos@180 | 370 changes that you have not yet committed. Once you've committed a |
bos@180 | 371 change, if you decide it was a mistake, you can still do something |
bos@180 | 372 about it, though your options may be more limited. |
bos@180 | 373 |
bos@180 | 374 For more information about the \hgcmd{revert} command, and details |
bos@180 | 375 about how to deal with changes you have already committed, see |
bos@182 | 376 chapter~\ref{chap:undo}. |
bos@180 | 377 |
bos@42 | 378 %%% Local Variables: |
bos@42 | 379 %%% mode: latex |
bos@42 | 380 %%% TeX-master: "00book" |
bos@42 | 381 %%% End: |