1. Ivan Galin
  2. hgbook-ru

Source

hgbook-ru / ru / ch05-daily.xml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->

<chapter id="chap:daily">
  <?dbhtml filename="mercurial-in-daily-use.html"?>
  <title>Повседневное использование Mercurial</title>

  <sect1>
    <title>Указание Mercurial, какие файлы необходимо отслеживать</title>

    <para id="x_1a3">Mercurial не работает с файлами в хранилище, пока вы не скажете ему, чтобы он управлял ими. Команда <command role="hg-cmd">hg status</command> покажет о каких файлах Mercurial не знает, он использует <quote><literal>?</literal></quote> для отображения таких файлов.</para>

    <para id="x_1a4">Чтобы сказать Mercurial отслеживать файлы, используйте команду <command role="hg-cmd">hg add</command>. После того, как вы добавили файл, запись в результатах <command role="hg-cmd">hg status</command> для этого файла изменится с <quote><literal>?</literal></quote> на <quote><literal>A</literal></quote>.</para>

      &interaction.daily.files.add;

    <para id="x_1a5">После запуска <command role="hg-cmd">hg commit</command> файлы, которые вы добавили перед фиксацией не будут отображаться в выводе <command role="hg-cmd">hg status</command>. Дело в том, что <command role="hg-cmd">hg status</command> по умолчанию сообщает только о <quote>интересных</quote> файлах &emdash; о тех, что вы модифицировали, либо указали Mercurial'у сделать что-либо с ними.  Если ваш репозиторий содержит тысячи файлов, то вам редко понадобится информация обо всех не измененных файлах, которые отслеживает Mercurial. (Вы можете узнать и о них; мы вернемся к этому позже.)</para>

    <para id="x_1a6">Когда вы добавляете файл, Mercurial сразу ничего с ним не делает. Только после фиксации Mercurial сделает снимок состояния файла. Он будет продолжать отслеживать изменения каждый раз после фиксации, до тех пор пока файл не будет удален.</para>

    <sect2>
      <title>Явное и неявное именование файлов</title>

      <para id="x_1a7">При выполнении любой команды, если вы не указываете имя файла, Mercurial понимает это как <quote>Я собираюсь работать со всеми файлами в этом каталоге и его подкаталогах</quote>.</para>

      &interaction.daily.files.add-dir;

      <para id="x_1a8">Обратите внимание, что в данном примере в отличие от предыдущего Mercurial вывел имена добавленных файлов.</para>

      <para id="x_1a9">Когда, как в предыдущем случае, мы явно указываем имя файла добавляемого в командной строке. Mercurial делает предположение, что вы знаете, что делаете, и не выводит ничего.</para>

      <para id="x_1aa">Однако, когда мы <emphasis>подразумеваем</emphasis> файлы, указывая только имя каталога, Mercurial дополнительно выводит имя каждого обработанного файла. Это делает процесс более прозрачным и уменьшает вероятность незаметных неприятных сюрпризов. Такое поведение свойственно большинству команд Mercurial.</para>
    </sect2>

    <sect2>
      <title>Mercurial отслеживает файлы, а не каталоги</title>

      <para id="x_1ab">Mercurial не отслеживает информацию о каталогах. Вместо этого он отслеживает путь к файлу. Перед созданием файла он создает недостающие каталоги пути. После удаления &emdash; удаляет все пустые каталоги, которые присутствовали в пути файла. Кажется в этом нет ничего особенного, но имеется незначительное следствие: в Mercurial невозможно содержать пустой каталог.</para>

      <para id="x_1ac">Пустые каталоги нужны не часто, и есть несколько вариантов обойти ограничение, чтобы достичь желаемого эффекта. Разработчики Mercurial полагали, что усложнения, которые потребуются для поддержки управления пустыми каталогами, не стоят незначительных преимуществ данной опции.</para>

      <para id="x_1ad">Если вам требуется пустой каталог в репозитории, есть несколько путей сделать это. Первый &emdash; создать каталог и добавить в него <command role="hg-cmd">hg add</command> скрытый (<quote>hidden</quote>) файл. В Unix-подобных системах любой файл,  имя которого начинается с точки (<quote><literal>.</literal></quote>), рассматривается как скрытый большинством команд и инструментами GUI. Этот метод представлен ниже.</para>

&interaction.daily.files.hidden;

      <para id="x_1ae">Другой вариант удовлетворить потребность в пустой директории &emdash; просто создать необходимый каталог автоматически с помощью скриптов.</para>
    </sect2>
  </sect1>

  <sect1>
    <title>Как прекратить отслеживание файла</title>

    <para id="x_1af">Когда файл больше не нужен в репозитории, используйте команду <command role="hg-cmd">hg remove</command>, которая удаляет файл и указывает Mercurial прекратить его отслеживание. Удаленный файл в выводе <command role="hg-cmd">hg status</command> отображается буквой <quote><literal>R</literal></quote>.</para>

    &interaction.daily.files.remove;

    <para id="x_1b0">После выполнения <command role="hg-cmd">hg remove</command> над файлом Mercurial больше не отслеживает его изменения даже если вы пересоздадите файл с таким же именем в этом каталоге. Если вы создали одноименный файл и хотите, чтобы Mercurial отслеживал новый файл, просто выполните <command role="hg-cmd">hg add</command> с ним. Mercurial будет знать что вновь добавленный файл никак не связан со старым одноименным файлом.</para>

    <sect2>
      <title>Удаление файла не влияет на его историю</title>

      <para id="x_1b1">Важно понимать, что удаление файла, имеет только два результата.</para>
      <itemizedlist>
	<listitem><para id="x_1b2">Удаляется текущая версия файла из рабочего каталога.</para>
	</listitem>
	<listitem><para id="x_1b3">Mercurial  прекращает отслеживать изменения над файлом со следующей фиксации (commit'а)</para>
	</listitem></itemizedlist>
      <para id="x_1b4">Удаление файла в любом случае <emphasis>не</emphasis> меняет <emphasis>историю</emphasis> его изменений.</para>

      <para id="x_1b5">Если вы обновите рабочий каталог до версии, в которой удаленный файл еще отслеживался, то он появится в каталоге и будет содержать данные, которые в нем были на момент фиксации версии. Если вы обновите каталог до более поздней версии, где данный файл уже был удален, Mercurial снова удалит файл из каталога.</para>
    </sect2>

    <sect2>
      <title>Отсутствующие файлы</title>

      <para id="x_1b6">Mercurial считает <emphasis>потерянными</emphasis> файлы, которые вы удалили не используя <command role="hg-cmd">hg remove</command>. Отсутствующие файлы в выводе <command role="hg-cmd">hg status</command> отображаются с <quote><literal>!</literal></quote>. Команды Mercurial как правило ничего не сделают с потерянными файлами.</para>

      &interaction.daily.files.missing;

      <para id="x_1b7">Если в вашем репозитории есть файл, который <command role="hg-cmd">hg status</command> отображает как потерянный, и вы хотите его действительно удалить, вы можете это сделать командой <command role="hg-cmd">hg remove <option role="hg-opt-remove">--after</option></command>.</para>

      &interaction.daily.files.remove-after;

      <para id="x_1b8">С другой стороны если вы случайно удалили файл, используйте команду <command role="hg-cmd">hg revert</command> filename чтобы его восстановить. Файл будет восстановлен в неизмененной форме.</para>

      &interaction.daily.files.recover-missing;
    </sect2>

    <sect2>
      <title>Замечание: почему в Mercurial явно указывается удаление файла?</title>

      <para id="x_1b9">Возможно вы удивитесь, что Mercurial требует явно указывать удаление файла. Раньше при разработке Mercurial можно было удалять файл, когда угодно. Mercurial замечал отсутствие файла автоматически при следующем запуске <command role="hg-cmd">hg commit</command> и прекращал отслеживание файла. На практике выяснилось, что это приводит к случайному незаметному удалению файлов.</para>
    </sect2>

    <sect2>
      <title>Полезное сокращение &emdash; добавление и удаление файлов в один прием</title>

      <para id="x_1ba">Mercurial  предоставляет комбинированную команду <command role="hg-cmd">hg addremove</command>, которая добавляет неотслеживаемые файлы и помечает отсутствующие файлы как удаленные.</para>

      &interaction.daily.files.addremove;

      <para id="x_1bb">Команда <command role="hg-cmd">hg commit</command> также имеет опцию <option role="hg-opt-commit">-A</option>, которая выполняет то же самое добавление-и-удаление, за которыми сразу же следует фиксация.</para>

      &interaction.daily.files.commit-addremove;
    </sect2>
  </sect1>

  <sect1 id="chap:daily.copy">
    <title>Копирование файлов</title>

    <para id="x_1bc">Для создания копии файла Mercurial предоставляет команду <command role="hg-cmd">hg copy</command>. Когда вы копируете файл с помощью этой команды, Mercurial создает запись о том, что новый файл является копией исходного файла. Он использует такие скопированные файлы, когда вы объединяете свою работу с чьей-либо еще.</para>

    <sect2>
      <title>Поведение копии при слиянии</title>

      <para id="x_1bd">При объединении получается, что изменения <quote>преследуют</quote> копии. Чтобы лучше продемонстрировать эту мысль, рассмотрим пример. Для начала возьмем обычный скромный репозиторий с одним файлом.</para>

      &interaction.daily.copy.init;

      <para id="x_1be">Нам необходимо работать параллельно, и затем объединить. Поэтому давайте клонируем наш репозиторий.</para>

      &interaction.daily.copy.clone;

      <para id="x_1bf">Возвращаясь к исходному репозиторию, выполним команду <command role="hg-cmd">hg copy</command>, чтобы сделать копию первого созданного файла.</para>

      &interaction.daily.copy.copy;

      <para id="x_1c0">Если посмотрим вывод команды <command role="hg-cmd">hg status</command>, увидим, что скопированный файл отображается как обычный добавленный файл.</para>

      &interaction.daily.copy.status;

      <para id="x_1c1">Но если мы укажем опцию <option role="hg-opt-status">-C</option> в команде <command role="hg-cmd">hg status</command>, в выводе будет еще одна строка: файл, копия которого была сделана.</para>

      &interaction.daily.copy.status-copy;

      <para id="x_1c2">Теперь, вернувшись к клонированному репозиторию, сделаем параллельные изменения. Добавим строку в исходный файл.</para>

      &interaction.daily.copy.other;

      <para id="x_1c3">Теперь мы имеем измененный файл <filename>file</filename> в этом репозитории. Когда мы подтягиваем изменения из первого репозитория и объединяем две последние ревизии (head), Mercurial переносит изменения, которые были сделаны в файле <filename>file</filename> в его копию <filename>new-file</filename>.</para>

      &interaction.daily.copy.merge;
    </sect2>

    <sect2 id="sec:daily:why-copy">
      <title>Почему изменения следуют за копией?</title>

      <para id="x_1c4">Перенос изменений исходного файла в копии может показаться понятным лишь посвященным, но в большинстве случаев это крайне желательно.</para>

      <para id="x_1c5">Прежде всего напомним, что подобный перенос происходит <emphasis>только</emphasis> при объединении. И если вы делаете <command role="hg-cmd">hg copy</command> файла и последовательно изменяете оригинал в процессе работы, с копией ничего не происходит.</para>

      <para id="x_1c6">Во-вторых, надо понимать, что изменения будут вноситься в копию до тех пор пока репозиторий, из которого подтягиваются изменения, <emphasis>не знает</emphasis> о существовании копии.</para>

      <para id="x_1c7">Mercurial делает это по следующей причине. Представим, что я исправляю серьезный баг в исходнике, и фиксирую изменения. А в то же время вы решаете сделать <command role="hg-cmd">hg copy</command> файла в вашем репозитории, при этом вы ничего не знаете о баге и не видите последней фиксации, и вы начинаете колдовать со своей копией файла.</para>

      <para id="x_1c8">Когда вы подтянули и объединили мои изменения, и Mercurial <emphasis>не</emphasis> перенес изменения в копии, ваш исходник будет содержать баг, и пока вы не вспомните и не перенесете исправление вручную, баг <emphasis>останется</emphasis> не исправленным в вашей копии файла.</para>

      <para id="x_1c9">Благодаря автоматическому переносу зафиксированных изменений от исходного файла к копиям, Mercurial предотвращает подобные проблемы. Насколько мне известно, Mercurial <emphasis>единственная</emphasis> система контроля версий, которая подобным образом переносит изменения в копии.</para>

      <para id="x_1ca">Когда в истории изменений есть запись о появлении копии и последующего объединения, обычно не требуется последующий перенос изменений в исходном файле в копию, и поэтому Mercurial  переносит только те изменения в копию, которые были до этой точки, а не дальнейшие.</para>
    </sect2>

    <sect2>
      <title>Как сделать, чтобы изменения <emphasis>не</emphasis> преследовали копию</title>

      <para id="x_1cb">Если по каким-то причинам вы решили, что дело автоматического переноса изменений в копии не для Вас, то просто используйте обычную системную команду копирования (в Unix-подобных системах, это <command>cp</command>), а затем добавьте файл вручную с помощью <command role="hg-cmd">hg add</command>. Перед тем как это сделать, перечитайте <xref linkend="sec:daily:why-copy"/>, и убедитесь, что в вашем специфическом случае это действительно не нужно.</para>

    </sect2>
    <sect2>
      <title>Поведение команды <command role="hg-cmd">hg copy</command></title>

      <para id="x_1cc">При выполнении команды <command role="hg-cmd">hg copy</command> Mercurial делает копии каждого исходного файла в таком виде, в каком на текущий момент он находится в рабочем каталоге. Это означает, что если вы вносите изменения в файл, а затем делаете его копию без предварительной фиксации изменений, то копия будет содержать изменения, внесенные до момента копирования. (Мне кажется такое поведение нелогичным, поэтому я обращаю внимание здесь.)</para>

      <para id="x_1cd">Действие команды <command role="hg-cmd">hg copy</command> подобно команде <command>cp</command> в Unix (для удобства вы можете использовать алиас <command role="hg-cmd">hg cp</command>). Последний аргумент &emdash; адрес <emphasis>назначения</emphasis>, все предыдущие &emdash; <emphasis>источники</emphasis>.</para>

      <para id="x_685">Если вы указываете единственный файл как источник и файл назначения не существует, будет создан новый файл с этим именем.</para>

      &interaction.daily.copy.simple;
      
      <para id="x_1ce">Если адрес назначения указан каталог, Mercurial сделает копии источников в этот каталог</para>

      &interaction.daily.copy.dir-dest;

      <para id="x_1cf">Копирование каталогов рекурсивно, и сохраняет структуру каталогов источника.</para>

      &interaction.daily.copy.dir-src;

      <para id="x_1d0">Если и источник, и назначение &emdash; каталоги, то дерево каталогов источника будет также создано в каталоге назначения.</para>

	&interaction.daily.copy.dir-src-dest;

      <para id="x_1d1">Также как с командой <command role="hg-cmd">hg remove</command>, если вы создали копии вручную и хотите, чтобы Mercurial знал, что это копии, просто используйте опцию <option role="hg-opt-copy">--after</option> в команде <command role="hg-cmd">hg copy</command>.</para>

      &interaction.daily.copy.after;
    </sect2>
  </sect1>

  <sect1>
    <title>Переименование файлов</title>

    <para id="x_1d2">Переименование файлов обычно используется чаще, чем копирование. Я рассмотрел команду <command role="hg-cmd">hg copy</command> до команды переименования, так как по существу Mercurial воспринимает переименование так же, как копирование. Следовательно, понимание того, как ведет себя Mercurial с копиями, объяснит, чего ожидать от переименования файлов.</para>

    <para id="x_1d3">При выполнении команды <command role="hg-cmd">hg rename</command> Mercurial копирует исходные файлы, затем удаляет их и помечает как удаленные.</para>

      &interaction.daily.rename.rename;

    <para id="x_1d4">Команда <command role="hg-cmd">hg status</command> показывает, что новые файлы были добавлены, а файлы, с которых они были скопированы, удалены.</para>

    &interaction.daily.rename.status;

    <para id="x_1d5">Так же как с результатами <command role="hg-cmd">hg copy</command> мы должны использовать опцию <option role="hg-opt-status">-C</option> команды <command role="hg-cmd">hg status</command>, чтобы увидеть, что добавленный файл действительно отслеживается Mercurial, как исходный, уже удаленный, файл.</para>

    &interaction.daily.rename.status-copy;

    <para id="x_1d6">Так же как и для команд <command role="hg-cmd">hg remove</command> и <command role="hg-cmd">hg copy</command>, вы можете  указать Mercurial о переименовании после выполнения, используя опцию <option role="hg-opt-rename">--after</option>. В большинстве других случаев, поведение команды <command role="hg-cmd">hg rename</command> и ее поддерживаемых опций подобно поведению команды <command role="hg-cmd">hg copy</command>.</para>

    <para id="x_686">Если вы знакомы с командной строкой Unix, вы будете рады узнать, что команда <command role="hg-cmd">hg rename</command> может работать как <command role="hg-cmd">hg mv</command>.</para>

    <sect2>
      <title>Переименование файлов и объединение изменений</title>

      <para id="x_1d7">С тех пор как переименование в Mercurial реализовано как копирование и удаление, после переименования происходит такой же перенос изменений при объединении (merge), как и после копирования.</para>

      <para id="x_1d8">Если вы изменили файл и переименовали его, а затем мы объединяем наши изменения, мои модификации в файле с первоначальным именем будут перенесены в файл с новым именем. (Это кажется достаточно простым действием, однако не во всех системах контроля версий оно работает.)</para>

      <para id="x_1d9">Если по поводу следования изменений за копией вы возможно кивнете и скажете: <quote>Да, это может быть полезно</quote>, то, что касается следования их при переименовании, абсолютно ясно, что это действительно важно. Без этой возможности изменения легко бы оставались осиротевшими при переименовании файлов.</para>
    </sect2>

    <sect2>
      <title>Расходящиеся переименования и слияние</title>

      <para id="x_1da">Расходящиеся переименования происходят, когда два разработчика берутся за один файл &emdash; назовем его <filename>foo</filename> в своих репозиториях.</para>

      &interaction.rename.divergent.clone;

      <para id="x_1db">Анна переименовывает файл в <filename>bar</filename>.</para>

      &interaction.rename.divergent.rename.anne;

      <para id="x_1dc">Тем временем Bob переименовывает его в <filename>quux</filename>. (Помните, что <command role="hg-cmd">hg mv</command> является псевдонимом для <command role="hg-cmd">hg rename</command>.)</para>

	&interaction.rename.divergent.rename.bob;

      <para id="x_1dd">Я расцениваю это как конфликт, потому что каждый разработчик выразил свое мнение о том, как данный файл должен называться.</para>

      <para id="x_1de">Как вы считаете, что должно произойти когда они объединят работу? На самом деле Mercurial всегда сохраняет <emphasis>оба</emphasis> имени при слиянии изменений, которые содержат расходящиеся переименования.</para>

      &interaction.rename.divergent.merge;

      <para id="x_1df">Обратите внимание, что Mercurial  предупредил о наличии расходящихся переименований, но оставил на ваше усмотрение, как с ними поступить после слияния.</para>
    </sect2>

    <sect2>
      <title>Сходящиеся переименования и слияние</title>

      <para id="x_1e0">Другой вариант конфликта возникает, когда два человека переименовывают два разных файла и дают им одно и то же имя. В таком случае Mercurial выполняет стандартное слияние и предоставляет вам управлять им для нахождения подходящего решения.</para>
    </sect2>

    <sect2>
      <title>Другие проблемы с именованием</title>

      <para id="x_1e1">У Mercurial есть давнишний баг, который дает ошибку при выполнении слияния, если с одной стороны имеется некоторый файл, а с другой стороны &emdash; каталог с таким же именем. Баг задокументирован как Mercurial <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue 29</ulink>.</para>

      &interaction.issue29.go;

    </sect2>
  </sect1>

  <sect1>
    <title>Избавление от ошибок</title>

    <para id="x_1e2">У Mercurial есть несколько полезных команд для восстановления после некоторых распространенных ошибок.</para>

    <para id="x_1e3">Команда <command role="hg-cmd">hg revert</command>  позволяет отменить изменения, сделанные в рабочем каталоге. Например, если вы случайно выполнили <command role="hg-cmd">hg add</command>, просто запустите <command role="hg-cmd">hg revert</command>, указав имя добавленного файла, и файл больше не будет считаться добавленным для отслеживания в Mercurial. <command role="hg-cmd">hg revert</command> можно использовать и для отмены от ошибочных изменений в файле.</para>

    <para id="x_1e4">Необходимо помнить, что команда <command role="hg-cmd">hg revert</command> действует только на изменения, которые не были фиксированы. Если вы зафиксировали изменение, но поняли, что произошла ошибка, вы по-прежнему можете ее исправить, хотя возможности будут более ограничены.</para>

    <para id="x_1e5">Дополнительная информация о команде <command role="hg-cmd">hg revert</command> и о том, что можно сделать с зафиксированными изменениями, приведена в <xref linkend="chap:undo"/>.</para>
  </sect1>

  <sect1>
    <title>Работа со сложными слияниями</title>

    <para id="x_687">В сложных и крупных проектах, не редкость слияние двух ревизий является головной болью. Предположим, что существует большой исходный файл, который был сильно отредактирован каждой стороной слияния: это практически неминуемо приведет к конфликтам, некоторые из которых могут потребовать несколько попыток разобраться.</para>

    <para id="x_688">Давайте начнём с простого случая, чтоб увидеть как с этим бороться. Начнем с репозитория, содержащего один файл, и клонируем его дважды.</para>

    &interaction.ch04-resolve.init;

    <para id="x_689">В одном клоне, будем изменять файл по одному пути.</para>

    &interaction.ch04-resolve.left;

    <para id="x_68a">В другом клоне, будем изменять файл по одному пути.</para>

    &interaction.ch04-resolve.right;

    <para id="x_68b">Далее вытянем каждую ревизию в наш первоначальный репозиторий.</para>

    &interaction.ch04-resolve.pull;

    <para id="x_68c">Мы думаем, что теперь в нашем репозитории находится две головных ревизии.</para>

    &interaction.ch04-resolve.heads;

    <para id="x_68d">Обычно, если мы запустим <command role="hg-cmd">hg merge</command> в этот момент, он перенаправит нас в графический интерфейс, который позволит нам решать вручную противоречия в изменениях в файле <filename>myfile.txt</filename>. Однако, чтобы упростить эту задачу для представления здесь, мы хотели бы чтоб слияние провалилось. Вот один из способов, которым мы можем этого добиться.</para>

    &interaction.ch04-resolve.export;

    <para id="x_68e">Мы сообщили механизму слияния Mercurial выполнить команду <command>false</command> (которая, как мы и хотели, потерпит неудачу) если обнаружит, что слияние не может разрешится автоматически.</para>

    <para id="x_68f">Если мы сейчас запустим <command role="hg-cmd">hg merge</command>, он должен остановится, и сообщить о провале.</para>

    &interaction.ch04-resolve.merge;

    <para id="x_690">Даже если мы не заметим, что объединение не удалось, Mercurial не даст нам случайно зафиксировать результат неудачного слияния.</para>

    &interaction.ch04-resolve.cifail;

    <para id="x_691">Когда <command role="hg-cmd">hg commit</command> выполняется неудачно, как в этом случае, можно предположить, что мы используем неправильную команду <command role="hg-cmd">hg resolve</command>. Как обычно, <command role="hg-cmd">hg help resolve</command> выведет полезную справку.</para>

    <sect2>
      <title>Файл анализа состояний</title>

      <para id="x_692">Когда происходит слияние, большая часть файлов, как правило, остаётся без изменений. Для каждого файла, в котором Mercurial  что-то делает, он отслеживает состояние файла.</para>

      <itemizedlist>
	<listitem>
	  <para id="x_693"><emphasis>Разрешенные</emphasis> файлы, которые был успешно объединены, либо автоматически с помощью Mercurial или вручную с помощью человеческого вмешательства.</para>
	</listitem>
	<listitem>
	  <para id="x_694"><emphasis>Неразрешенные</emphasis> файлы &emdash; не были объединены успешно, необходимо уделить дополнительное внимание.</para>
	</listitem>
      </itemizedlist>

      <para id="x_695">Если Mercurial видит <emphasis>любой</emphasis> файл в неразрешенных состояние после слияния, он будет считать, что слияние не увенчались успехом. К счастью, нам не запускать всё слияние с нуля.</para>

      <para id="x_696">Опция <option role="hg-opt-resolve">--list</option> или <option role="hg-opt-resolve">-l</option> команды <command role="hg-cmd">hg resolve</command> печатает состояние каждого объединяемого файла.</para>

      &interaction.ch04-resolve.list;

      <para id="x_697">В выводе <command role="hg-cmd">hg resolve</command>, разрешённые файлы отмечены <literal>R</literal>, а неразрешённые файлы отмечены <literal>U</literal>. Если какие-либо файлы перечислены с <literal>U</literal>, мы знаем, что попытка зафиксировать результаты слияния не удастся.</para>
    </sect2>

    <sect2>
      <title>Разрешение файлов при слиянии</title>

      <para id="x_698">Есть несколько вариантов, чтобы переместить файл из неразрешенного в разрешенное состояние. Самым распространенным является перезапуск <command role="hg-cmd">hg resolve</command>. Если мы будем пропускать отдельные имена файлов или каталогов, он будет повторять слияние неразрешенных файлов в этих местах. Мы также можем использовать опцию <option role="hg-opt-resolve">--all</option> или <option role="hg-opt-resolve">-a</option>, которая заставит повторить слияние для <emphasis>всех</emphasis> нерешенных файлов.</para>

      <para id="x_699">Mercurial также позволяет нам изменять состояние файла напрямую. Мы можем вручную пометить файл как решённый с помощью опции <option role="hg-opt-resolve">--mark</option>, или, как нерешенный используя опцию <option role="hg-opt-resolve">--unmark</option>. Это позволяет очистить особенно грязные сторонние дополнения, и следить за каждым файлом в прогрессе выполнения.</para>
    </sect2>
  </sect1>

  <sect1>
    <title>Более удобные diff-ы</title>

    <para id="x_6c7">Вывода команды <command role="hg-cmd">hg diff</command> по-умолчанию обратно совместимым с обычной командой <command>diff</command>, но имеет некоторые недостатки.</para>

    <para id="x_6c8">Рассмотрим случай, когда мы используем <command role="hg-cmd">hg rename</command> для переименования файла.</para>

    &interaction.ch04-diff.rename.basic;

    <para id="x_6c9">Вывод <command role="hg-cmd">hg diff</command> выше скрывает тот факт, что мы просто переименовали файл. Команда <command role="hg-cmd">hg diff</command> принимает опции <option>--git</option> или <option>-g</option>, чтобы использовать новый формат diff, который отображает такую информацию в более читаемом виде.</para>

    &interaction.ch04-diff.rename.git;

    <para id="x_6ca">Эта функция также помогает в случаях, которые в противном случае могут ввести в заблуждение: файл, который, как представляется, измененился в соответствии с <command role="hg-cmd">hg status</command>, но для которого <command role="hg-cmd">hg diff</command>  ничего не выводит. Такая ситуация может возникнуть, если мы изменили исполняемый файл.</para>

    &interaction.ch04-diff.chmod;

    <para id="x_6cb">Обычная команда <command>diff</command> не обращает внимания на права доступа к файлу, поэтому <command role="hg-cmd">hg diff</command>  ничего по умолчанию не выводит. Если мы запускаем ее с опцией <option>-g</option>, она расскажет нам, что происходит.</para>

    &interaction.ch04-diff.chmod.git;
  </sect1>

  <sect1>
    <title>Какими файлами управлять, а каких избегать</title>

    <para id="x_6cc">Системы управления версиями, как правило, лучше всего в управляют текстовыми файлами, которые написаны людьми, например исходный код, где файлы не меняются от одного изменения к следующему. Некоторые централизованные систем контроля версий могут сносно иметь дело и с бинарными файлами, такими как растровые изображения.</para>

    <para id="x_6cd">Например, команда разработчиков игр, как правило, совмещать ее исходный код и все её двоичный данные (например, данные геометрии, текстуры, карты уровней) в системе контроля версий.</para>

    <para id="x_6ce">Так как, как правило, невозможно объединить два противоречивых изменения в двоичном файле, централизованные систем часто предоставляют механизм блокирования файла, что позволяет пользователю сказать: <quote>Я единственный, кто может редактировать этот файл</quote>.</para>

    <para id="x_6cf">По сравнению с централизованной системой, распределенная система контроля версий меняет некоторые из факторов, которыми руководствуются принимая решение, какими файлами управлять и каким образом.</para>

    <para id="x_6d0">Например, распределенная система контроля версий не может, по своей природе, блокировать файлы. Таким образом, нет встроенного механизма защищающего 2 людей от конфликтующих изменений в двоичном файле. Если у вас есть команда, где несколько человек могут часто редактировать бинарный файл, тогда идея использовать Mercurial или любую другую распределенную систему контроля версий  для управления этими файлами не будет хорошей.</para>

    <para id="x_6d1">При сохранении изменений файлов, как правило Mercurial сохраняет только различия между предыдущей и нынешней версиями файла. Для большинства текстовых файлов, это очень эффективно. Тем не менее, некоторые файлы (в частности, бинарные файлы) записываются таким образом, что даже незначительные изменения в логической структуре файла отражается в изменении во многих или большинстве байтов внутри файла. Например, сжатые файлы, особенно чувствительны к этому. Если различия между каждой последующей версией файла, всегда имеют больший размер, Mercurial не сможет хранить историю изменений файла очень эффективно. Это может повлиять на локальные ресурсы хранения и количество времени, необходимое для копирования хранилища.</para>

    <para id="x_6d2">Чтобы получить представление о том, каким образом это может повлиять на вас на практике, предположим, вы хотите использовать Mercurial для управления документами OpenOffice. OpenOffice хранит документы на диске как сжатый ZIP архив. Изменение даже одной буквы документа в OpenOffice, и приводит к изменению почти каждого байта во всём файле, когда вы его сохраните. Теперь предположим, что файл 2 МБ в размере. Поскольку большая часть файла меняется каждый раз, когда вы сохраняете его, Mercurial придется хранить все 2 МБ файла каждый раз, когда вы фиксируете изменения, даже если с вашей точки зрения, меняется только несколько слов за раз. Частое редактирование файла, не дружественно для системы хранения Mercurial и приведёт к эффекту переполнения хранилища.</para>

    <para id="x_6d3">Еще хуже, если и вы, и кто-то изменяете документ OpenOffice, и не существует удобный способа объединить вашу работу. В самом деле, нет даже хорошего способа сказать, что изменилось между соответствующими ревизиями.</para>

    <para id="x_6d4">Есть, несколько четких рекомендаций относительно конкретных видов файлов, с которыми нужно быть очень осторожными.</para>

    <itemizedlist>
      <listitem>
	<para id="x_6d5">Файлы, которые являются очень большими и несжимаемыми, например, iso cd-rom образы, будет в силу огромных размеров очень медленно клонироваться по сети.</para>
      </listitem>
      <listitem>
	<para id="x_6d6">Файлы, которые сильно меняются от одного изменения к следующему могут быть дорогостоящим для хранения, если вы их изменяете часто, и конфликты из-за одновременного изменения могут быть сопряжено с трудностями.</para>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1>
    <title>Резервные копии и мониторинг.</title>

    <para id="x_6d7">Mercurial поддерживает полную копию истории в каждом клоне, всем, кто использует Mercurial для совместной работы над проектом потенциально могут выступать в качестве источника резервных копий в случае катастрофы. Если центральное хранилище становится недоступным, можно построить просто заменить путем клонирования копии хранилища от другого разработчика и, получить любые изменения, которые, возможно, не видели другие.</para>

    <para id="x_6d8">Достаточно просто использовать Mercurial для оффлайновых резервных копий и удаленных зеркал. Настройка периодического задания (например, через команду <command>cron</command>) на удаленном сервере, чтобы вытаскивать изменения из вашего основного хранилища каждый час. Это будет немого сложнее в маловероятном случае, когда вы поддерживаете часто изменяемый набор мастер-репозиториев, в этом случае вам нужно сделать небольшой сценарий, чтобы обновлять список репозиториев для резервного копирования.</para>

    <para id="x_6d9">Если вы выполняете традиционное резервное копирование мастер-репозитория на ленту или жесткий диск, и вы хотите создать резервную копию хранилища с именем <filename>myrepo</filename>, <command>hg clone -U myrepo myrepo.bak</command> для создания клона <filename>myrepo</filename> перед началом резервного копирования. Опция <option>-U</option> не проверяет рабочий каталог после завершения клонирования, поскольку излишне и резервное копирование занимало бы больше времени.</para>

    <para id="x_6da">Если вы затем используете <filename>myrepo.bak</filename> вместо <filename>myrepo</filename>, вам будет гарантирована возможность получить снимок репозитория, не боясь что какой-то разработчик вставит изменение в середине резервного копирования.</para>
  </sect1>
</chapter>

<!--
local variables: 
sgml-parent-document: ("00book.xml" "book" "chapter")
end:
-->