2010-04-10 5 views
130

Исходя из svn, только начинающий знакомиться с git.Удаляет ли ветку в git ее из истории?

Когда ветка удалена в git, удалена ли она из истории?

В svn вы можете легко восстановить ветвь, вернув операцию удаления (обратное слияние). Как и все удаления в svn, ветвь никогда не удаляется, она просто удаляется из текущего дерева.

Если ветка фактически удалена из истории в git, что происходит с изменениями, которые были объединены с этой веткой? Сохраняются ли они?

ответ

176

Ветки - это всего лишь указатели на фиксации в git. В git каждый коммит имеет полное исходное дерево, это совсем другая структура из svn, где все ветви и теги (по соглашению) живут в отдельных «папках» репозитория вместе со специальной «стволом».

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

Если ветка удалена без объединения в другую ветку, то фиксации в этой ветке (вплоть до точки, в которой разветвлено от фиксации, которая еще доступна) перестанут быть видимыми.

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

+2

Спасибо за ответ. Не могли бы вы пояснить, что вы подразумеваете под «каждый коммит имеет полное исходное дерево»? Насколько я понимаю, каждая фиксация в git - это набор дельт, который ссылается на родительское, а не целое дерево. –

+0

Нет, каждая фиксация является состоянием дерева в данной точке. Дельты вычисляются позже для отображения и перезагрузки и еще много чего, но идентификатор commit - это хэш всего дерева. – ben

+1

@Ken Liu: фиксация содержит указатели на ноль или более родительских коммитов, объект дерева и некоторые метаданные о фиксации. Таким образом, фиксация однозначно идентифицирует как исходное дерево, так и, если смотреть против его родителя (ов), изменения, которые он ввел. –

62

В 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/, который помогает найти следы кончика ветви с заданным именем и воскрешение (восстановить) его.

+0

Удивительный! 'git reflog show HEAD' перечислил фиксацию, и я создал новую ветку, как вы сказали, идеально. –

1

Если вы беспокоитесь о случайно удаленных филиалах и больше не имеете локальной копии своего репо, есть расширения для корпоративных серверов Git, таких как Gerrit, которые обнаружат перезаписи истории и удаления ветвей, будут поддерживать их под особым ref, чтобы они могли быть восстановлены, если это необходимо, и не будут обрезаны сборкой мусора. Администраторы Gerrit могут по-прежнему удалять выбранные коммиты, если это необходимо по юридическим причинам.

 Смежные вопросы

  • Нет связанных вопросов^_^