git fsck, объединяющий --lost-found и --unreachable
Я нашел много интересных сообщений о
git fsck
, поэтому я хотел немного поэкспериментировать с ними. Прежде всего источники, которые я прочитал перед этим вопросом:
Как найти недостижимый хэш коммита в репозитории GIT по ключевым словам?
gitfsck: чем отличаются --dangling, --unreachable и --lost-found?
Я начал с этого репо:
* 9c7d1ea (HEAD -> test) f
* cd28884 e
| * 7b7bac0 (master) d
| * cab074f c
|/
* d35af2c b
| * f907f39 r # unreferenced commit
|/
* 81d6675 a
Где был создан из отдельного
HEAD
из
a
. Затем я хотел перебазировать
master
на
test
, но у меня были некоторые неустановленные изменения, поэтому я сделал:
git rebase --autostash test
Получение (не показываю, но все равно есть):
* caee68c (HEAD -> master) d
* 2e1cb7d c
* 9c7d1ea (test) f
* cd28884 e
* d35af2c b
* 81d6675 a
Далее я запускаю:
$ git fsck
#...
dangling commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
#...
$ git fsck --unreachable
#...
unreachable commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
unreachable commit d8bb677ce0f6602f4ccad46123ee50f2bf6b5819 # stash index
#...
$ git fsck --lost-found
#...
dangling commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
dangling commit f907f39d41763accf6d64f4c736642c0120d5ae2 # r
#...
Первый вопрос
Почему только версия возвращает
r
совершить? А почему не те
c
а также
d
перед
rebase
показан среди недосягаемых? Я думал, что понял разницу, читая связанные вопросы, но я явно что-то упускаю. У меня все еще есть полный рефлог, но я думаю, он вам не нужен, так как все коммиты (кроме связанных с
stash
) ссылаются.
Я знаю, что должен создать еще один пост, но второй вопрос частично связан. Я попробовал из любопытства:
$ git fsck --lost-found --unreachable
#...
unreachable commit 6387b70fe14f1ecb90e650faba5270128694613d # stash
unreachable commit d8bb677ce0f6602f4ccad46123ee50f2bf6b5819 # stash index
unreachable commit f907f39d41763accf6d64f4c736642c0120d5ae2 # r
unreachable commit 7b7bac0608936a0bcc29267f68091de3466de1cf # c before rebase
unreachable commit cab074f2c9d63919c3fa59a2dd63ec874b0f0891 # d before rebase
#...
Второй вопрос
Комбинируя оба варианта, я получаю все недостижимые коммиты (а не только объединение
--lost-found
а также
--unreachable
), это очень неожиданно. Почему оно так себя ведет?
1 ответ
Кое-что из этого действительно вызывает недоумение и, по-видимому, не задокументировано должным образом, но беглый взгляд на встроенный/fsck.c показывает, что использование:
- включается ;
- включается .
Пункт 1 не особенно интересен, так как
--full
в любом случае теперь включено по умолчанию, но в документации действительно должно быть указано, что отключает
--no-full
. Пункт 2 объясняет большую часть остального; У меня есть предположение о последней части [ Редактировать : остальное].
Обратите внимание, что когда вы запускали:
git checkout master && git rebase --autostash test
это заставило Git запуститься, что создало новый тайник, состоящий из двух новых коммитов. Затем Git, как обычно, выполнил перебазирование, которое скопировало
cab074f
а также
7b7bac0
коммиты, видимые в оригинале
git log --all --decorate --oneline --graph
вывод, к новому
2e1cb7d
а также
caee68c
коммиты видны во втором выводе.
Почему только версия возвращает коммит? И почему среди недостижимых не отображаются и до ребазы?
Предположительно, этот коммит все еще находится в reflog. Это делает его доступным по ссылке, но, поскольку подразумевает , на этот раз он становится недостижимым. То же самое касается оригиналов
c
и: они доступны через несколько записей reflog, как из
HEAD
reflog и
master
с.
Комбинируя оба варианта, я получаю все недостижимые коммиты (а не только объединение и ), это очень неожиданно. Почему оно так себя ведет?
Это более загадочно. [ Изменить : решено; см. ниже.] Давайте запустим их в порядке ваших команд:
fsck 1 и fsck 2: оба обнаруживают коммиты autostash. Это потому что
git stash push
скопировал оригинал в stash reflog, чтобы он мог указывать на коммит autostash (рабочее дерево). Тогда подразумеваемыйgit stash apply && git stash drop
(git stash pop
) применил тайник и бросил его, переместивstash@{1}
вход обратно и удаление stash reflog. Так что коммит из автосташа действительно "болтается". Это не вrefs/stash
и дело даже не вstash
рефлог, потому чтоgit stash
(ab) использует этот журнал ссылок как «стек тайника». Однако он указывает на фиксацию из автозакладки.Тогда первая fsck печатает
6387b70fe14f1ecb90e650faba5270128694613d
и называет это «висячим». Это коммит, который был удален. Секундаfsck
, с , добавляетd8bb677ce0f6602f4ccad46123ee50f2bf6b5819
: соответствующая фиксация, которая была удалена.fsck 3: коммиты и перебазированные оставались невидимыми под
git fsck --unreachable
потому что на них есть ссылки из reflogs. Но теперь, с , fsck не смотрит на reflogs. Мы должны ожидать, что фиксация autostash, фиксация и pre-rebase будут висящими. [ Изменить : согласно комментарию , это неправильно: ссылки наi
и , так что это скроется.]Мы действительно видим и
r
совершает, но нефиксирует .Почему бы и нет? Это мое предположение , но его легко проверить, если у вас все еще есть настройки: когда вы используетеgit rebase
успешно, Git создает или обновляет псевдоссылку с именем, чтобы запомнить хэш-идентификатор фиксации подсказки до завершения перебазирования. Обратите внимание, что это же имя используется для запоминания предыдущего значения ссылки после успешного выполнения.git reset
которая перемещает один, и после любой другой операции, которая может переместить имя ветки на некоторое расстояние (например, ускоренное слияние).Совершенно очевидно, чтоgit fsck
необходимо учитывать все различные*_HEAD
псевдоссылки как отправные точки для достижимости. Это тоже не задокументировано (и даже не совсем ясно, было ли это преднамеренным здесь — в последнее время код ссылок подвергался довольно серьезной переработке для поддержки альтернативных бэкэндов ссылок).fsck 4, как раз перед вашим разделом ВТОРОЙ ВОПРОС:
либо отключили включение псевдоссылки, либо — я думаю, что это более вероятно — вы сделали что-то промежуточное, что коснулось[ править ] С тех порORIG_HEAD
так что он больше не выбирал исходный коммит до перебазирования.--unreachable
перечисляет все недостижимые коммиты, тот факт, чтоd
доступен косвенно из автотайникаw
commit не имеет значения, и мы все видим.
Если вы хотите сообщить об ошибке документации Git, в документации fsck не указано, что
--lost-found
подразумевает
--no-reflogs
, вы должны сделать это.