MyTetra Share
Делитесь знаниями!
Free dating app
Качественное ТО Genesis - диагностика и замена фильтров.
Git: как переключиться на нужный коммит? Понимание, что такое ветка
Время создания: 22.06.2014 15:41
Автор: Xintrea
Текстовые метки: git, commit, коммит, checkout, переключиться, перейти, вернуться, head, ошибка, ветка, понимание, объяснение
Раздел: Компьютер - Программирование - Системы контроля версий (VCS) - Git
Запись: xintrea/mytetra_syncro/master/base/1403437294hkfzh1wflf/text.html на raw.github.com

Как переключиться на нужный коммит?


Для переключения на нужный коммит используется действие checkout. После переключения, все файлы в проекте станут такими, какими они были в данном коммите.



git checkout commit



Где commit - это хеш (обозначение, имя) коммита, причем можно указывать не весь хеш, а несколько начальных символов хеша.



Примечание: переключение на интересующий пользователя коммит всегда будет приводить репозитарий в состояние detached HEAD. Это нормально, не стоит этого бояться.


Нахождение в состоянии "detached HEAD" можно проверить командой git status:



$ git checkout 3c53ec44

...

$ git status

HEAD отделён на 3c53ec44



Состояние "detached HEAD" означает, что текущий рабочий указатель не находится ни на какой ветке. Но как же так? Ведь коммит всегда принадлежит какой-то ветке! Это можно увидеть в том же gitk... А разгадка в том, что коммиты в Git - это, конечно, "снимки состояния репозитария, которые связаны между собой, образуя цепочки". Но нужно понимать, что цепочки коммитов в Git не считаются ветками! Вот это поворот!



Как работают ветки в Git?


Веткой в Git называется указатель на коммит, и этому указателю задано определенное имя. Если такой указатель указывает на последний коммит в цепочке, то в момент добавления нового коммита (у которого текущий является родителем) этот именованный указатель автоматически "переместится": то есть он начнет указывать на новый коммит. А имя указателя останется, естественно, без изменений. Таким образом, создается иллюзия, что программист работает в именованной ветке, и при добавлении коммитов ветка прирастает новыми коммитами. Хотя, на деле, система Git оперирует не ветками, а именно указателями на коммиты, не более того.


Нужно запомнить: никаких веток, в естественном человеческом понимании, в Git нет.



Вышеуказанные размышления можно продемонстрировать и по-другому. Нахождение в состоянии "detached HEAD" можно проверить командой git branch:



$ git branch

* (HEAD отделён на 3c53ec44)

control_panel

master

new_engine



Здесь видно, что пользователь переключился на какой-то коммит. Но не видно на какой ветке находится пользователь, и, тем более, не видно на какой ветке он находился ранее. (Перед переключением, в gitk, было видно, что коммит 3c53ec44 находится в ветке control_panel, но не является в ней последним). А так как коммит не самый последний в ветке, то после переключения рабочий указатель не начинает указывать ни на какую ветку (то есть рабочий указатель не совпадает с каким-либо именованным указателем, находящимся на конце какой-либо ветки). А такое состояние, на первый взгляд, и считается "detached HEAD".


Но тогда возникает вопрос: а что произойдет, если с помощью хеша коммита переключиться на коммит, который является последним в какой-нибудь цепочке, и в gitk видно, что на данном коммите завершается ветка control_panel? Поймет ли Git, что произошло переключение на коммит, на который указывает именованный указатель с именем control_panel? То есть, поймет ли Git, что происходит переключение на ветку control_panel?


Следующие команды показывают, что произошло переключение на коммит, на который так же указывает указатель ветки control_panel. И видно, что хеш коммита (на который переключились) 4c171d82 и хеш ветки 4c171d82 - совпадают. Но состояние "detached HEAD" все равно возникло:



$ git checkout 4c171d82


$ git branch -v

* (HEAD отделён на 4c171d82) 4c171d82 Manager и регулятор громкости

control_panel 4c171d82 Manager и регулятор громкости

master c4bfddfd ALS перенесен в разел коммутаторов

new_engine b9bcf376 Merge branch 'new_engine' of ...



То есть, даже если пользователь переключился на конечный коммит какой-либо ветки, состояние считается все равно как "detached HEAD". Надо разобраться почему так происходит.


А дело вот в чем. В Git есть два указателя:



  • Указатель рабочей области проекта - так называемый working tree, или WT-указатель.
  • Указатель рабочей ветки - так называемый HEAD-указатель



Так вот, надо знать что:



  • Команда git checkout ХЕШ_КОММИТА - перемещает WT-указатель, но HEAD-указатель не трогает.
  • Команда git checkout ИМЯ_ВЕТКИ - перемещает WT-указатель и HEAD-указатель.



Если WT-указатель и HEAD-указатель не совпадают, такое состояние и называется "detached HEAD". А когда они совпадают - значит можно нормально работать. Причем работа будет проиcходить в ветке, имя которой соответствует именованному указателю на коммит, на который так же указывает HEAD.



Важно для понимания: возможно ли в Git ветвление без веток?


Да, если над проектом работает несколько человек, или если один человек работает над проектом из разных локаций (на работе, дома, в дороге), или при различных комбинациях такой организации работы. Во всех этих случаях, даже в пределах одной ветки, могут образовываться различные ветвления.


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



Дописать...



А как вернуться обратно после просмотра коммита?


Ответ. Команда:



git checkout -


(да, в конце команды ставится символ тире "-")



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


Примечание: по-сути, данная команда просмативает историю перемещений пользователя по коммитам.


Дописать. Показать команды просмотра истории перемещений.



А как перейти в самое свежее состояние?


Дописать. Свежее состояние - внутри ветки?


Так же в этом разделе:
 
MyTetra Share v.0.65
Яндекс индекс цитирования