В чем разница между "git reset" и "git checkout"? - PullRequest
398 голосов
/ 04 сентября 2010

Я всегда думал о git reset и git checkout как об одном и том же, в том смысле, что оба возвращают проект к определенной фиксации. Однако я чувствую, что они не могут быть точно такими же, поскольку это было бы излишним. Какова реальная разница между двумя? Я немного сбит с толку, поскольку у svn есть только svn co, чтобы отменить коммит.

ДОБАВЛЕНО

VonC и Чарльз очень хорошо объяснили разницу между git reset и git checkout. Мое текущее понимание состоит в том, что git reset возвращает все изменения обратно в конкретный коммит, тогда как git checkout более или менее подготавливает ветку. Я нашел следующие две диаграммы весьма полезными для достижения этого понимания:

http://a.imageshack.us/img651/1559/86421927.png http://a.imageshack.us/img801/1986/resetr.png

ДОБАВЛЕНО 3

С http://think -like-a-git.net / section / перебазировать с нуля / используя git-cherry-pick-to-simulate-git-rebase.html Оформление заказа и сброс могут эмулировать перебазирование.

enter image description here

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

enter image description here

Ответы [ 6 ]

174 голосов
/ 04 сентября 2010
  • git reset конкретно означает , обновляя индекс , перемещая ГОЛОВКУ.
  • git checkout означает обновление рабочего дерева (до индекса или указанного дерева). Он будет обновлять HEAD только в том случае, если вы извлекаете ветку (в противном случае вы получаете отдельную HEAD ).

Для сравнения, поскольку svn не имеет индекса, только рабочее дерево, svn checkout скопирует данную ревизию в отдельный каталог.
Более близкий эквивалент для git checkout будет:

  • svn update (если вы находитесь в той же ветке, то есть с тем же URL-адресом SVN)
  • svn switch (если вы извлекаете, например, ту же ветку, но с другого URL репо SVN)

Все эти три модификации рабочего дерева (svn checkout, update, switch) имеют только одну команду в git: git checkout.
Но так как git также имеет понятие индекса («промежуточной области» между репо и рабочим деревом), у вас также есть git reset.


Thinkeye упоминает в комментариях статья " Сброс демистификации ".

Например, если у нас есть две ветви, 'master' и 'develop', указывающие на разные коммиты, и мы в настоящее время находимся на 'develop' (поэтому HEAD указывает на него), и мы запускаем git reset master, * develop 'теперь будет указывать на тот же коммит, что и master.

С другой стороны, если мы вместо этого запустим git checkout master, 'develop' не будет двигаться, само HEAD будет двигаться. HEAD теперь будет указывать на 'master'.

Итак, в обоих случаях мы перемещаем HEAD, чтобы указать на фиксацию A, но то, как мы это делаем, сильно отличается. reset переместит ветку, на которую указывает HEAD, касса сама переместится на HEAD, чтобы указать на другую ветку.

http://git-scm.com/images/reset/reset-checkout.png

По тем пунктам:

LarsH добавляет в комментариях :

Первый абзац этого ответа, однако, вводит в заблуждение: «git checkout ... обновит ГОЛОВКУ только в том случае, если вы извлекаете ветку (если нет, в итоге вы получаете отсоединенную ГОЛОВУ)». Неверно: git checkout будет обновлять HEAD, даже если вы извлекаете коммит, который не является ветвью (и да, в конечном итоге вы получаете отдельный HEAD, но он все еще обновляется).

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo согласен в комментариях :

@ LarsH правильный.
Второй пункт имеет неправильное представление о том, что в HEAD будет обновлять HEAD, только если вы извлекаете ветку.
ГОЛОВА идет туда, где ты, как тень.
Извлечение ссылки, не относящейся к ветви (например, тега) или фиксации напрямую, переместит HEAD. Отделенная головка не означает, что вы отсоединились от ГОЛОВКИ, это означает, что головка отделена от ссылки на ветку, которую вы можете видеть, например, git log --pretty=format:"%d" -1.

  • Состояния присоединенной головы будут начинаться с (HEAD ->,
  • detached будет по-прежнему отображать (HEAD, но не будет иметь стрелки на ветке ref.
62 голосов
/ 04 сентября 2010

В простейшем виде reset сбрасывает индекс, не касаясь рабочего дерева, а checkout меняет рабочее дерево, не касаясь индекса.

Сбрасывает индекс для соответствия HEAD, рабочее дерево остается в покое:

git reset

Концептуально это проверяет индекс в рабочем дереве. Чтобы заставить его действительно что-то делать, вы должны будете использовать -f, чтобы заставить его перезаписывать любые локальные изменения. Это функция безопасности, позволяющая убедиться, что форма «без аргументов» не является разрушительной:

git checkout

Как только вы начинаете добавлять параметры, это правда, что есть некоторое перекрытие.

checkout обычно используется с веткой, тегом или коммитом. В этом случае он сбросит HEAD и индекс для данного коммита, а также выполнит извлечение индекса в рабочее дерево.

Также, если вы поставите --hard на reset, вы можете попросить reset перезаписать рабочее дерево, а также сбросить индекс.

Если у вас есть проверенная ветвь, между reset и checkout есть критическая разница, когда вы предоставляете альтернативную ветку или коммит. reset изменит текущую ветвь так, чтобы она указывала на выбранный коммит, тогда как checkout оставит текущую ветку в покое, но вместо этого извлечет предоставленную ветвь или коммит.

Другие формы reset и commit включают пути снабжения.

Если вы указываете пути к reset, вы не можете указать --hard, а reset изменит только индексную версию предоставленных путей на версию в предоставленном коммите (или HEAD, если вы не укажете фиксации).

Если вы указываете пути к checkout, например reset, он обновляет индексную версию предоставленных путей, чтобы соответствовать предоставленной фиксации (или HEAD), но всегда извлекает версию индекса предоставленных путей в рабочее дерево.

29 голосов
/ 28 января 2016

Один простой случай использования при отмене изменения:1. Используйте сброс, если вы хотите отменить внесение изменений в измененный файл.2. Используйте checkout, если вы хотите отменить изменения в неустановленный файл / ы.

9 голосов
/ 21 марта 2015

Atlassian дает нам отличное объяснение о сброс Git , проверка Git и так, возврат Git .В этой статье объясняется различное использование этих команд на разных уровнях - файл, промежуточный снимок и фиксация.

https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

8 голосов
/ 20 февраля 2018

Ключевое отличие в двух словах состоит в том, что reset перемещает текущую ссылку ветвления , а checkout - нет (перемещает HEAD).

Как объясняет книга Pro Gitпод Сбросить демистификацию ,

Первое, что сделает reset, это переместит то, что HEAD указывает на .Это не то же самое, что изменение самой HEAD (что и делает checkout);reset перемещает ветку , на которую указывает HEAD.Это означает, что если для HEAD задана ветвь master (т. Е. Вы находитесь на ветке master), запуск git reset 9e5e6a4 начнется с того, что master укажет на 9e5e6a4.[выделение добавлено]

См. также ответ VonC на очень полезный отрывок текста и диаграммы из той же статьи, который я не буду здесь дублировать.

Конечно, есть намного больше деталей о том, какие эффекты checkout и reset могут оказать на индекс и рабочее дерево, в зависимости от того, какие параметры используются.Там может быть много сходств и различий между двумя командами.Но, на мой взгляд, самое важное различие заключается в том, перемещают ли они кончик текущей ветви.

1 голос
/ 11 сентября 2015

Две команды (сброс и проверка) совершенно разные.

checkout X НЕТ reset --hard X

Если X - это имя ветви, checkout X изменит текущую ветвь, а reset --hard X - нет.

...