... Я хотел бы ... удалить последние 2 коммита.Это возможно?
Вы не можете удалить коммиты, но вы можете легко сказать Git забыть их.
Theспособ, которым это работает, довольно прост, в конце концов.Начнем с того, что каждый коммит сохраняет снимок, а также сохраняет хэш-идентификатор своего родительского коммита (вместе с вашим сообщением в журнале коммитов и вашим именем автора и т. Д.).Это формирует обращенную назад цепочку коммитов.
Если мы позволим одиночным заглавным буквам заменять хэш-идентификаторы коммитов, мы можем нарисовать эту цепочку:
... <-F <-G <-H <--master
Обратите внимание, что имя ветви , master
в этом случае хранит хэш-идентификатор последнего коммита в цепочке.(Когда что-то хранит хеш-идентификатор коммита, мы говорим, что эта вещь указывает на коммит, отсюда и стрелки. Имя master
указывает на H
, H
указывает на G
и т. д.)
Способ, которым Git находит эти коммиты, заключается в считывании хеш-идентификатора H
из master
, который находит коммит H
, затем чтении коммита H
и его показе,Затем, прочитав H
, Git имеет хеш-идентификатор commit G
, поэтому Git может прочитать G
и показать его и т. Д.
Когда мы делаем новый коммит, Git фактически делаетэто:
- запись снимка;
- запись автора и сообщения журнала и т. д .;
- с новой точкойвернуться к текущему коммиту;
- и последнему, но наиболее важному, записать хэш-идентификатор нового коммита в имя ветви.
Так что если у нас было:
...--F--G--H
и мы добавили --I
:
...--F--G--H--I
, то Git изменил имя master
для храненияидентификатор хеша коммита I
.В конечном итоге мы имеем:
...--F--G--H--I--J <-- master
Если мы сделали несколько нежелательных коммитов, мы можем сказать Git: Переустановить имя master
, чтобы оно указывало на фиксацию H
вместо фиксации J
. Есть несколько способов сделать это, но первый, к которому нужно обратиться, в этом случае - git reset --hard
(хотя у нас проверено master
, и убедитесь, что у вас нет ничего интересногопроигрыш, потому что git reset --hard
говорит Git выбросить все из):
git checkout master
git reset --hard HEAD~2
Суффикс ~2
говорит Git, чтобы он отсчитывал два шага - технически, два первого родителя шагов, которые имеют значение, когда у нас есть несколько коммитов слияния в нашей цепочке, но здесь мы этого не делаем, это не имеет значения.Если master
в настоящее время указывает на J
, то Git будет считать дважды: J
до I
, затем I
до H
.Затем Git заменяет нашу работу содержимым из commit H
и делает имя, master
, указывающее на H
вместо J
:
I--J
/
...--F--G--H <-- master
Теперь, когдаJ
трудно найти , он кажется подлежащим удалению.
Недостатком этого является то, что если у нас есть наш Git, скажем другому Git: Здесь, возьмите копии коммитов I
и J
, , которые другие Git имеют в двух коммитах и повторно представят их нашему Git даже после того, как наш Git забыл их,Но если мы никогда не отправляли два коммита где-либо еще, мы единственные, у кого есть их, поэтому, если мы забудем их, они так же хороши, как пропали.
(Если у нас есть толкнул их, мы можем получить наш Git и их Git, и каждый второй Git , который подобрал их с тех порзатем все забудут их, а затем они исчезнут. Но, очевидно, это быстро становится трудным.)