Я пытался переключиться на ветку, над которой работаю, и случайно включил аргумент '-C'
для команды git switch
, которая говорит ей создать новую ветку.
По сути, я сделал git switch -C foo
, где foo
— это уже существующая ветвь, и теперь ветвь foo
относится к чему-то совершенно отличному от того, что должно быть, а исходное foo
теперь отсутствует в git log
.
Нет соответствующей исходной ветки для извлечения из удаленного репо, все локально.
Да, это точно
Лучше всего добавить это уточнение в текст вашего вопроса. Комментарии не индексируются для поиска, и пользователям рекомендуется рассматривать их как возможно эфемерные.
Вы можете получить историю имени вашей ветки, используя:
git reflog show <branch-name>
Это покажет вам идентификатор коммита, на который ранее указывала ветка. Вы можете вернуть его обратно, захватив этот идентификатор фиксации, а затем:
git branch -f <branch-name> <commit-ID-from-reflog>
# or if checked out:
git switch <branch-name>
git reset --hard <commit-ID-from-reflog>
Обратите внимание, что вы использовали git switch -C
, а вариант с заглавной C
эквивалентен:
git branch -f <new-branch>
git switch <new-branch>
Если бы вы использовали параметр -c
в нижнем регистре, эквивалентная команда branch
пропустила бы параметр -f
и, следовательно, выдала бы ошибку, а не перезаписала существующую ветку. Как правило, некоторые параметры команды Git могут принимать строчные или заглавные буквы, а заглавные буквы часто означают «принудительно», поэтому используйте их с осторожностью и, возможно, по умолчанию сначала используйте строчные буквы.
Примечание: параметр show
в команде git reflog
необязателен, поскольку используется по умолчанию. Тем не менее, мне нравится включать его, главным образом потому, что при использовании reflog
с именами веток завершение табуляции не будет работать без него. (По крайней мере, я обнаружил, что это верно с Git Bash.)
Допустим, у вас есть ветки dev
и main
.
Вспомните, что репозиторий Git — это «график» коммитов, а ветки — это «указатели» на конкретные коммиты в этом графе.
Ваша ошибка привела к удалению указателя ветки из ветки foo
и размещению его в другом месте графа коммитов. Коммиты все еще там, но у них больше нет ветки, указывающей на них. В конце концов, они будут «собраны мусором» и удалены, но, вероятно, они все еще там.
Ваш график фиксации может выглядеть так до ошибки:
$ git log --graph --oneline --decorate
* 7da3c3 (dev) add
| * cb44c2 (HEAD -> main) update
|/
* c62eda Add a
Тогда вы бежите git branch -C dev
.
После этой ошибки ваш график фиксации может выглядеть так:
$ git log --graph --oneline --decorate
* cb44c2 (HEAD -> dev, main) update
* c62eda Add a
Коммит 7da3c3
, кажется, исчез!
Не паникуйте. Коммит не удаляется, он просто больше не виден в выводе по умолчанию git log
, потому что на него ничего не указывает.
Если вы уже знаете, что «потерянная» ветка указывает на 7da3c3
, вы можете просто запустить git branch -f dev 7da3c3
(или git switch -C dev 7da3c3
), чтобы переместить указатель ветки dev
обратно в исходное положение. Но обычно мы не знаем хэши коммитов наугад, поэтому нам нужно выяснить, на какой хэш нам нужно переместить указатель ветки.
Мы можем просмотреть «потерянные» коммиты с помощью git log --reflog
, как показано на Получить список всех коммитов git, включая «потерянные»:
$ git log --reflog --graph --oneline --decorate
* 7da3c3 add
| * cb44c2 (HEAD -> dev, main) update
|/
* c62eda Add a
Здесь мы видим наш старый коммит 7da3c3
без указателя ветки. Затем все, что нам нужно сделать, это переместить указатель ветки обратно в нужное место, используя git branch -f dev 7da3c3
, как я сказал выше. Опция -f
/--force
необходима, потому что в противном случае git branch
откажется воссоздавать/перемещать ветку, которая уже существует, без «принудительного» включения.
Вы также можете использовать команду git reflog dev
, как показано в другом ответе, чтобы просмотреть историю конкретно ветки dev
, что может быть более полезным, но не дает такого приятного визуального обзора, как log --graph
.
Также обратите внимание, что ваш вывод reflog может выглядеть намного более загруженным, чем в моем простом примере, если вы выполнили другие перемещения веток, перебазирования и т. д. Обычно git reflog <branch>
должен показывать правильный коммит непосредственно вверху списка, но это не всегда будет может иметь место в операциях «восстановления», подобных этой. Возможно, вам придется некоторое время осмотреться, чтобы найти подходящую. Вы можете использовать git show
для просмотра коммитов по их хешу (например, git show 7da3c3
) или использовать git checkout
/git switch --detached
для перемещения по репозиторию в режиме «отсоединенной головы».
Можете ли вы показать настоящую команду, которую вы набрали по ошибке? Похоже, вы сделали
git switch -C foo
, гдеfoo
— это уже существующая ветвь, и теперь ветвьfoo
относится к чему-то совершенно отличному от того, что должно быть, а исходноеfoo
теперь отсутствует вgit log
. Это правильно?