Случайно использовал «git switch -C» в существующей ветке — как восстановить?

Я пытался переключиться на ветку, над которой работаю, и случайно включил аргумент '-C' для команды git switch, которая говорит ей создать новую ветку.

По сути, я сделал git switch -C foo, где foo — это уже существующая ветвь, и теперь ветвь foo относится к чему-то совершенно отличному от того, что должно быть, а исходное foo теперь отсутствует в git log.

Нет соответствующей исходной ветки для извлечения из удаленного репо, все локально.

Можете ли вы показать настоящую команду, которую вы набрали по ошибке? Похоже, вы сделали git switch -C foo, где foo — это уже существующая ветвь, и теперь ветвь foo относится к чему-то совершенно отличному от того, что должно быть, а исходное foo теперь отсутствует в git log. Это правильно?

shadowtalker 14.02.2023 17:59

Да, это точно

boguslavsky 14.02.2023 18:00

Лучше всего добавить это уточнение в текст вашего вопроса. Комментарии не индексируются для поиска, и пользователям рекомендуется рассматривать их как возможно эфемерные.

shadowtalker 14.02.2023 18:33
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
Аутсорсинг разработки PHP для индивидуальных веб-решений
Аутсорсинг разработки PHP для индивидуальных веб-решений
Услуги PHP-разработки могут быть экономически эффективным решением для компаний, которые ищут высококачественные услуги веб-разработки по доступным...
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
HTML предоставляет множество тегов для структурирования и организации содержимого веб-страницы. Одним из наиболее часто используемых тегов для...
2
3
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете получить историю имени вашей ветки, используя:

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 для перемещения по репозиторию в режиме «отсоединенной головы».

Другие вопросы по теме