Что происходит, когда вы создаете ветку git, а затем удаляете предыдущий коммит? - PullRequest
2 голосов
/ 09 ноября 2011

Я создал новый файл (с небольшим количеством кода и тяжелой работой) и передал его в основную ветку моего репозитория git. Через мгновение я понял, что, вероятно, мне следовало создать ветку для файла. Я думал, что смогу отозвать коммит из master и повторить коммит на ветке, но думаю, что сделал все в глупом порядке. По какой-то причине я сначала создал ветку, а затем пошел, чтобы отозвать коммит, используя Можно ли отозвать коммиты? в качестве руководства.

Вот по сути то, что я сделал:

echo "Lots of code and hard work" > newfile.txt
git commit -m "thoughtless commit" newfile.txt
# Oh wait, I should've branched!
git branch thoughtful
git checkout thoughtful
# Hmm, I didn't mean for that last commit to be in master
git checkout master
# get the previous commit's hash
oldhead=$(git log | awk 'BEGIN{commitcount=0; } /^commit/{ if (commitcount++ == 1) { print $2 }; }')
git reset --hard "$oldhead"
git checkout thoughtful

Так что теперь я, очевидно, уничтожил коммит на master (действительно, 'newfile.txt' больше не существует на master ), но он все еще существует в заботливый (и я думаю, reflog).

Может быть, кто-то так любезно объяснит, что я здесь сделал, и почему не требуется коммит на вдумчивый ?

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Когда вы создали свою ветку thoughtful, она началась с текущего состояния master, которое уже содержало коммит. С этого момента две ветви не связаны. Что бы вы ни делали с master, это не повлияет на thoughtful. Фиксация, которая представляет файл, все равно будет частью thoughtful.

Вы должны попробовать git log thoughtful и git log master, чтобы просмотреть историю коммитов. На thoughtful вы все равно увидите коммит, который вы пытались удалить с мастера.

Более полная разбивка следует

Предполагая, что мы в настоящее время на master ...

echo "Lots of code and hard work" > newfile.txt
git commit -m "thoughtless commit" newfile.txt

Вы создали коммит на master, содержащий newfile.txt.

# Oh wait, I should've branched!
git branch thoughtful

Вы создали ветку thoughtful, которая находится в текущем состоянии master, но в остальном полностью не связана с мастером . Начальная точка ветви - master, поскольку вы не указали явно начальную точку, и master в настоящее время извлечено.

git checkout thoughtful

Теперь вы на thoughtful; вам не нужно checkout новых веток, чтобы сделать их реальными, этот шаг абсолютно не действует, так как вы делаете следующее:

# Hmm, I didn't mean for that last commit to be in master
git checkout master

Теперь вы на master.

# get the previous commit's hash
oldhead=$(git log | awk 'BEGIN{commitcount=0; } /^commit/{ if (commitcount++ == 1) { print $2 }; }')

Вы перепрыгнули через тонну обручей, чтобы получить предыдущий коммит, когда вы могли просто использовать master~ или HEAD~. То, что - это то, как вы получаете «предыдущий» коммит, а не проверяя git log. В будущем, чтобы отменить последний коммит, используйте git reset --hard HEAD~.

git reset --hard "$oldhead"

Вы изменили коммит master баллов. Теперь это тот коммит, который обнаружена вышеупомянутой командой, предположительно, коммит до newfile.txt. Использование --hard заставляет Git также обновлять рабочий каталог, поэтому newfile.txt исчезает; если бы вы пропустили --hard, newfile.txt все равно был бы в каталоге, но был бы указан как новый файл в git status.

git checkout thoughtful

Вы вернулись к thoughtful, который содержит newfile.txt, обновив ваш рабочий каталог и снова введя newfile.txt.

1 голос
/ 09 ноября 2011

Основой для понимания этого является то, что вы должны визуализировать ветви как указатели на коммит, который является ГОЛОВОМ ветви. И каждый коммит указывает на одного или нескольких его родителей. Ветвь (мастер и т. Д.) Является указателем. Не больше, не меньше.

Когда вы создали thoughtful, вы создали еще один указатель на тот же коммит, что и мастер. Затем вы переместили главный указатель на предыдущий коммит. Вы не удаляете коммит или что-то в этом роде, вы перемещаете главный указатель на предыдущий коммит. И ваша thoughtful ветка / указатель все еще указывает на коммит, который вы хотите. Вы находитесь в том состоянии, в котором хотели быть!

PS: Чтобы получить старую HEAD, используйте git reflog или имена ref, например HEAD@{1}. Кроме того, в этом случае HEAD~ даст вам правильный вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...