Как я могу снова разархивировать свои файлы после локальной фиксации?

268

Я выполнил следующую команду

git add <foo.java>
git commit -m "add the foo.java file"

Как я могу удалить свой локальный коммит сейчас и untage foo.java?

Если я git reset --hardнаберу текст, я обнаружу, что он вернул мой измененный foo.javaк исходному.

Кит Хо
источник

Ответы:

453

git reset --soft HEAD~1должен делать то, что вы хотите. После этого у вас будут первые изменения в индексе (видимые с git diff --cached), а ваши новейшие изменения не внесены. git statusбудет выглядеть так:

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.java
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   foo.java
#

Затем вы можете сделать git add foo.javaи зафиксировать оба изменения одновременно.

Антти
источник
Я отредактировал ответ: «Изменения, которые должны быть зафиксированы» имеют первые изменения, а «изменения, не подготовленные для фиксации», имеют вторые изменения.
Антти
4
То, что описано в этом ответе, на самом деле то, что git commit --amendделает; но с гораздо более сложным рабочим процессом. Это не отвечает на вопрос, заданный OP, несмотря на то, что он дает правильное направление ( git reset).
7heo.tk
2
Пришлось заменить '^' на '~', чтобы все заработало, так что это выглядит так:git reset --soft HEAD~
Shahar
3
сделать git reset --soft HEAD ~ 1, затем git reset HEAD
Joko Wandiro
идеальный ответ на то, что я хочу!
DeepInJava
78

Использование:

git reset HEAD^

Это делает «смешанный» сброс по умолчанию, который будет делать то, что вы просили; поместите foo.java в unstaged, удалив самый последний коммит.

Райан Стюарт
источник
2
Не могли бы вы объяснить мне, что такое «смешанный» сброс, «мягкий» сброс и «жесткий» сброс?
Кит Хо,
1
@Kit Ho - git reset manual имеет отличные описания этих.
manojlds
4
@Kit, @manojlds: так же работает stackoverflow.com/questions/2530060/… (бесстыдная вилка)
Cascabel
5
Это на самом деле единственный правильный ответ. Две другие ответы будут ставить файлы снова после выполнения фиксации.
7heo.tk
git reset --softне работа, но git reset HEAD^сделал
wordsforthewise
43

Для меня следующий способ более читабелен (а значит, предпочтительнее):

git reset HEAD~1

Вместо 1этого может быть любое количество коммитов, которые вы хотите удалить.

Андрей Дейнеко
источник
39

git reset --softтолько для этого: это как git reset --hard, но не касается файлов.

wRAR
источник
4
Это было самое понятное объяснение, которое я когда-либо слышал (всего за 11 слов)! Спасибо!
phreakhead
3
Этот ответ неверен. git resetmsgstr "это как, git reset --hardно не трогает файлы." Не git reset --soft. git reset --softвнесет изменения, поэтому вам не нужно будет добавлять их в стадию, если вы хотите их зафиксировать, но вам придется git resetих (да, во второй раз и без --soft), если вы этого не сделаете. Так что ответ короткий, но неверный.
7heo.tk
12

Для удаления всех файлов в вашем последнем коммите -

git reset HEAD~

Lavika
источник
8

«Сброс» - это способ отмены изменений локально. При фиксации вы сначала выбираете изменения для включения в « git add » - это называется «постановка». И после того , как изменения в постановке, то « GIT совершить » их.

Чтобы отступить от постановки или коммита, вы «сбрасываете» ГОЛОВУ. В ветке HEAD - это переменная git, которая указывает на самый последний коммит. Так что, если вы поставили, но не сделали коммит, вы " git reset HEAD " Это поддерживает текущую ГОЛОВУ, снимая изменения со сцены. Это сокращение от " git reset - смешанный HEAD ~ 0 ".

Если вы уже зафиксировали, значит, HEAD уже продвинут, поэтому вам необходимо выполнить резервное копирование к предыдущему коммиту. Здесь вы « сбросите HEAD ~ 1 » или « сбросите HEAD ^ 1 » или « сбросите HEAD ~ » или « сбросите HEAD ^ » - все ссылки на HEAD минус один.

Какой символ лучше, ~ или ^? Думайте о тильде как о едином потоке - когда каждый коммит имеет одного родителя и это просто последовательность изменений в последовательности, вы можете ссылаться на поток обратно, используя тильду, как HEAD ~ 1, HEAD ~ 2, HEAD ~ 3, для родителя, прародителя, прадедушки и т. Д. (Технически это поиск первого родителя в более ранних поколениях).

Когда происходит слияние, коммиты имеют более одного родителя. Вот когда в игру вступает ^ каретка - вы можете помнить, потому что она показывает, что ветви собираются вместе. С помощью каретки HEAD ^ 1 будет первым родителем, а HEAD ^ 2 будет вторым родителем одного коммита - например, мать и отец.

Таким образом, если вы просто возвращаетесь на один прыжок для фиксации с одним родителем, то HEAD ~ и HEAD ^ эквивалентны - вы можете использовать любой из них.

Кроме того, сброс может быть --soft , --mixed или --hard . Мягкий сброс просто возвращает коммит - он сбрасывает HEAD, но не извлекает файлы из предыдущего коммита, поэтому все изменения в рабочем каталоге сохраняются. И --soft reset даже не очищает сцену (также известную как индекс ), поэтому все файлы, которые были размещены, все еще будут на сцене.

--Mixed сброса (по умолчанию) также не проверяет файлы из ранее фиксации, поэтому все изменения сохраняются, но стадия очищается. Вот почему простой « Git Reset HEAD » очистит сцену.

--Hard сброс сбрасывает ГОЛОВА, и он очищает почву, но он также проверяет все файлы из ранее фиксации и поэтому он переписывает любые изменения.

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

Кроме того , вы можете копить свои изменения , если вы хотите сохранить их, проверить ранее фиксации, снимите копить изменения, стадии их, создать новый коммит, а затем нажмите что.

HieroB
источник
+1 за подробное объяснение операции. ИМО это должен быть принятый ответ!
ISAE
2

Допустим, вы хотите отменить изменения до n коммитов,

Где фиксируются хэши следующим образом:

  • h1
  • х2 ...
  • кп
  • Hn + 1

Затем выполните следующую команду:
git reset hn

Теперь ГОЛОВА будет в hn + 1. Изменения с h1 на hn будут неизменными.

Васанта Ганеш К
источник