Как восстановить исходный коммит git?

358

Я впервые отправляюсь в репозиторий git; Затем я сожалею о коммите и хочу вернуть его. я попробую

# git reset --hard HEAD~1

Я получаю это сообщение:

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

Этот коммит является первым коммитом репозитория. Любая идея, как отменить первоначальный коммит git?

Чау Чи Ян
источник

Ответы:

566

Вам просто нужно удалить ветку, на которой вы находитесь. Вы не можете использовать, git branch -Dпоскольку это имеет проверку безопасности против этого. Вы можете использовать update-refдля этого.

git update-ref -d HEAD

Вы не использовать rm -rf .gitили что - нибудь подобное , так как это будет полностью уничтожить весь репозиторий , включая все другие отрасли, а также отрасли , которую вы пытаетесь сбросить.

CB Bailey
источник
1
Попробовал это в то время как в ребазе - хотел разделить самый первый коммит - потом сделал git status, и к моему удивлению, git сказал fatal: Not a git repository (or any parent up to mount point ...)!
Мэтт Фенвик
1
это не сработало для меня. Создайте файлы, в том числе некоторые, которые следует игнорировать, но нет .gitignore. git add ., git commit -m "initial commit", git update-ref -D HEAD, Создать .gitignore, уведомление , что мерзавец все еще видит файлы, добавленные ранее , что следует игнорировать. Другими словами git update-ref -d HEAD, не вернул меня в состояние до первоначального коммита.
Ган
2
Но в этом суть оригинального вопроса. Возвращение в состояние перед самым первым коммитом.
Ган
2
git reset --hard HEAD~1удалит добавленные файлы для всех других коммитов. Очевидно, вопрос заключается в том, как добраться до того же состояния, в котором эта команда работает во всех других случаях. Посмотрите эту суть, чтобы убедиться, что
gman
11
В случае, если кто-то запутается в комментариях gman: действительно git update-ref -d HEAD отменяет первоначальную фиксацию, но сохраняет все ранее зафиксированные изменения, добавленные в индекс. Если вы также хотите удалить эти изменения, просто выполните следующее git reset --hard. Даже если он неполный, этот ответ действительно лучший, поэтому избегайте его использования rm -fr .git(если только вы не знаете, что делаете).
rsenna
62

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

git update-ref -d HEAD

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

git push --force origin
frazras
источник
1
Стоит отметить ... это правильная команда, но она не удаляет HEAD ... она удаляет ссылку (расположенную в .git \ refs \head), которую извлек файл .git \ HEAD. После выполнения этой команды вы все равно можете найти файл HEAD, указывающий на файл refs /heads / <name>, который вы удалили, но если вы пойдете по этому пути, вы увидите, что заголовок ref больше не существует.
Данк
15

Этот вопрос был связан с этим сообщением в блоге, и было предложено альтернативное решение для более новых версий Git:

git branch -m master old_master
git checkout --orphan master
git branch -D old_master

Это решение предполагает, что:

  1. У вас есть только один коммит в вашей masterветке
  2. Там нет ответвления, old_masterпоэтому я могу использовать это имя

Он переименует существующую ветку old_masterи создаст новую, потерянную, ветку master (как будто она создана для новых репозиториев), после чего вы можете свободно удалять old_master... или нет. Вам решать.

Примечание. Перемещение или копирование ветки git сохраняет ее reflog (см. Этот код ), а удаление и последующее создание новой ветки приводит к его уничтожению. Поскольку вы хотите вернуться к исходному состоянию без истории, вы, вероятно, захотите удалить ветку, но другие могут захотеть рассмотреть эту небольшую заметку.

nonsensickle
источник
12

На условиях, оговоренных в вопросе:

  • Коммит - это первый коммит в репозитории.
  • Это означает, что было выполнено очень мало команд:
    • а git init,
    • предположительно некоторые git addоперации,
    • и git commit,
    • и это все!

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

rm -fr .git

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

ОПАСНОСТЬ! Это удаляет каталог Git-репозитория.

Он удаляет каталог репозитория Git навсегда и безвозвратно, если у вас нет резервных копий. Согласно предварительным условиям, вы ничего не хотите хранить в хранилище, поэтому вы ничего не теряете. Все добавленные вами файлы по-прежнему доступны в рабочих каталогах, при условии, что вы еще не изменили их и не удалили их и т. Д. Однако это безопасно, только если в вашем репозитории больше ничего нет. При обстоятельствах, описанных в вопросе «первый раз заархивируйте хранилище, а затем пожалейте об этом», это безопасно. Однако очень часто это небезопасно.

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

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

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

Джонатан Леффлер
источник
9
Это плохой совет. Что если в репо есть другие вещи, которые вы не хотите потерять?
Мэтт Фенвик
6
Тогда это был бы не первый коммит, правда. Там только один начальный коммит.
Джонатан Леффлер
9
«Тогда это не будет первоначальный коммит» - на самом деле, да. Вы пренебрегаете очень распространенным случаем нескольких ветвей. Смотри ответ Чарльза.
Мэтт Фенвик
2
Полезно, однако, должно прийти с предупреждением.
Саймон Бенгтссон
5
Это на самом деле работает. Принятый ответ не дает. Смотрите комментарий
gman
3

Ты не можешь Так:

rm -rf .git/
git init
git add -A
git commit -m 'Your new commit message'
ma11hew28
источник
1
Он пытался сказать git reset --hard, так зачем он git add -A?
Аристотель Пагальцис
3

Я добавлю, что работало для меня в конце. Мне нужно было удалить начальную фиксацию в репозитории, так как помещенные в карантин данные были помещены не в одну позицию, фиксация уже была отправлена.

Убедитесь, что вы находитесь на правильной ветке.

git checkout master

git update-ref -d HEAD

git commit -m "Initial commit

git push -u origin master

Это смогло решить проблему.

Важный

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

Эдвард
источник
1

Я удивляюсь, почему «изменение» не является предложением и было вычеркнуто @damkrat, так как изменение кажется мне просто верным способом наиболее эффективного решения основной проблемы исправления неправильного коммита, поскольку нет цели не иметь первоначального совершить. Как некоторые подчеркивали, вы должны модифицировать «публичную» ветку, как master, только если никто не клонировал ваш репо ...

git add <your different stuff>
git commit --amend --author="author name <author.name@email.com>"-m "new message"
Ричард
источник
- Автор требуется только в том случае, если кто-то исправит авторство коммита
Ричард
0

git reset --hard внести изменения, затем сделать

git add -A
git commit --amend --no-edit 

или

git add -A
git commit --amend -m "commit_message"

а потом

git push origin master --force

--force перепишет тот коммит, к которому вы перезагружены на первом шаге.

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

damkrat
источник
-1

Все, что вам нужно сделать, это отменить коммит.

git revert {commit_id}'

Тогда дави

git push origin -f
Абдалла Нофал
источник
Это невозможно сделать с первым коммитом.
Пользователь, который не является пользователем