Как мне вернуть все локальные изменения в проекте, управляемом Git, в предыдущее состояние?

У меня есть проект, в котором я участвовал git init. После нескольких коммитов я сделал git status, который сказал мне, что все было в актуальном состоянии и никаких локальных изменений не было.

Затем я внес несколько последовательных изменений и понял, что хочу все выбросить и вернуться в исходное состояние. Эта команда сделает это за меня?

git reset --hard HEAD

person Jacques René Mesrine    schedule 18.07.2009    source источник


Ответы (16)


Если вы хотите отменить изменения, внесенные в вашу рабочую копию, сделайте следующее:

git checkout .

Если вы хотите отменить изменения, внесенные в индекс (т.е. добавленные вами), сделайте это. Предупреждение: это приведет к сбросу всех ваших не отправленных коммитов в состояние мастера!:

git reset

Если вы хотите отменить зафиксированное изменение, сделайте следующее:

git revert <commit 1> <commit 2>

Если вы хотите удалить неотслеживаемые файлы (например, новые файлы, сгенерированные файлы):

git clean -f

Или неотслеживаемые каталоги (например, новые или автоматически созданные каталоги):

git clean -fd
person 1800 INFORMATION    schedule 18.07.2009
comment
fwiw по прошествии такого длительного времени git checkout path/to/file вернет только локальные изменения в path/to/file - person Matijs; 22.08.2011
comment
+1 в ответах ниже также упоминает git clean -f (чтобы удалить неотслеживаемые изменения) и -fd (чтобы также удалить неотслеживаемые каталоги) - person ptdev; 05.07.2012
comment
С помощью команды git git checkout branchId он будет просматривать измененные файлы, но возврата не будет. Я должен использовать git reset --hard - person Huluvu424242; 21.10.2012
comment
и если вы также хотите очистить неотслеживаемые файлы, прочтите это stackoverflow.com/questions/61212/ - person Surasin Tancharoen; 06.11.2012
comment
➜ API git: (master) ✗ git checkout. ➜ API git: (master) ✗ git reset ➜ API git: (master) ✗ git revert ... fatal: пустой набор фиксаций пройден ➜ API git: (master) ✗ gst На ветке master Ваша ветка актуальна с "происхождение / хозяин". Не отслеживаемые файлы: (используйте git add ‹file› ... чтобы включить в то, что будет зафиксировано) V1 / css / js / ничего не изменилось - person antiqe; 20.02.2015
comment
Будьте осторожны: git reset возвращает ваши коммиты к мастеру! (Для меня было недостаточно ясно, что added будет включать Commit, и я случайно потерял свои изменения) - person falsarella; 25.04.2015
comment
Могу ли я отменить изменения pull, если изменения не были зафиксированы? stackoverflow.com/questions/30763832/ - person Android Developer; 10.06.2015
comment
git checkout . и git reset [--hard HEAD] не работали, мне пришлось сделать git clean -fd, чтобы отменить мои изменения. - person BrainSlugs83; 16.06.2015
comment
Я также добавил некоторые подробности о git clean - person 1800 INFORMATION; 16.06.2015
comment
git reset не сбрасывает ваши изменения, git reset --hard это делает. - person Cerin; 06.07.2016
comment
@Cerin git reset действует как git reset --mixed (сбрасывает индекс, но не рабочее дерево (т.е. измененные файлы сохраняются, но не помечаются для фиксации) и сообщает о том, что не было обновлено. Это действие по умолчанию), о чем я сказал. git-scm.com/docs/git-reset - person 1800 INFORMATION; 11.07.2016
comment
Одно замечание: сделайте git checkout . в корневом каталоге вашего проекта. Или в подкаталоге, который вы хотите вернуть. - person exebook; 20.07.2016
comment
git checkout . в корне моего проекта применялся только к файлам в этом каталоге, мне пришлось сделать git checkout *, чтобы вернуть все подкаталоги. - person danio; 27.04.2017
comment
git reset отключает этапы, не сбрасывает неопубликованные коммиты в мастер - person rok; 31.12.2017
comment
Предупреждение совершенно неверное! Прежде всего, git reset работает с текущей веткой (HEAD), и то, что он делает, не имеет ничего общего с основной веткой. Кроме того, сброс не имеет ничего общего с неопубликованными коммитами, и вы не потеряете их автоматически только потому, что вы использовали git reset. - person disklosr; 03.01.2018
comment
Я использовал git clean -fd, а затем git fetch & git check ‹другую ветку›. Это сработало! - person Khachornchit Songsaen; 04.06.2018
comment
Вам не всегда нужно использовать --hard. На самом деле, иногда это неправильно ... делать. Возможно, вам повезет больше с командой --gentle. - person JOATMON; 05.12.2018
comment
Полностью согласен с @disklosr, предупреждение о git reset в лучшем случае вводит в заблуждение, а в худшем - ложно. Создается впечатление, что reset каким-то образом вернет вашу текущую ветку к ветке master, что совершенно неверно. reset не работает с ветвями, поэтому все, что он делает, относится к вашей текущей ветке, даже если это не master. Во-вторых, он не меняет рабочее дерево, поэтому вы не можете потерять данные с reset. Если у вас есть неопубликованные коммиты, они исчезнут из локальной истории, но фактические файлы не будут изменены. Вы можете снова совершить то же самое! - person Mike; 11.11.2020
comment
Я был бы злым и проголосовал бы против этого (не то чтобы это имело значение), но я отменил изменение (НЕ нажимал его), и после git reset, git reset --hard, git clean, git checkout, git checkout - force ... Я наконец понял, что, возможно, ответ - 'rm -rf.; git clone .... ' потому что, черт возьми, продолжает говорить, что я на один коммит ВПЕРЕД удалением, и, черт возьми, я просто сбросил и стер все мои локальные изменения, так что НЕТ, я нет! Нашел ответ ниже: git reset --hard origin / develop Без origin / branch_name он на самом деле не будет полностью сброшен .. - person Traderhut Games; 09.02.2021

Примечание. Вы также можете запустить

git clean -fd

as

git reset --hard

не удаляет неотслеживаемые файлы, тогда как git-clean удаляет любые файлы из отслеживаемого корневого каталога, которые не находятся под отслеживанием git. ВНИМАНИЕ - БУДЬТЕ ОСТОРОЖНЫ! Полезно сначала запустить пробный запуск с помощью git-clean, чтобы увидеть, что он удалит.

Это также особенно полезно, когда вы получаете сообщение об ошибке.

~"performing this command will cause an un-tracked file to be overwritten"

Что может произойти, когда вы делаете несколько вещей, одна из которых - обновление рабочей копии, когда вы и ваш друг оба добавили новый файл с тем же именем, но он сначала передал его в систему управления версиями, и вы не заботитесь об удалении своей неотслеживаемой копии .

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

person Antony Stubbs    schedule 20.07.2009
comment
Команда очистки файла - git clean -f. Не отслеживаемые каталоги удаляются с помощью git clean -d - person Jonathan Mitchell; 03.04.2011
comment
git clean -fd (для -d требуется сила) - person electblake; 04.04.2011
comment
-n или --dry-run - это флаги для пробного запуска. - person stephenbez; 29.07.2014
comment
git clean -ffd, если у вас есть другой репозиторий git в вашем репозитории git. Без двойного f он не был бы удален. - person Trismegistos; 07.10.2016

Повторно клонировать

GIT=$(git rev-parse --show-toplevel)
cd $GIT/..
rm -rf $GIT
git clone ...
  • ✅ Удаляет локальные, не отправляемые коммиты
  • ✅ Отменяет изменения, внесенные вами в отслеживаемые файлы
  • ✅ Восстанавливает отслеженные файлы, которые вы удалили
  • ✅ Удаляет файлы / каталоги, перечисленные в .gitignore (например, файлы сборки)
  • ✅ Удаляет файлы / каталоги, которые не отслеживаются и не находятся в .gitignore
  • ???? Вы не забудете такой подход
  • ???? Избыточная пропускная способность

Ниже приведены другие команды, которые я забываю ежедневно.

Очистить и сбросить

git clean --force -d -x
git reset --hard
  • ❌ Удаляет локальные, не отправляемые коммиты
  • ✅ Отменяет изменения, внесенные вами в отслеживаемые файлы
  • ✅ Восстанавливает отслеженные файлы, которые вы удалили
  • ✅ Удаляет файлы / каталоги, перечисленные в .gitignore (например, файлы сборки)
  • ✅ Удаляет файлы / каталоги, которые не отслеживаются и не находятся в .gitignore

Чистый

git clean --force -d -x
  • ❌ Удаляет локальные, не отправляемые коммиты
  • ❌ Отменяет изменения, внесенные вами в отслеживаемые файлы
  • ❌ Восстанавливает отслеженные файлы, которые вы удалили
  • ✅ Удаляет файлы / каталоги, перечисленные в .gitignore (например, файлы сборки)
  • ✅ Удаляет файлы / каталоги, которые не отслеживаются и не находятся в .gitignore

Сброс настроек

git reset --hard
  • ❌ Удаляет локальные, не отправляемые коммиты
  • ✅ Отменяет изменения, внесенные вами в отслеживаемые файлы
  • ✅ Восстанавливает отслеженные файлы, которые вы удалили
  • ❌ Удаляет файлы / каталоги, перечисленные в .gitignore (например, файлы сборки)
  • ❌ Удаляет файлы / каталоги, которые не отслеживаются и не находятся в .gitignore

Примечания

Контрольный пример для подтверждения всего вышеперечисленного (используйте bash или sh):

mkdir project
cd project
git init
echo '*.built' > .gitignore
echo 'CODE' > a.sourceCode
mkdir b
echo 'CODE' > b/b.sourceCode
cp -r b c
git add .
git commit -m 'Initial checkin'
echo 'NEW FEATURE' >> a.sourceCode
cp a.sourceCode a.built
rm -rf c
echo 'CODE' > 'd.sourceCode'

См. также

  • git revert, чтобы делать новые коммиты, отменяющие предыдущие.
  • git checkout, чтобы вернуться во времени к предыдущим коммитам (может потребоваться сначала выполнить вышеуказанные команды)
  • git stash то же, что и git reset выше, но вы можете отменить его
person William Entriken    schedule 20.03.2017
comment
Извините за кражу сверху ответов. Я постоянно использую эту ссылку, в основном пишу для себя. - person William Entriken; 20.03.2017
comment
Я почти уверен, что первый вариант (Повторное клонирование) действительно удаляет локальные, не отправленные коммиты :) - person Marandil; 08.05.2017
comment
Что означают красный крестик и зеленая галочка? Отменяет ли красный крестик предложение рядом с ним? - person styfle; 18.05.2017
comment
@styfle ✅ - это то, что он делает, ❌ - это то, что он не делает - person William Entriken; 25.05.2017
comment
@FullDecent Это немного сбивает с толку. ❌ НЕ удаляет локальные коммиты без отправки. Это означает, что он НЕ удаляет. Двойной минус означает, что он удаляет? - person styfle; 25.05.2017
comment
Это могло бы иметь больше смысла в таблице и поставить ✅, если команда делает то, что делает. - person styfle; 25.05.2017
comment
Спасибо, двойные негативы исправлены, потому что одиночный негатив БОЛЬШЕ негативного - person William Entriken; 10.08.2018
comment
О флаге -x в git clean -f -d -x: если указана опция -x, игнорируемые файлы также удаляются. Это может быть полезно, например, для удаления всех продуктов сборки. - из документации GIT - person Alex; 09.07.2019
comment
Я запустил git reset --hard, и он восстановил мои отслеживаемые файлы, но НЕ удалял неотслеживаемые файлы. фактически, когда я побежал git status после, он сказал Untracked files: (use "git add <file>..." to include in what will be committed). чего я и хотел! почему вы говорите, что он удаляет неотслеживаемые файлы? - person calyxofheld; 07.02.2020
comment
@calyxofheld не говорит, что удаляет неотслеживаемые файлы. ❌ означает, что не работает, ✅ означает, что работает. В разделе «Сброс» я вижу ❌ Удаляет файлы / каталоги, которые не отслеживаются и не находятся в .gitignore. - person vrnvorona; 14.10.2020

Если вы хотите отменить все изменения И быть в курсе текущего удаленного мастера (например, вы обнаружите, что главный HEAD переместился вперед, так как вы от него разветвились, и ваш push «отклоняется»), вы можете использовать

git fetch  # will fetch the latest changes on the remote
git reset --hard origin/master # will set your local branch to match the representation of the remote just pulled down.
person Michael Durrant    schedule 22.04.2015
comment
Кажется важным указать origin в git reset --hard origin/master (что работает) - без него (т.е. git reset --hard) ничего не изменится. - person Jake; 02.10.2019
comment
У меня были некоторые локальные изменения, и я не мог избавиться от них с помощью какой-либо команды, которую я сделал git reset --hard origin / master, и он также смог вытащить изменения мастера - person abhishek ringsia; 30.12.2019

Загляните в git-reflog. В нем будут перечислены все состояния, которые он запомнил (по умолчанию 30 дней), и вы можете просто проверить то, которое хотите. Например:

$ git init > /dev/null
$ touch a
$ git add .
$ git commit -m"Add file a" > /dev/null
$ echo 'foo' >> a
$ git commit -a -m"Append foo to a" > /dev/null
$ for i in b c d e; do echo $i >>a; git commit -a -m"Append $i to a" ;done > /dev/null
$ git reset --hard HEAD^^ > /dev/null
$ cat a
foo
b
c
$ git reflog
145c322 HEAD@{0}: HEAD^^: updating HEAD
ae7c2b3 HEAD@{1}: commit: Append e to a
fdf2c5e HEAD@{2}: commit: Append d to a
145c322 HEAD@{3}: commit: Append c to a
363e22a HEAD@{4}: commit: Append b to a
fa26c43 HEAD@{5}: commit: Append foo to a
0a392a5 HEAD@{6}: commit (initial): Add file a
$ git reset --hard HEAD@{2}
HEAD is now at fdf2c5e Append d to a
$ cat a
foo
b
c
d
person William Pursell    schedule 19.07.2009
comment
Большое спасибо, Уильям, за git reflog. Я сбросил свое дерево до старой версии и не знаю, как вернуться к последней. твой git reflog спас меня. Еще раз спасибо. - person palaniraja; 23.02.2011
comment
спас меня тоже! В моем случае мое приключение с git rebase -i пошло не так (закончилось тем, что некоторые коммиты были уничтожены из-за ошибки редактирования). Благодаря этому совету я снова в хорошем состоянии! - person paneer_tikka; 15.05.2013
comment
Что вы имеете в виду под 30-дневным дефолтом !? - person Mohe TheDreamy; 09.11.2016
comment
@MoheTheDreamy Я имею в виду, что есть ограничение по времени. В конце концов, сборщик мусора удалит недостижимые ссылки, когда их возраст превысит этот предел. Раньше по умолчанию (и, возможно, остается) 30 дней. Поэтому старые ссылки могут быть недоступны. - person William Pursell; 10.11.2016

Прочитав кучу ответов и попробовав их, я обнаружил различные крайние случаи, которые означают, что иногда они не полностью очищают рабочую копию.

Вот мой текущий сценарий bash для этого, который работает постоянно.

#!/bin/sh
git reset --hard
git clean -f -d
git checkout HEAD

Запускаем из корневого каталога рабочей копии.

person Scott Davey    schedule 04.06.2014
comment
Последняя команда дает мне error: pathspec 'HEAD' did not match any file(s) known to git. - person 0xC0000022L; 18.03.2015
comment
У меня это сработало, когда я вынул ... git checkout HEAD - person Jester; 25.09.2015
comment
git reset --hard восстанавливает отслеживаемые файлы (поэтапно или нет), git clean -f -d удаляет неотслеживаемые файлы, git checkout -- HEAD зачем нам тогда это нужно? - person v.shashenko; 22.10.2015
comment
Нам не нужен двойной дефис. Должно быть опечатка. - person Farax; 20.12.2016
comment
Удалено -- из git checkout -- HEAD, поскольку это недопустимая команда, а git checkout HEAD -. - person Dominic Comtois; 18.08.2020

просто выполнить -

git stash

он удалит все ваши локальные изменения. и вы также можете использовать его позже, выполнив -

git stash apply 
person piyushmandovra    schedule 24.04.2015
comment
использование git stash pop автоматически удалит для вас самое верхнее спрятанное изменение - person Arrow Cen; 14.12.2015
comment
git stash drop, чтобы удалить последнее сохраненное состояние без применения к рабочей копии. - person deerchao; 22.03.2016
comment
git stash apply не добавляет вновь созданные файлы - person Ravistm; 09.09.2019

ВПЕРЕД ОПАСНОСТЬ: (пожалуйста, прочтите комментарии. Выполнение команды, предложенной в моем ответе, может удалить больше, чем вы хотите)

чтобы полностью удалить все файлы, включая каталоги, которые мне пришлось запустить

git clean -f -d
person Tobias Gassmann    schedule 11.09.2013
comment
Чтобы избавить кого-либо от боли, через которую я только что прошел: это также удалит файлы .gitignore-d! - person landons; 18.09.2013
comment
извините, если я причинил вам какие-либо проблемы. Тогда я просто попытался вернуться и удалить все в этой папке. Я не помню точных обстоятельств, но -d было единственным, что у меня сработало. Надеюсь, я не причинил вам слишком много боли :-) - person Tobias Gassmann; 27.11.2013
comment
без вреда. У меня были резервные копии, но это, вероятно, требует отказа от ответственности;) - person landons; 27.11.2013

Встречал похожую проблему. Решение состоит в том, чтобы использовать git log, чтобы узнать, какая версия локальной фиксации отличается от удаленной. (Например, версия 3c74a11530697214cbcc4b7b98bf7a65952a34ec).

Затем используйте git reset --hard 3c74a11530697214cbcc4b7b98bf7a65952a34ec, чтобы отменить изменение.

person Patrick    schedule 28.08.2013

Я искал похожую проблему,

Хотел выбросить локальные коммиты:

  1. клонировал репозиторий (git clone)
  2. переключился на ветку dev (git checkout dev)
  3. сделал несколько коммитов (git commit -m "commit 1")
  4. но решил выбросить эти локальные коммиты, чтобы вернуться к удаленному (origin / dev)

Так было и ниже:

git reset --hard origin/dev

Проверять:

git status  

        On branch dev  
        Your branch is up-to-date with 'origin/dev'.  
        nothing to commit, working tree clean  

теперь локальные коммиты потеряны, возвращаются к исходному клонированному состоянию, пункт 1 выше.

person Manohar Reddy Poreddy    schedule 25.02.2017
comment
спасибо, это единственное, что у меня сработало - git reset --hard origin - person Nisim Naim; 10.11.2019
comment
рад узнать, что это помогло. - person Manohar Reddy Poreddy; 10.11.2019

Возможно, вам не обязательно захочется / нуждаться в хранении вашей работы / файлов в вашем рабочем каталоге, а вместо этого просто полностью избавиться от них. Команда git clean сделает это за вас.

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

Имейте в виду, что вы должны быть очень осторожны с этой командой, поскольку она предназначена для удаления файлов из вашего локального рабочего каталога, которые НЕ ОТСЛЕЖИВАЮТСЯ. если вы внезапно передумаете после выполнения этой команды, вы не сможете вернуться к просмотру содержимого файлов, которые были удалены. Более безопасная альтернатива - выполнить

git stash --all

который удалит все, но сохранит все в тайнике. Позже этот тайник можно будет использовать.

Однако, если вы действительно хотите удалить все файлы и очистить рабочий каталог, вам следует выполнить

git clean -f -d

Это удалит все файлы, а также все подкаталоги, в которых нет элементов в результате выполнения команды. Перед выполнением команды git clean -f -d разумно запустить

git clean -f -d -n

который покажет вам предварительный просмотр того, что БУДЕТ удалено после выполнения git clean -f -d

Итак, вот краткое изложение ваших вариантов от наиболее агрессивного до наименее агрессивного.


Вариант 1: удалить все файлы локально (наиболее агрессивно)

git clean -f -d

Вариант 2: предварительный просмотр вышеуказанного воздействия (предварительный просмотр наиболее агрессивный)

git clean -f -d -n

Вариант 3: убрать все файлы (наименее агрессивно)

`git stash --all` 
person jbooker    schedule 14.06.2016

Попробуйте это, чтобы отменить все незавершенные изменения в локальной ветке

$ git reset --hard HEAD

Но если вы видите такую ​​ошибку:

fatal: Unable to create '/directory/for/your/project/.git/index.lock': File exists.

Вы можете перейти в папку .git и удалить файл index.lock:

$ cd /directory/for/your/project/.git/
$ rm index.lock

Наконец, снова запустите команду:

$ git reset --hard HEAD
person Janderson Silva    schedule 03.01.2017

Добавляем сюда еще один вариант.

Я имею в виду заголовок: Отменить локальные изменения.
Это также может применяться к изменениям, которые не были подготовлены для фиксации.

В этом случае вы можете использовать:

git restore <file>

Чтобы вернуться в предыдущее состояние.

person RtmY    schedule 06.09.2020
comment
Чтобы восстановить все изменения файлов в текущем локальном каталоге, вы можете использовать: git restore. - person John C; 02.12.2020
comment
Лучший ответ здесь - person maverick; 25.05.2021
comment
восстановление - это не команда git - person NemyaNation; 16.07.2021
comment
Пожалуйста, запустите git help - вы должны увидеть это там .. (: - person RtmY; 16.07.2021

Этот вопрос больше касается более широкого сброса / возврата репозитория, но в случае, если вы заинтересованы в отмене отдельного изменения, я добавил здесь аналогичный ответ:

https://stackoverflow.com/a/60890371/2338477

Ответы на вопросы:

  • Как отменить отдельные изменения с сохранением изменений в истории git или без него

  • Как вернуться к старой версии для перезапуска из того же состояния

person TarmoPikaro    schedule 28.03.2020

Если вы просто хотите удалить все изменения, выберите git checkout . Это быстрее и проще.

person lLauriix    schedule 10.06.2021

Попробуйте это, если вы находитесь в верхнем каталоге проекта:

git restore .

Если нет, используйте:

git restore :/

Если вы хотите отменить локальные изменения для подмножества:

  • восстановить все рабочие файлы дерева с помощью top pathspec magic: git restore :/
  • восстановить все файлы в текущем каталоге: git restore .
  • тип файла (например, все исходные файлы C): git restore '*.c'

Дополнительные сведения см. В документации по восстановлению git.

Чтобы удалить неотслеживаемые файлы: git clean -f

person amra    schedule 22.07.2021