hgbook
annotate en/daily.tex @ 168:f8b5b782e150
Backed out changeset 08a4467f489162c14cf17b94aa771a23dd6f02dc
It just didn't work. Sigh.
It just didn't work. Sigh.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Mon Mar 26 23:20:59 2007 -0700 (2007-03-26) |
parents | 9094c9fda8ec |
children | 1b55292716a4 |
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 |
bos@117 | 44 makes in such cases is that we 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@118 | 250 means that if you make some modifications to a file, then copy it |
bos@118 | 251 without first having committed those changes, the new copy will |
bos@118 | 252 contain your modifications. |
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@118 | 272 the \hgopt{--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@156 | 338 I personally find this behaviour quite surprising, which is why I |
bos@156 | 339 wanted to explicitly mention it here. I would have expected Mercurial |
bos@156 | 340 to prompt me with a three-way choice instead: do I want to keep only |
bos@156 | 341 \filename{bar}, only \filename{quux}, or both? |
bos@156 | 342 |
bos@156 | 343 In practice, when you rename a source file, it is likely that you will |
bos@156 | 344 also modify another file (such as a makefile) that knows how to build |
bos@156 | 345 the source file. So what will happen if Anne renames a file and edits |
bos@156 | 346 \filename{Makefile} to build it under its new name, while Bob does the |
bos@156 | 347 same, but chooses a different name for the file, is that after the |
bos@156 | 348 merge, there will be two copies of the source file in the working |
bos@156 | 349 directory under different names, \emph{and} a conflict in the section |
bos@156 | 350 of the \filename{Makefile} that both Bob and Anne edited. |
bos@156 | 351 |
bos@156 | 352 This behaviour is considered surprising by other people, too: |
bos@156 | 353 see~\bug{455} for details. |
bos@156 | 354 |
bos@156 | 355 \subsection{Convergent renames and merging} |
bos@156 | 356 |
bos@156 | 357 Another kind of rename conflict occurs when two people choose to |
bos@156 | 358 rename different \emph{source} files to the same \emph{destination}. |
bos@156 | 359 In this case, Mercurial runs its normal merge machinery, and lets you |
bos@156 | 360 guide it to a suitable resolution. |
bos@156 | 361 |
bos@156 | 362 \subsection{Other name-related corner cases} |
bos@156 | 363 |
bos@156 | 364 Mercurial has a longstanding bug in which it fails to handle a merge |
bos@156 | 365 where one side has a file with a given name, while another has a |
bos@156 | 366 directory with the same name. This is documented as~\bug{29}. |
bos@156 | 367 \interaction{issue29.go} |
bos@121 | 368 |
bos@42 | 369 %%% Local Variables: |
bos@42 | 370 %%% mode: latex |
bos@42 | 371 %%% TeX-master: "00book" |
bos@42 | 372 %%% End: |