в чем разница между git reset --mixed, --soft и --hard?

<p>я ищу разделить коммит и не уверен, какой вариант сброса использовать.</p><p>я смотрел на страницу <a href="https://stackoverflow.com/questions/2530060/can-you-explain-to-me-git-reset-in-plain-english">можете ли вы объяснить, что делает "git reset" на простом английском?</a> , но я понял, что не совсем понимаю, что такое индекс git или область подготовки, и поэтому объяснения не помогли.</p><p>кроме того, варианты использования для <code>--mixed</code> и <code>--soft</code> выглядят одинаково для меня в этом ответе (когда вы хотите исправить и повторить.) может кто-нибудь еще сломать? я понимаю, что <code>--mixed</code>, вероятно, является вариантом, но я хочу знать <em>почему</em>. и наконец, как насчет <code>--hard</code>?</p><p>может ли кто-нибудь дать мне пример рабочего процесса, как будет происходить выбор 3-х вариантов?</p>

<p>когда вы изменяете файл в своем репозитории, изменение изначально не является этапным. чтобы зафиксировать это, вы должны поставить его, то есть добавить в индекс, используя <code>git add</code>. когда вы делаете фиксацию, это те изменения, которые были добавлены в индекс.</p><p><code>git reset</code> меняет, как минимум, текущую ветвь (<code>head</code>). разница между <code>--mixed</code> и <code>--soft</code> в том, изменен или нет ваш индекс. итак, если мы находимся на ветке <code>master</code> с этой серией коммитов:</p><pre><code>- a - b - c (master) </code></pre><p><code>head</code> указывает на <code>c</code>, а индекс соответствует <code>c</code>.</p><p>когда мы запускаем <code>git reset --soft b</code>, <code>master</code> (и, следовательно, <code>head</code>) теперь указывает на <code>b</code>, но индекс по-прежнему содержит изменения из <code>c</code>; <code>git status</code> покажет их как постановочные. поэтому, если мы запустим <code>git commit</code> на этом этапе, мы получим новый коммит с теми же изменениями, что и <code>c</code>.</p><hr><p>итак, начиная с этого снова:</p><pre><code>- a - b - c (master) </code></pre><p>теперь давайте сделаем <code>git reset --mixed b</code>. (примечание: <code>--mixed</code> является опцией по умолчанию). еще раз, <code>master</code> и <code>head</code> указывают на b, но на этот раз индекс также изменяется, чтобы соответствовать <code>b</code>. если мы запустим <code>git commit</code> на этом этапе, ничего не произойдет, так как индекс соответствует <code>head</code>. у нас все еще есть изменения в рабочем каталоге, но, поскольку они отсутствуют в индексе, <code>git status</code> показывает их как неперехваченные. чтобы зафиксировать их, вы должны <code>git add</code>, а затем зафиксировать как обычно.</p><hr><p>и, наконец, <code>--hard</code> - это то же самое, что <code>--mixed</code> (он изменяет ваш <code>head</code> и индекс), за исключением того, что <code>--hard</code> также изменяет ваш рабочий каталог. если мы находимся на <code>c</code> и запускаем <code>git reset --hard b</code>, то изменения, добавленные в <code>c</code>, а также любые незафиксированные изменения, которые у вас есть, будут удалены, и файлы в вашей рабочей копии будут соответствовать commit <code>b</code>. так как вы можете навсегда потерять изменения таким образом, вы всегда должны запускать <code>git status</code> перед выполнением аппаратного сброса, чтобы убедиться, что ваш рабочий каталог чист, или что вы в порядке потери ваших незафиксированных изменений.</p><hr><p>и, наконец, визуализация: <img src="https://i.stack.imgur.com/qrate.jpg" alt="enter image description here"></p>

<p><em> пожалуйста, имейте в виду, это упрощенное объяснение, предназначенное в качестве первого шага в попытке понять эту сложную функциональность. </em></p><p>может быть полезно для визуальных учеников, которые хотят визуализировать, как выглядит состояние их проекта после каждой из следующих команд:</p><hr><p>для тех, кто использует терминал с включенным цветом (git config --global color.ui auto): </p><p><code>git reset --soft a</code>, и вы увидите вещи b и c в зеленом цвете (подготовлены и готовы к фиксации) </p><p><code>git reset --mixed a</code> (или <code>git reset a</code>), и вы увидите вещи b и c в красном (не подготовленные и готовые к постановке (зеленые), а затем зафиксированные) </p><p><code>git reset --hard a</code> и вы больше нигде не увидите изменений b и c (как если бы они никогда не существовали)</p><hr><p>или для тех, кто использует программу с графическим интерфейсом, как «башня» или «sourcetree»</p><p><code>git reset --soft a</code> и вы увидите вещи b и c в области 'staged files', готовые к фиксации</p><p><code>git reset --mixed a</code> (или <code>git reset a</code>), и вы увидите вещи b и c в области 'unstaged files', готовые для перемещения в промежуточную, а затем зафиксированные</p><p><code>git reset --hard a</code> и вы больше нигде не увидите изменений b и c (как если бы они никогда не существовали)</p>

<p>проще говоря:</p><ul> <li><strong><code>--soft</code></strong>:<strong> uncommit </strong>изменения, изменения остаются поэтапными (<em>index</em>).</li> <li><strong><code>--mixed</code></strong><em>(по умолчанию)</em>:<strong> uncommit + unstage </strong>изменения, изменения остаются в <em>рабочем дереве</em>.</li> <li><strong><code>--hard</code></strong>:<strong> uncommit + unstage + delete </strong>изменения, ничего не осталось.</li> </ul>

<p><strong> вот основное объяснение для пользователей tortoisegit: </strong></p><p><code>git reset --soft</code> и <code>--mixed</code> оставляют ваши файлы без изменений. </p><p><code>git reset --hard</code> фактически <em>измените ваши файлы</em> в соответствии с коммитом, к которому вы сбросили.</p><p>в tortoisegit концепция <em>index</em> очень скрыта в графическом интерфейсе. когда вы изменяете файл, вам не нужно запускать <code>git add</code>, чтобы добавить изменение в промежуточную область/индекс. при работе с изменениями существующих файлов, которые не меняют имен файлов, <code>git reset --soft</code> и <code>--mixed</code> одинаковы! вы заметите разницу только в том случае, если добавите новые или переименованные файлы. в этом случае, если вы запустите git reset --mixed, вам придется повторно добавить ваши файлы из списка <em>not versioned files</em>. </p>

<p>в этих случаях мне нравится визуал, который, я надеюсь, может объяснить это:</p><p><code>git reset --[hard/mixed/soft]</code>:</p><p> <a href="https://i.stack.imgur.com/iu0at.png"> <img src="https://i.stack.imgur.com/iu0at.png" alt="enter image description here"> </a> </p><p>так что у каждого эффекта разные рамки</p><ol> <li>hard => workingdir + index + head</li> <li>смешанный => индекс + голова</li> <li>soft => head only (индекс и рабочий каталог без изменений).</li> </ol>

<p>основное различие между различными опциями команды git reset приведено ниже.</p><ul> <li>--soft: сбрасывает только head в выбранный вами коммит. работает в основном так же, как git checkout, но не создает отдельное состояние головы.</li> <li>--mixed (опция по умолчанию): сбрасывает заголовок в коммит, выбранный вами в истории, и отменяет изменения в индексе.</li> <li>--hard: сбрасывает заголовок в коммит, выбранный вами в истории, отменяет изменения в индексе и отменяет изменения в вашем рабочем каталоге.</li> </ul>

<p>здесь есть несколько ответов с неправильным представлением о <code>git reset --soft</code>. хотя существует определенное условие, при котором <code>git reset --soft</code> будет изменять только <code>head</code> (начиная с состояния отдельного заголовка), обычно (и для предполагаемого использования), <strong>перемещает ссылку на ветку, которую вы в настоящее время извлекли.</strong> конечно, это не может быть сделано, если у вас нет извлеченной ветки (отсюда определенное условие, когда <code>git reset --soft</code> изменит только <code>head</code>). </p><p>я считаю, что это лучший способ думать о <code>git reset</code>. вы не просто перемещаете <code>head</code> ( <a href="https://stackoverflow.com/a/54935492/7936744">все это делает</a> ), вы также перемещаете <em>ссылка на ветвь</em>, например, <code>master</code>. это похоже на то, что происходит, когда вы запускаете <code>git commit</code> (текущая ветвь перемещается вместе с <code>head</code>), за исключением того, что вместо создания (и перехода к) фиксации <em>new</em> вы переходите к <em>предыдущему</em> совершить.</p><p><strong>это точка <code>reset</code>, изменяющая <em>ветвь</em> на что-то отличное от нового коммита, без изменения <code>head</code>.</strong> вы можете увидеть это в примере документации:</p><blockquote> <p>отменить коммит, сделав его веткой тем</p> <pre><code> $ git branch topic/wip (1) $ git reset --hard head~3 (2) $ git checkout topic/wip (3) </code></pre> <ol> <li>вы сделали некоторые коммиты, но понимаете, что они были преждевременны, чтобы быть в "основной" ветке. вы хотите продолжить полировать их в ветке темы, поэтому создайте ветку "topic/wip" вне текущего заголовка.</li> <li>перемотайте ветку master, чтобы избавиться от этих трех коммитов.</li> <li>переключитесь на ветку "topic/wip" и продолжайте работать.</li> </ol> </blockquote><p>какой смысл в этой серии команд? вы хотите переместить <em>ответвление</em>, здесь <code>master</code>, поэтому пока вы извлекаете <code>master</code>, вы запускаете <code>git reset</code>.</p><p>ответ с наибольшим количеством голосов здесь в целом хорош, но я подумал, что добавлю это, чтобы исправить несколько ответов с ошибочными представлениями.</p><h3>измени свою ветку</h3><p><code>git reset --soft <ref></code>: сбрасывает указатель ветки для текущей извлеченной ветки в фиксацию по указанной ссылке,. файлы в вашем рабочем каталоге и индексе не изменены. фиксация с этого этапа вернет вас туда, где вы были до команды <code>git reset</code>.</p><h3>измените свой индекс тоже</h3><p><code>git reset --mixed <ref></code></p><p>или эквивалентно</p><p><code>git reset <ref></code>:</p><p>делает то, что делает <code>--soft</code> <strong>, а</strong> также сбрасывает индекс в соответствии с фиксацией по указанной ссылке. в то время как <code>git reset --soft head</code> ничего не делает (потому что говорит о перемещении извлеченной ветви в извлеченную ветвь), <code>git reset --mixed head</code>, или, что то же самое, <code>git reset head</code>, является обычной и полезной командой, потому что она сбрасывает индекс до состояния вашего последнего коммита.</p><h3>измените свой рабочий каталог тоже</h3><p><code>git reset --hard <ref></code>: делает то, что <code>--mixed</code> делает <strong>, а</strong> также перезаписывает ваш рабочий каталог. эта команда похожа на <code>git checkout <ref></code>, за исключением того, что (и это ключевой момент для <code>reset</code>) <em>все формы <code>git reset</code> перемещают ветку, на которую ссылается <code>head</code>.</em></p><h3>примечание о «такая-то команда перемещает голову»:</h3><p>бесполезно говорить, что команда перемещает переменную <code>head</code>. любая команда, которая меняет ваше местоположение в истории коммитов, перемещает <code>head</code>. вот что такое <code>head</code> <strong></strong>, указатель на то, где вы находитесь. <a href="https://stackoverflow.com/a/54935492/7936744"><code>head</code> это вы</a> , и поэтому будете двигаться, когда вы это делаете. </p>

<p><code>--soft</code>: говорит git сбросить head для другого коммита, так что индекс и рабочий каталог не будут изменены каким-либо образом. все файлы, измененные между оригинальным head и коммитом, будут размещены.</p><p><code>--mixed</code>: так же, как софт, это сбросит head к другому коммиту. он также сбросит индекс, чтобы он соответствовал ему, в то время как рабочий каталог не будет затронут. все изменения останутся в рабочем каталоге и появятся как измененные, но не подготовленные.</p><p><code>--hard</code>: это сбрасывает все - он сбрасывает head обратно в другой коммит, сбрасывает индекс, чтобы соответствовать ему, и сбрасывает рабочий каталог, чтобы соответствовать ему.</p><p>основное различие между <code>--mixed</code> и <code>--soft</code> заключается в том, изменен или нет ваш индекс. проверьте больше об этом <a href="https://kolosek.com/git-reset-revert-and-checkout/">здесь</a> .</p>

<p>краткий ответ, в каком контексте используются 3 варианта:</p><p>to<strong> сохранить текущие изменения в коде </strong>но переписать историю коммитов:</p><ul> <li><code>soft</code>: вы можете зафиксировать все сразу и создать новый коммит с новым описанием (если вы используете torotise git или любой другой графический интерфейс, это тот, который нужно использовать, так как вы можете пометить, какие файлы вы хотите в коммите и сделать несколько коммитов таким образом с разными файлами. в sourcetree все файлы будут помещаться для коммита.)</li> <li><code>mixed</code>: вам нужно будет снова добавить отдельные файлы в индекс, прежде чем делать коммиты (в sourcetree все измененные файлы будут неизменными)</li> </ul><p>чтобы фактически<strong> потерять ваши изменения </strong>также в коде:</p><ul> <li><code>hard</code>: вы не просто переписываете историю, но и теряете все свои изменения вплоть до момента сброса</li> </ul>

<p>вам не нужно заставлять себя помнить различия между ними. подумайте, как вы на самом деле сделали коммит.</p><p>1. внесите некоторые изменения.</p><p>2.git добавить.</p><p>3.gc -m "я сделал что-то"</p><p>soft, mixed и hard - это способ, позволяющий отказаться от операций, которые вы делали от 3 до 1.</p><p>софт "притворился", что никогда не видел, что ты сделал "gc -m".</p><p>смешанный «сделал вид», чтобы никогда не видеть, что вы сделали «git add».</p><p>тяжело «притворялся», чтобы никогда не видеть, что вы сделали изменения в файле. </p>

<p>прежде чем перейти к этим трем вариантам, нужно понять 3 вещи.</p><p>1) история/голова</p><p>2) стадия/индекс</p><p>3) рабочий каталог</p><p>reset --soft: история изменена, head изменен, рабочий каталог не изменен.</p><p>reset --mixed: история изменена, head изменена, рабочая директория изменена с неподготовленными данными.</p><p>reset --hard: история изменена, head изменен, рабочий каталог изменен с потерянными данными.</p><p>с git --soft всегда безопасно. нужно использовать другой вариант в сложном требовании.</p>

<p>ответ mkarasek велик, простыми словами мы можем сказать ...</p><ul> <li><code>git reset --soft</code>: установите <code>head</code> для предполагаемого коммита, но сохраняйте свои изменения с момента последнего коммита</li> <li><code>git reset --mixed</code>: он такой же, как <code>git reset --soft</code>, но единственное отличие состоит в том, что он не вносит изменения с момента последнего коммита</li> <li><code>git reset --hard</code>: установите <code>head</code> для указанного вами коммита и сбросьте все ваши изменения с последних коммитов, включая не зафиксированные изменения. </li> </ul>