Случайно использовал «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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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 для перемещения по репозиторию в режиме «отсоединенной головы».

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