<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Rerere on DevOps Way - Практические гайды</title>
    <link>https://devopsway.ru/tags/rerere/</link>
    <description>Recent content in Rerere on DevOps Way - Практические гайды</description>
    <image>
      <title>DevOps Way - Практические гайды</title>
      <url>https://devopsway.ru/images/devopsway-og.png</url>
      <link>https://devopsway.ru/images/devopsway-og.png</link>
    </image>
    <generator>Hugo -- 0.160.1</generator>
    <language>ru</language>
    <lastBuildDate>Thu, 16 Apr 2026 13:12:41 -0400</lastBuildDate>
    <atom:link href="https://devopsway.ru/tags/rerere/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>День 7: cherry-pick и rerere — перенос коммитов и память Git о конфликтах</title>
      <link>https://devopsway.ru/posts/git-cherrypick-rerere/</link>
      <pubDate>Thu, 16 Apr 2026 10:00:00 +0300</pubDate>
      <guid>https://devopsway.ru/posts/git-cherrypick-rerere/</guid>
      <description>Как точечно перенести один коммит между ветками через cherry-pick. Как включить rerere — и Git будет сам разрешать повторяющиеся конфликты, запоминая ваше решение.</description>
      <content:encoded><![CDATA[<h2 id="цель-урока">Цель урока</h2>
<p>После урока вы <strong>умеете</strong> переносить отдельные коммиты между ветками через <code>cherry-pick</code>, различаете случаи, когда это уместно, и когда правильнее <code>merge</code>/<code>rebase</code>. Включили <code>rerere</code> глобально и понимаете, как Git запоминает ваше решение конфликта, чтобы применить его автоматически в следующий раз.</p>
<table>
  <thead>
      <tr>
          <th>Параметр</th>
          <th>Значение</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Bloom</td>
          <td>Применение, Анализ</td>
      </tr>
      <tr>
          <td>SFIA</td>
          <td>Уровень 2–3</td>
      </tr>
      <tr>
          <td>Время</td>
          <td>35–45 минут</td>
      </tr>
      <tr>
          <td>Артефакт</td>
          <td><code>rerere.enabled = true</code> в <code>~/.gitconfig</code> + алиас <code>pick</code></td>
      </tr>
      <tr>
          <td>Проверка</td>
          <td>Мини-тест + сценарий с повторным конфликтом</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="теория-за-3-минуты">Теория за 3 минуты</h2>
<p><strong><code>git cherry-pick &lt;sha&gt;</code></strong> берёт один коммит с одной ветки и применяет как новый коммит на текущую. Новый коммит имеет <strong>другой SHA</strong>, но тот же diff и то же сообщение.</p>
<p><strong>Когда уместно cherry-pick:</strong></p>
<ul>
<li>hotfix из <code>main</code> надо прокинуть в активный <code>release/*</code></li>
<li>один коммит из чужого PR пригодится и вашей команде, остальное не нужно</li>
<li>восстановление потерянного коммита (вы видели в Дне 2 — reflog + cherry-pick)</li>
</ul>
<p><strong>Когда НЕ cherry-pick:</strong></p>
<ul>
<li>регулярная синхронизация двух веток (это <code>merge</code> или <code>rebase</code>)</li>
<li>5+ коммитов переносить точечно — накопится drift, лучше <code>rebase --onto</code> или merge</li>
</ul>
<p><strong><code>rerere</code> (reuse recorded resolution)</strong> — механизм, где Git запоминает <strong>как вы разрешили конфликт</strong> (по хэшу содержимого конфликтных областей) и применяет ту же развязку автоматически, когда встречает идентичный конфликт снова.</p>
<p>Типичный случай: вы второй раз rebase&rsquo;ите ту же long-lived ветку на обновлённый <code>main</code>, и снова сталкиваетесь с тем же конфликтом в том же файле. С включённым <code>rerere</code> конфликт решается сам.</p>
<hr>
<h2 id="практика-1-cherry-pick-без-конфликта">Практика 1: cherry-pick без конфликта</h2>
<h3 id="шаг-1-собираем-репо-с-двумя-ветками">Шаг 1. Собираем репо с двумя ветками</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p demo-cherry <span class="o">&amp;&amp;</span> <span class="nb">cd</span> demo-cherry
</span></span><span class="line"><span class="cl">git init -q
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &gt; app.js <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">function sum(a, b) { return a + b; }
</span></span></span><span class="line"><span class="cl"><span class="s">module.exports = sum;
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;feat: initial app&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Создаём release-ветку от main</span>
</span></span><span class="line"><span class="cl">git branch release/v1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># На main добавляем три коммита</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;// main change 1&#34;</span> &gt;&gt; app.js <span class="o">&amp;&amp;</span> git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;feat: main change 1&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># КРИТИЧЕСКИЙ багфикс — нужен в release тоже</span>
</span></span><span class="line"><span class="cl">cat &gt; app.js <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">function sum(a, b) {
</span></span></span><span class="line"><span class="cl"><span class="s">  if (typeof a !== &#39;number&#39; || typeof b !== &#39;number&#39;) return 0;  // hotfix
</span></span></span><span class="line"><span class="cl"><span class="s">  return a + b;
</span></span></span><span class="line"><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="cl"><span class="s">module.exports = sum;
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;fix: guard against non-number input&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">HOTFIX_SHA</span><span class="o">=</span><span class="k">$(</span>git rev-parse HEAD<span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;// main change 3&#34;</span> &gt;&gt; app.js <span class="o">&amp;&amp;</span> git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;feat: main change 3&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">git log --oneline
</span></span></code></pre></div><h3 id="шаг-2-переносим-только-hotfix-на-release">Шаг 2. Переносим только hotfix на release</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout release/v1
</span></span><span class="line"><span class="cl">git cherry-pick <span class="nv">$HOTFIX_SHA</span>
</span></span></code></pre></div><p>Git применит тот же diff, создаст новый коммит с таким же сообщением, вернёт вам чистый tree.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git log --oneline release/v1
</span></span><span class="line"><span class="cl"><span class="c1"># &lt;new-sha&gt; fix: guard against non-number input</span>
</span></span><span class="line"><span class="cl"><span class="c1"># &lt;root&gt;    feat: initial app</span>
</span></span></code></pre></div><p><strong>Запомните</strong>: SHA изменился. Тот же diff, другой коммит. Это нормально — cherry-pick всегда создаёт нового «клона».</p>
<h3 id="шаг-3-возвращаемся-на-main">Шаг 3. Возвращаемся на main</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git checkout main
</span></span></code></pre></div><hr>
<h2 id="практика-2-cherry-pick-с-конфликтом--включаем-rerere">Практика 2: cherry-pick с конфликтом (+ включаем rerere)</h2>
<p>Поставим ситуацию, когда коммит изменил файл, а в целевой ветке этот файл уже другой. Перед этим включим <code>rerere</code> — Git будет <strong>тихо запоминать</strong> ваше решение, это пригодится в Практике 3.</p>
<h3 id="шаг-0-включаем-rerere-глобально">Шаг 0. Включаем rerere глобально</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git config --global rerere.enabled <span class="nb">true</span>
</span></span><span class="line"><span class="cl">git config --global rerere.autoupdate <span class="nb">true</span>
</span></span></code></pre></div><ul>
<li><code>enabled</code> — писать и читать решения</li>
<li><code>autoupdate</code> — автоматически добавлять в index разрешённые области (без <code>git add</code>)</li>
</ul>
<p>Включайте один раз на машину — работает везде, места почти не занимает.</p>
<h3 id="шаг-1-готовим-конфликт">Шаг 1. Готовим конфликт</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> .. <span class="o">&amp;&amp;</span> mkdir -p demo-conflict <span class="o">&amp;&amp;</span> <span class="nb">cd</span> demo-conflict
</span></span><span class="line"><span class="cl">git init -q
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat &gt; config.json <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">{
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;timeout&#34;: 30,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;retries&#34;: 3
</span></span></span><span class="line"><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;feat: config&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">git branch feature
</span></span><span class="line"><span class="cl">git checkout -q feature
</span></span><span class="line"><span class="cl">cat &gt; config.json <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">{
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;timeout&#34;: 30,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;retries&#34;: 5,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;feature_flag&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;feat: add feature_flag&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">git checkout -q main
</span></span><span class="line"><span class="cl">cat &gt; config.json <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">{
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;timeout&#34;: 60,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;retries&#34;: 3
</span></span></span><span class="line"><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add . <span class="o">&amp;&amp;</span> git commit -q -m <span class="s2">&#34;perf: increase timeout&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Из feature хотим только коммит с feature_flag</span>
</span></span><span class="line"><span class="cl"><span class="nv">FEATURE_SHA</span><span class="o">=</span><span class="k">$(</span>git log feature --format<span class="o">=</span>%H -1 --grep feature_flag<span class="k">)</span>
</span></span></code></pre></div><h3 id="шаг-2-cherry-pick--конфликт">Шаг 2. Cherry-pick → конфликт</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git cherry-pick <span class="nv">$FEATURE_SHA</span>
</span></span><span class="line"><span class="cl"><span class="c1"># CONFLICT (content): Merge conflict in config.json</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Automatic cherry-pick failed; fix conflicts...</span>
</span></span></code></pre></div><h3 id="шаг-3-разрешаем-вручную">Шаг 3. Разрешаем вручную</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cat config.json
</span></span></code></pre></div><p>Вы увидите маркеры:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
</span></span><span class="line"><span class="cl">  &#34;timeout&#34;: 60,
</span></span><span class="line"><span class="cl">  &#34;retries&#34;: 3
</span></span><span class="line"><span class="cl">=======
</span></span><span class="line"><span class="cl">  &#34;timeout&#34;: 30,
</span></span><span class="line"><span class="cl">  &#34;retries&#34;: 5,
</span></span><span class="line"><span class="cl">  &#34;feature_flag&#34;: true
</span></span><span class="line"><span class="cl">&gt;&gt;&gt;&gt;&gt;&gt;&gt;
</span></span></code></pre></div><p>Объединяем руками — берём <code>timeout: 60</code> из main и <code>feature_flag</code> из feature:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cat &gt; config.json <span class="s">&lt;&lt; &#39;EOF&#39;
</span></span></span><span class="line"><span class="cl"><span class="s">{
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;timeout&#34;: 60,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;retries&#34;: 5,
</span></span></span><span class="line"><span class="cl"><span class="s">  &#34;feature_flag&#34;: true
</span></span></span><span class="line"><span class="cl"><span class="s">}
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span><span class="line"><span class="cl">git add config.json
</span></span><span class="line"><span class="cl">git cherry-pick --continue
</span></span></code></pre></div><p>Коммит создан, работа продолжается.</p>
<hr>
<h2 id="практика-3-rerere-применяет-решение-автоматически">Практика 3: rerere применяет решение автоматически</h2>
<p>Теперь самое интересное. В Практике 2 rerere тихо записал, <strong>как вы развязали конфликт</strong>. Представим, что тот же конфликт нужно решить ещё раз — например, мы сделали rebase, ветку перезаписали, и cherry-pick приходится повторить.</p>
<h3 id="шаг-1-откатываем-и-повторяем">Шаг 1. Откатываем и повторяем</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Откатываем коммит с разрешением, но память rerere остаётся</span>
</span></span><span class="line"><span class="cl">git reset --hard HEAD~1
</span></span><span class="line"><span class="cl">git cherry-pick <span class="nv">$FEATURE_SHA</span>
</span></span></code></pre></div><p>На этот раз Git скажет:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Auto-merging config.json
</span></span><span class="line"><span class="cl">CONFLICT (content): Merge conflict in config.json
</span></span><span class="line"><span class="cl">error: could not apply &lt;sha&gt;... feat: add feature_flag
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">Staged &#39;config.json&#39; using previous resolution.
</span></span></code></pre></div><p>Обратите внимание на последнюю строку: <strong><code>Staged ... using previous resolution</code></strong> — rerere узнал конфликт по хэшу преимаджа, подставил ваше старое решение и даже сам сделал <code>git add</code>. Откройте файл:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cat config.json
</span></span></code></pre></div><p>Там уже правильное содержимое (<code>timeout: 60</code> + <code>feature_flag: true</code>), <strong>без маркеров конфликта</strong> и уже в индексе (<code>autoupdate</code> сработал). Остаётся только завершить cherry-pick:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git cherry-pick --continue
</span></span></code></pre></div><p>Второй раз вы не писали ни строчки — Git сам сделал работу по памяти. Если <code>autoupdate</code> выключен, нужно вручную <code>git add config.json</code>, но содержимое всё равно уже разрешено.</p>
<h3 id="шаг-2-где-git-хранит-память">Шаг 2. Где Git хранит память</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ls .git/rr-cache/
</span></span><span class="line"><span class="cl"><span class="c1"># &lt;hash&gt;/preimage postimage</span>
</span></span><span class="line"><span class="cl">cat .git/rr-cache/*/preimage <span class="p">|</span> head
</span></span></code></pre></div><p><code>rr-cache</code> — каталог с записями: каждая пара «как конфликт выглядел (preimage)» → «как вы его решили (postimage)». Ключ — хэш от преимаджа, поэтому «похожие, но не идентичные» конфликты rerere отличает.</p>
<hr>
<h2 id="артефакт-готовая-настройка">Артефакт: готовая настройка</h2>
<p>Добавьте в <code>~/.gitconfig</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="k">[rerere]</span>
</span></span><span class="line"><span class="cl">    <span class="na">enabled</span> <span class="o">=</span> <span class="s">true
</span></span></span><span class="line"><span class="cl"><span class="s">    autoupdate = true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[alias]</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># cherry-pick с коротким именем + авто-skip пустых коммитов</span>
</span></span><span class="line"><span class="cl">    <span class="na">pick</span> <span class="o">=</span> <span class="s">&#34;cherry-pick --allow-empty --keep-redundant-commits&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Список коммитов, отсутствующих в текущей ветке по сравнению с &lt;branch&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Удобно искать, что перенести</span>
</span></span><span class="line"><span class="cl">    <span class="na">missing</span> <span class="o">=</span> <span class="s">&#34;!f() { git log --cherry-pick --oneline --no-merges ..$1; }; f&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Показать, что rerere помнит</span>
</span></span><span class="line"><span class="cl">    <span class="na">rr-status</span> <span class="o">=</span> <span class="s">rerere status
</span></span></span><span class="line"><span class="cl"><span class="s">    rr-diff   = rerere diff</span>
</span></span></code></pre></div><p>Использование:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git missing main                        <span class="c1"># что есть в main, чего нет у меня</span>
</span></span><span class="line"><span class="cl">git pick &lt;sha&gt;                          <span class="c1"># cherry-pick</span>
</span></span><span class="line"><span class="cl">git rr-status                           <span class="c1"># какие конфликты rerere готов решить</span>
</span></span><span class="line"><span class="cl">git rr-diff                             <span class="c1"># посмотреть как именно</span>
</span></span></code></pre></div><hr>
<h2 id="когда-cherry-pick--запах">Когда cherry-pick — запах</h2>
<ul>
<li><strong>Вы делаете его 5+ раз подряд</strong> между теми же двумя ветками. Значит, ветки должны синхронизироваться merge&rsquo;ом, а не точечно.</li>
<li><strong>Вы переносите чужие коммиты без ревью diff</strong> — теряется контекст, легко затащить то, чего не ожидали.</li>
<li><strong>Коммит зависит от 10 предыдущих</strong>, которых на целевой ветке нет — получите конфликт на конфликте, проще взять всю цепочку.</li>
</ul>
<p>Правило: cherry-pick хорош для <strong>одного изолированного коммита</strong>. Для потока — merge или rebase.</p>
<hr>
<h2 id="-документирование">📝 Документирование</h2>
<p>Напишите в <code>NOTES.md</code>:</p>
<ol>
<li><strong>Своими словами</strong>: почему cherry-pick создаёт новый SHA, а не «перемещает» коммит.</li>
<li><strong>Три ситуации</strong>, где cherry-pick оправдан, и одна — где лучше merge.</li>
<li><strong>Что помнит rerere</strong> — по одному предложению, как вы объясните коллеге.</li>
<li><strong>Включили ли rerere у себя</strong> (<code>git config --global rerere.enabled true</code>). Да/нет — и почему.</li>
</ol>
<hr>
<h2 id="мини-тест">Мини-тест</h2>
<ol>
<li>Вы cherry-pick&rsquo;нули коммит, который <strong>уже применён</strong> в целевой ветке. Что произойдёт по умолчанию и что изменит флаг <code>--allow-empty</code>?</li>
<li>Можно ли cherry-pick&rsquo;нуть <strong>merge-коммит</strong>? Какой флаг нужен?</li>
<li>В какой момент rerere <strong>записывает</strong> решение — когда вы руками разрешаете конфликт, или когда делаете <code>git add</code>?</li>
<li>Если хэш конфликтной области отличается от «помеченной» даже на один пробел, сработает ли rerere?</li>
</ol>
<p>Ответы — в конце.</p>
<hr>
<h2 id="что-дальше">Что дальше</h2>
<ul>
<li><strong>День 8</strong> → worktree: работать одновременно в двух ветках без <code>git stash</code> и <code>git checkout</code>. Вы сможете держать hotfix-ветку открытой параллельно с feature-веткой, в разных каталогах, с общим <code>.git/</code>.</li>
<li><strong><a href="/posts/git-master-final-challenge/">Challenge</a></strong> → сломанный репозиторий с 10 проблемами. Задача P8 — cherry-pick с конфликтом + rerere запомнит решение.</li>
</ul>
<hr>
<h2 id="ответы-на-мини-тест">Ответы на мини-тест</h2>
<ol>
<li>По умолчанию Git скажет «The previous cherry-pick is now empty» и предложит пропустить. С <code>--allow-empty</code> создаст пустой коммит (нужно редко — например, для сохранения истории событий).</li>
<li>Да: <code>git cherry-pick -m 1 &lt;merge-sha&gt;</code>. Флаг <code>-m</code> указывает, относительно какого родителя считать diff (у merge-коммита их двое).</li>
<li><code>rerere</code> записывает решение именно когда вы делаете <code>git add</code> на файл с разрешённым конфликтом. Сам по себе факт правки маркеров в файле не достаточен.</li>
<li>Нет. Хэш считается от точного содержимого preimage — разница в пробел, табуляцию или порядок строк даст другой хэш. Это и защита (не применит «почти похожее» решение по ошибке), и ограничение.</li>
</ol>
]]></content:encoded>
    </item>
  </channel>
</rss>
