В Git ветви - это всего лишь указатели (ссылки) на фиксации в направленном ациклическом графе (DAG) коммитов. Это означает, что удаление ветки удаляет только ссылки на коммиты, что может сделать некоторые коммиты в DAG недоступными, поэтому невидимыми. Но все фиксации, которые были на удаленной ветке, все равно будут находиться в репозитории, по крайней мере до тех пор, пока недоступные коммиты не будут обрезаны (например, с использованием git gc
).
Обратите внимание, что git branch -d
откажется удалить ветку, если не может быть уверен, что ее удаление не оставит недостижимых коммитов. Вам нужно использовать более сильный git branch -D
, чтобы принудительно удалить ветвь, если она может оставить недостижимые коммиты.
Обратите внимание, что недостижимые коммиты, если они присутствуют, являются только теми, которые совершаются между последним концом удаленной ветви и либо фиксацией, которая была присоединена к другой существующей ветке, либо помеченной фиксацией, либо точкой ветвления; в зависимости от того, что наступит позже. Например, в следующей ситуации:
----O----*----*----/M----* <-- master <-- HEAD
\ /
\--.----.--/--x---y <-- deleted branch
только совершает «х» и «у» станет недостижимым после удаления ветви.
Если вы оперировали удаленный филиал в gc.reflogExpire
период, по умолчанию 90 дней, вы бы последний кончик проколотой ветви, записанной в ГОЛОВАХ reflog (см git reflog show HEAD
или git log --oneline --walk-reflogs HEAD
). Вы должны использовать HEAD reflog для восстановления удалённого указателя. Заметим также, что в этом случае недостижимая запись только в удаленной ветке будет защищена от обрезки (удаления) в течение периода gc.reflogExpireUnreachable
, который по умолчанию составляет 30 дней.
Если вы не можете найти кончик просто удаленного филиала в reflog для головы, вы можете попробовать использовать git fsck
найти «недостижим совершить <sha1>», и рассматривать (через git show <sha1>
или git log <sha1>
), чтобы найти кончик удаленной ветви.
Независимый от того, как вы нашли кончик удаленного филиала, вы можете отменить удаление, или, скорее, повторно создать только удаленный филиал с помощью
git branch <deleted-branch> <found-sha1-id>
Заметим, однако, что reflog для филиала будет потеряна.
Существует также git-resurrect.sh скрипта contrib/
, который помогает найти следы кончика ветви с заданным именем и воскрешение (восстановить) его.
Спасибо за ответ. Не могли бы вы пояснить, что вы подразумеваете под «каждый коммит имеет полное исходное дерево»? Насколько я понимаю, каждая фиксация в git - это набор дельт, который ссылается на родительское, а не целое дерево. –
Нет, каждая фиксация является состоянием дерева в данной точке. Дельты вычисляются позже для отображения и перезагрузки и еще много чего, но идентификатор commit - это хэш всего дерева. – ben
@Ken Liu: фиксация содержит указатели на ноль или более родительских коммитов, объект дерева и некоторые метаданные о фиксации. Таким образом, фиксация однозначно идентифицирует как исходное дерево, так и, если смотреть против его родителя (ов), изменения, которые он ввел. –