Почему git checkout не удаляет новые файлы?

Предположим, я создаю (но не фиксирую) файл file.txt, а затем набираю git checkout HEAD или git checkout HEAD .. Я думал, что git checkout в основном перезаписал ваши текущие рабочие файлы моментальным снимком в фиксации, которую вы ему даете, поэтому я подумал, что это удалит file.txt. Но это не так. Почему?


person Jack M    schedule 27.08.2018    source источник
comment
Ну, потому что ваше предположение было неверным. git checkout не влияет на неотслеживаемые файлы.   -  person Sergio Tulentsev    schedule 27.08.2018
comment
Git управляет только отслеживаемыми файлами, и он довольно усердно работает, чтобы не допустить потери данных (что очень важно).   -  person coreyward    schedule 27.08.2018
comment
@SergioTulentsev Я не думаю, что это действительно хороший способ сформулировать это. Неотслеживаемый просто означает, что сейчас его нет в зоне подготовки. git checkout по-прежнему будет изменять файлы, которые отличаются от того, как они были в последнем коммите, даже если вы не внесли эти изменения.   -  person Jack M    schedule 27.08.2018
comment
@JackM нет, это не то, что означает неотслеживание в git.   -  person Sergio Tulentsev    schedule 27.08.2018
comment
@SergioTulentsev Согласно книге Pro Git и этому ответу: Нет! Отслеживаемые файлы — это файлы, которые находятся в индексе прямо сейчас.   -  person Jack M    schedule 27.08.2018
comment
@JackM книга по git не согласен: отслеживаемые файлы — это файлы, которые были в последнем снимке; они могут быть немодифицированными, модифицированными или поэтапными. Короче говоря, отслеживаемые файлы — это файлы, о которых Git знает. Неотслеживаемые файлы — это все остальное  — любые файлы в вашем рабочем каталоге, которые не были в вашем последнем снимке и не находятся в вашей промежуточной области.   -  person Sergio Tulentsev    schedule 27.08.2018
comment
@JackM: ха, еще проще, создай новый файл и сделай git status. Вы увидите новый файл в разделе Неотслеживаемые файлы.   -  person Sergio Tulentsev    schedule 27.08.2018
comment
Книга Git на самом деле не противоречит: индекс обычно заполняется через git checkout, так что в индексе прямо сейчас находятся те, что были в моментальном снимке. Но если вы измените индекс (например, на git rm --cached или git add), это изменит набор отслеживаемых файлов. Заметьте также, что git checkout <tree-ish> <paths> сильно отличается от команды git checkout <branch>. Некоторые (включая меня) считают, что оно должно использовать другое написание, то есть вообще не начинаться с git checkout.   -  person torek    schedule 27.08.2018
comment
@torek: да, мне было трудно объяснить моему другу-новичку, почему git checkout ведет себя так по-другому :)   -  person Sergio Tulentsev    schedule 27.08.2018
comment
git checkout ‹tree-ish› ‹paths› сильно отличается от команды git checkout ‹branch› О, это круто. Я просто буду здесь, плачу.   -  person Jack M    schedule 28.08.2018
comment
@JackM для удаления неотслеживаемых файлов вы можете использовать git clean, я исправил свой ответ ниже.   -  person Andrew Prigorshnev    schedule 30.08.2018


Ответы (2)


git checkout не перезаписывает вашу рабочую копию.

Он работает так же, как git reset --hard, но с важным отличием: git checkout безопасен для рабочего каталога, поэтому он не перезаписывает существующие изменения в вашем рабочем каталоге. На самом деле, он немного умнее — он пытается сделать тривиальное слияние в рабочем каталоге.

Итак, если вы хотите отменить все ваши изменения и просто получить снимок из HEAD, используйте вместо этого git reset --hard HEAD или просто git reset --hard.

Но даже git reset --hard не удаляет ваши неотслеживаемые файлы. Чтобы удалить неотслеживаемые файлы:

  • Выполнить git clean --dry-run. Он просто говорит вам, что будет удалено. Сделайте это, потому что очистка — опасная команда.
  • Запустите git clean --force, чтобы удалить неотслеживаемые файлы.

Вы можете найти более подробную информацию о git checkout и git reset здесь и об очистке здесь.

person Andrew Prigorshnev    schedule 27.08.2018
comment
Вижу, ты провел достаточно времени в тени. Время начать вносить свой вклад! :) - person Sergio Tulentsev; 27.08.2018
comment
@SergioTulentsev Да, спасибо, пора начинать :) - person Andrew Prigorshnev; 27.08.2018
comment
Я узнал, что даже git reset --hard не удаляет неотслеживаемые файлы, поэтому я исправил свой ответ. - person Andrew Prigorshnev; 30.08.2018

file.txt, будучи неотслеживаемым, является «невидимым» для Git. Если в извлекаемом коммите есть еще один файл с именем file.txt, он может быть перезаписан как побочный эффект извлечения, но Git не станет удалять неотслеживаемые файлы.

person chepner    schedule 27.08.2018
comment
Так что, если я удалю или изменю файл, который был в предыдущем коммите, и вернусь к этому коммиту, этот файл будет возвращен, но это только как побочный эффект? - person Jack M; 27.08.2018
comment
@JackM На самом деле, в этом случае вы получите ошибку проверки. Git заставит вас что-то сделать с ожидающим изменением, потому что он не может знать, каковы были ваши намерения здесь. Вы просто забыли зафиксировать? - person Sergio Tulentsev; 27.08.2018
comment
@SergioTulentsev Это неправда. Git не выдает ошибок и возвращает измененные файлы в их предыдущее состояние. - person Jack M; 27.08.2018
comment
@JackM: когда делаешь git checkout . или git checkout <ref>? Я описывал последнее. - person Sergio Tulentsev; 27.08.2018
comment
@SergioTulentsev git checkout HEAD . - если я просто делаю git checkout HEAD, он ничего не делает, но и не выдает явной ошибки (однако он выводит сообщение об изменении файла, что, я думаю, вы имеете в виду) . - person Jack M; 27.08.2018
comment
@JackM: да, именно это я и имел в виду. - person Sergio Tulentsev; 27.08.2018