2

У меня есть последовательность коммитов

A---B---C---D (HEAD) (master)

Далее я перехожу в коммит A

A (HEAD) ---B---C---D (master)

Вношу некоторые изменения и делаю новую ветку, путём создания нового коммита:

A---B---C---D (master)
|----------------------------- E (HEAD)

После этого перехожу в D:

A---B---C---D (HEAD) (master)
|----------------------------- E

Но отобразить E никакими мыслимыми способами не получается. Пробовал

git branch 
git log --graph
git log --branches

Добавлено

Пример действий

$ git checkout <A>
$ touch 1.txt
$ git commit -am "new not a name branch"
$ git checkout master

Далее смотрю список комитов. Коммита <E> нет.

hedgehogues
  • 9,569

1 Answers1

5

Это нештатная ситуация

У вас это была не "ветка без названия", а "отделённая голова" (и это не едкая шутка, а буквальный перевод термина "detached HEAD").

E считается "коммитом-потеряшкой" (dangling commit), поскольку не связан ни с какой веткой или меткой и будет через какое-то время (gc.reflogExpireUnreachable, по умолчанию через 30 дней) стёрт сборщиком мусора (git gc) окончательно.

Поэтому никакие обычные средства работы вам его не покажут, да. На уровне пользователя можно считать, что этого коммита больше нет.
Придётся использовать аварийные низкоуровневые средства. Например, git reflog.

А чтобы он перестал быть "потеряшкой", необходимо зафиксировать его, сделав на нём (или впереди него, если у вас есть коммиты на нём основанные) ветку или метку.

Например, найдя в git reflog ваш потерянный коммит, можно разместить на нём ветку:

git checkout HEAD@{число} # или сразу хэш, как вам проще
git checkout -b название-ветки
  • Как сделать впереди него ветку (зафиксировать его)? – hedgehogues Jan 30 '18 at 12:42
  • Пробовал вызывать git gc --force, когда находился в мастере при уже созданном <E>, но после этого всё равно удалось перейти в <E> – hedgehogues Jan 30 '18 at 12:43
  • 1
    @hedgehogues потому что рефлог на него ссылкется, рефлоги gc не чистит – Pavel Mayorov Jan 30 '18 at 12:43
  • @PavelMayorov а смысл тогда в git gc? – hedgehogues Jan 30 '18 at 12:44
  • 1
    @hedgehogues рефлог не бесконечен. –  Jan 30 '18 at 12:45
  • @PavelMayorov, т.е в случае если reflog больше не содержит <E>, то git gc удалит dangling commit? – hedgehogues Jan 30 '18 at 12:46
  • 1
    @D-side зачем две команды checkout когда это делается одной? – Pavel Mayorov Jan 30 '18 at 12:47
  • @PavelMayorov в гите очень многое делается многими способами, в том числе "одной командой". Я в ежедневном обиходе использую довольно небольшое подмножество команд, просто чтобы не держать до фига в голове :) –  Jan 30 '18 at 12:49
  • 1
    @hedgehoguesgc удаляет только устаревшие коммиты https://ru.stackoverflow.com/questions/537951/%d0%9a%d0%b0%d0%ba-%d1%80%d0%b5%d0%b0%d0%bb%d1%8c%d0%bd%d0%be-%d1%83%d0%b4%d0%b0%d0%bb%d0%b8%d1%82%d1%8c-%d0%b2-git-%d1%84%d0%be%d1%80%d0%bc%d0%b0%d0%bb%d1%8c%d0%bd%d0%be-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d0%b5?answertab=votes#tab-top – Fat-Zer Jan 30 '18 at 12:49
  • @D-side но ведь вы уже знаете эту команду! Что сложного в git checkout HEAD@{число} -b название-ветки? – Pavel Mayorov Jan 30 '18 at 12:50
  • @PavelMayorov то, что этой формой я почти никогда не пользуюсь и мне нужно открыть маны, чтобы составить команду. А вот "перейти на коммит Х" и "разместить на HEAD новую ветку" пользуюсь регулярно. –  Jan 30 '18 at 12:51
  • @D-side это одна и та же форма, просто разные наборы опциональных параметров... – Pavel Mayorov Jan 30 '18 at 12:52
  • @PavelMayorov я в голове рассматриваю их как разные формы, поскольку они делают существенно разные вещи (открыть vs. создать). Это мои собственные тараканы. –  Jan 30 '18 at 12:53
  • @D-side вы забыли что у настройки reflogExpireUnreachable другое значение по умолчанию, такие рефлоги устаревают быстрее – Pavel Mayorov Jan 30 '18 at 12:55
  • @PavelMayorov точно. Другая опция. Спасибо. –  Jan 30 '18 at 12:55