Я случайно зафиксировал неправильные файлы в Git, но я ещё не переместил фиксацию на сервер.
Как я могу отменить эти фиксации из локального репозитория?
$ git commit -m "Something terribly misguided" # (1)
$ git reset HEAD~ # (2)
<< edit files as necessary >> # (3)
$ git add ... # (4)
$ git commit -c ORIG_HEAD # (5)
git status
, так что вам'нужно будет добавить их снова перед фиксацией). Если вы только хотите добавить больше изменений к предыдущему коммиту или изменить сообщение о коммите1, вы можете использовать git reset --soft HEAD~
, что похоже на git reset HEAD~
2, но оставляет существующие изменения поэтапными.git add
всё, что вы хотите включить в ваш новый коммит.reset
скопировал старую голову в .git/ORIG_HEAD
; commit
с -c ORIG_HEAD
откроет редактор, который изначально содержит сообщение журнала старого коммита и позволяет его редактировать. Если вам не нужно редактировать сообщение, вы можете использовать опцию -C
.Однако следует помнить, что если вы добавили новые изменения в индекс, то использование commit --amend
добавит их к предыдущему коммиту.
Если код уже выложен на вашем сервере и у вас есть права на перезапись истории (rebase), то:
git push origin master --force
Вы также можете посмотреть этот ответ:
Вышеприведенный ответ покажет вам git reflog
, который используется для выяснения SHA-1, к которому вы хотите вернуться. После того, как вы нашли точку, к которой вы хотите отменить возврат, используйте последовательность команд, как объяснено выше.
1 Обратите внимание, однако, что вам не нужно возвращаться к более раннему коммиту, если вы просто допустили ошибку в вашем сообщении о коммите. Более простой вариант - git reset
(чтобы удалить все изменения, которые вы сделали с тех пор), а затем git commit --amend
, который откроет ваш стандартный редактор сообщений фиксации, предварительно заполненный последним сообщением фиксации.
2 HEAD~
- то же самое, что и HEAD~1
.
Отмена фиксации немного пугает, если вы не знаете, как это работает. Но на самом деле это удивительно просто, если вы понимаете.
Скажем, у вас есть следующее, где C - это ваш HEAD, а (F) - состояние ваших файлов.
(F)
A-B-C
↑
master
Вы хотите nuke commit C и больше никогда его не видеть. Вы делаете следующее:
git reset --hard HEAD~1
Результат таков:
(F)
A-B
↑
master
Теперь B - это HEAD. Поскольку вы использовали --hard
, ваши файлы вернулись к состоянию на момент фиксации B.
А, но предположим, что коммит C был не катастрофой, а просто немного не тем. Вы хотите отменить коммит, но сохранить свои изменения для небольшого редактирования перед тем, как сделать лучший коммит. Начнём отсюда, с C в качестве HEAD:
(F)
A-B-C
↑
master
Вы можете сделать это, опустив --hard
:
git reset HEAD~1
В этом случае результат будет таким:
(F)
A-B-C
↑
master
В обоих случаях HEAD - это просто указатель на последний коммит. Когда вы делаете git reset HEAD~1
, вы говорите Git'у переместить указатель HEAD на один коммит назад. Но (если вы не используете --hard
) вы оставляете свои файлы в прежнем виде. Так что теперь git status
показывает изменения, которые вы проверили в C. Вы ничего не потеряли!
Для большей лёгкости вы можете даже отменить коммит, но оставить свои файлы и index:
git reset --soft HEAD~1
Это не только оставит ваши файлы в покое, но даже оставит ваш index в покое. Когда вы выполните команду git status
, вы увидите, что в индексе находятся те же файлы, что и раньше. На самом деле, сразу после этой команды вы можете выполнить git commit
, и вы повторно выполните тот же самый коммит, который вы только что выполнили.
И еще одно: Предположим, вы уничтожили коммит, как в первом примере, но потом обнаружили, что он вам всё-таки был нужен? Не повезло, верно?
Нет, всё ещё есть способ вернуть его обратно. Наберите git reflog
, и вы увидите список (частичный) коммитов shas (то есть хэшей), в которых вы перемещались. Найдите коммит, который вы уничтожили, и сделайте следующее:
git checkout -b someNewBranchName shaYouDestroyed
Теперь вы воскресили этот коммит. Коммиты на самом деле не уничтожаются в Git'е в течение примерно 90 дней, поэтому обычно вы можете вернуться и спасти тот, от которого не собирались избавляться.
Я долго не мог разобраться в этом, так что, возможно, это кому-то поможет...
Есть два способа "отменить" свой последний коммит, в зависимости от того, сделали ли вы уже свой коммит публичным (переместили в удалённый репозиторий) или нет:
Допустим, я сделал локальную фиксацию, но теперь хочу удалить эту фиксацию.
git log
commit 101: bad commit # latest commit, this would be called 'HEAD'
commit 100: good commit # second to last commit, this is the one we want
Чтобы вернуть всё к тому, что было до последней фиксации, нам нужно reset
на фиксацию перед HEAD
:
git reset --soft HEAD^ # use --soft if you want to keep your changes
git reset --hard HEAD^ # use --hard if you don't care about keeping the changes you made
Теперь git log
покажет, что наш последний коммит был удалён.
Если вы уже сделали свои коммиты публичными, вы захотите создать новый коммит, который "отменит" изменения, сделанные в предыдущем коммите (текущем HEAD).
git revert HEAD
Теперь ваши изменения будут отменены и готовы к фиксации:
git commit -m 'restoring the file I removed by accident'
git log
commit 102: restoring the file I removed by accident
commit 101: removing a file we don't need
commit 100: adding a file that we need
Для получения дополнительной информации ознакомьтесь с Git Basics - Undoing Things
Добавляйте/удаляйте файлы, чтобы получить то, что вам нужно:
git rm classdir
git add sourcedir
Затем внесите изменения в коммит:
git commit --amend
Предыдущий ошибочный коммит будет отредактирован, чтобы отразить новое состояние индекса - другими словами, всё будет так, как будто вы никогда не совершали ошибку.
Обратите внимание, что это следует делать только в том случае, если вы ещё не сделали push. Если вы уже сделали push, то вам нужно будет просто зафиксировать исправление обычным способом.
git rm yourfiles/*.class
git commit -a -m "deleted all class files in folder 'yourfiles'"
или
git reset --hard HEAD~1
Предупреждение: Приведенная выше команда навсегда удалит изменения в файлах .java
(и любых других файлах), которые вы хотели зафиксировать..
Команда hard reset
в HEAD-1
установит вашу рабочую копию в состояние фиксации перед вашей ошибочной фиксацией.
Замените файлы в индексе:
git rm --cached *.class
git add *.java
Затем, если это частная ветвь, измените коммит:
git commit --amend
Или, если это общая ветвь, сделайте новый коммит:
git commit -m 'Replace .class files with .java files'
(чтобы изменить предыдущий коммит, используйте замечательную interactive rebase).
ProTip™: Добавьте *.class
в gitignore, чтобы это больше не повторялось.
Внесение изменений в коммит - идеальное решение, если вам нужно изменить последний коммит, но более общим решением является reset
.
Вы можете сбросить git на любой коммит с помощью:
git reset @~N
Где N
- это количество коммитов до HEAD
, а @~
сбрасывает на предыдущий коммит.
Таким образом, вместо изменения коммита вы можете использовать:
git reset @~
git add *.java
git commit -m "Add .java files"
Посмотрите git help reset
, особенно разделы --soft
--mixed
и --hard
, чтобы лучше понять, что это делает.
Если вы что-то напутали, вы всегда можете воспользоваться рефлогом, чтобы найти пропущенные коммиты:
$ git reset @~
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~
2c52489 HEAD@{1}: commit: added some .class files
$ git reset 2c52489
... and you're back where you started
Используйте git revert <commit-id>
.
Чтобы получить идентификатор коммита, просто используйте git log
.
Если вы планируете полностью отменить локальный коммит, что бы вы ни изменили в нем, и если вас это не беспокоит, просто выполните следующую команду.
git reset --hard HEAD^1
(Эта команда проигнорирует весь ваш коммит, и ваши изменения будут полностью потеряны из вашего локального рабочего дерева). Если вы хотите отменить фиксацию, но хотите, чтобы ваши изменения находились в области постановки (до фиксации, как и после git add
), то выполните следующую команду.
git reset --soft HEAD^1
Теперь ваши зафиксированные файлы попадут в область постановки. Предположим, если вы хотите поднять файлы, потому что вам нужно отредактировать какое-то неправильное содержимое, то выполните следующую команду
git reset HEAD
Теперь зафиксированные файлы перейдут из области staged в область unstaged. Теперь файлы готовы к редактированию, поэтому, что бы вы ни изменили, вам нужно пойти отредактировать, добавить это и сделать свежий/новый коммит.
Если у вас установлен Git Extras, вы можете запустить git undo
, чтобы отменить последний коммит. git undo 3
отменит последние 3 фиксации.
Я хотел отменить последние 5 коммитов в нашем общем репозитории. Я нашел идентификатор ревизии, до которой я хотел откатиться. Затем я набрал следующее.
prompt> git reset --hard 5a7404742c85
HEAD is now at 5a74047 Added one more page to catalogue
prompt> git push origin master --force
Total 0 (delta 0), reused 0 (delta 0)
remote: bb/acl: neoneye is allowed. accepted payload.
To [email protected]:thecompany/prometheus.git
+ 09a6480...5a74047 master -> master (forced update)
prompt>
Я предпочитаю использовать git rebase -i
для этой работы, потому что появляется хороший список, в котором я могу выбрать коммиты, от которых нужно избавиться. Возможно, это не так прямолинейно, как некоторые другие ответы здесь, но это просто чувствуется правильным.
Выберите, сколько коммитов вы хотите перечислить, затем вызовите вот так (чтобы перечислить последние три)
git rebase -i HEAD~3
Образец списка
pick aa28ba7 Sanity check for RtmpSrv port
pick c26c541 RtmpSrv version option
pick 58d6909 Better URL decoding support
Затем Git удалит коммиты для любой строки, которую вы удалите.
Используйте git-gui (или аналогичный) для выполнения git commit --amend
. В графическом интерфейсе вы можете добавить или удалить отдельные файлы из фиксации. Вы также можете изменить сообщение о фиксации.
Просто верните вашу ветку в предыдущее место (например, с помощью gitk
или git rebase
). Затем повторно примените свои изменения из сохраненной копии. После сборки мусора в вашем локальном репозитории будет казаться, что нежелательная фиксация никогда не происходила. Чтобы сделать все это одной командой, используйте git reset HEAD~1
.
Слово предупреждения: Неосторожное использование git reset
- это хороший способ привести вашу рабочую копию в запутанное состояние. Я рекомендую новичкам в Git избегать этого, если они могут.
Выполните reverse cherry pick (git-revert), чтобы отменить изменения.
Если вы ещё не перетащили другие изменения в свою ветку, вы можете просто сделать...
git revert --no-edit HEAD
Затем переместите обновленную ветку в общий репозиторий.
*В истории коммитов будут показаны оба коммита по отдельности.
Также обратите внимание: не стоит этого делать, если над веткой может работать кто-то ещё.
git push --delete (branch_name) ## remove public version of branch
Очистите ветку локально, а затем перетолкните...
git push origin (branch_name)
Если вы хотите навсегда отменить коммит и вы клонировали какой-либо репозиторий.
Идентификатор коммита можно увидеть по следующим параметрам
git log
Тогда вы можете сделать это:
git reset --hard <commit_id>
git push origin <branch_name> -f
Если вы совершили хлам, но не оттолкнули,
git reset --soft HEAD~1
HEAD~1 - это сокращение для коммита перед head. Также вы можете сослаться на SHA-1 хэша, если хотите сбросить. Опция --soft удалит коммит, но оставит все ваши изменённые файлы "Changes to be committed", как об этом говорит git status.
Если вы хотите избавиться от любых изменений отслеживаемых файлов в рабочем дереве с момента фиксации перед head, используйте "--hard" вместо этого.
ИЛИ
Если вы уже вытолкнули, а кто-то вытащил, что обычно бывает в моём случае, вы не можете использовать git reset. Однако вы можете сделать git revert,
git revert HEAD
Это создаст новый коммит, который отменит всё, что было внесено случайным коммитом.
На SourceTree (GUI для GitHub) вы можете щелкнуть правой кнопкой мыши на фиксации и сделать 'Reverse Commit'. Это отменит ваши изменения.
В терминале:
В качестве альтернативы можно использовать:
git revert
Или:
git reset --soft HEAD^ # Use --soft if you want to keep your changes.
git reset --hard HEAD^ # Use --hard if you don't care about keeping your changes.
Одна команда:
git reset --soft 'HEAD^'
Она отлично работает для отмены последнего локального коммита!
Просто переустановите его, выполнив приведенную ниже команду с помощью git
:
git reset --soft HEAD~1
Объяснение: что делает git reset
, это по сути reset
на любой коммит, к которому вы хотите вернуться, затем если вы объедините его с --soft
ключом, он вернется назад, но сохранит изменения в вашем файле(ах), так что вы вернетесь к стадии, на которой файл был только что добавлен, HEAD
это голова ветки и если вы объедините его с ~1
(в этом случае вы также используете HEAD^
), он вернется только на один коммит, что вам и нужно...
Я создал шаги на изображении ниже более подробно для вас, включая все шаги, которые могут произойти в реальной ситуации и фиксации кода:
**Как отменить последний коммит Git?
Чтобы вернуть всё к тому состоянию, в котором оно было до последнего коммита, нам нужно вернуться к коммиту перед HEAD.
Если вы не хотите сохранять сделанные изменения:
git reset --hard HEAD^.
Если вы хотите сохранить сделанные изменения:
git reset --soft HEAD^.
Теперь проверьте свой журнал git. Он покажет, что наш последний коммит был удален.
Используйте reflog для нахождения правильного состояния
git reflog
REFLOG BEFORE RESET
Выберите правильный reflog (f3cb6e2 в моем случае) и введите
git reset --hard f3cb6e2
После этого HEAD репозитория будет сброшен на этот HEADid LOG AFTER RESET
В конечном итоге рефлог выглядит так, как показано на рисунке ниже
REFLOG FINAL
"Сбросить рабочее дерево на последний коммит"
git reset --hard HEAD^
"Очистить неизвестные файлы из рабочего дерева"
git clean
см. - Краткий справочник по Git
NOTE: Эта команда удалит ваш предыдущий коммит, поэтому используйте ее с осторожностью! Команда git reset --hard
более безопасна.