Прежде всего, пожалуйста, перестаньте обвинять Git. Неважно, что вы думаете, вы сделали что-то, чтобы этот коммит больше не был доступен из HEAD, и предположить, что это было что-то неподконтрольное вам, может только помешать вам понять, что это такое, как это исправить, и как этого избежать.
Это может быть любое количество вещей: сброс до предыдущего коммита (git reset
), проверка предыдущего коммита или ветвления при предыдущем коммите (git checkout
), выполнение ребазинга и удаление коммита ( git rebase -i
), исправляя коммит чем-то другим (git commit --amend
) ...
Обратите внимание, что, поскольку ваш вопрос настолько расплывчатый, существует множество возможностей, и я попытался охватить все вероятные, о которых я думал, но я не обязательно буду думать обо всем. Пожалуйста, не следуйте слепо инструкциям, если вы их не понимаете или не убедились, что это правильно. (Ваш вопрос, например, фактически не демонстрирует, что у вас есть коммиты впереди HEAD; они могут быть отклонены от него.)
Есть две вещи, которые вы можете захотеть сделать: посмотреть, как текущая позиция HEAD соотносится с тем, где, по вашему мнению, она должна быть, и посмотреть, как вы ее переместили.
Чтобы увидеть текущее состояние истории, есть несколько полезных вещей:
- Посмотрите, находитесь ли вы в ветке, как вам кажется, запустив
git branch
или даже git status
. Если вы просто проверили неправильную ветку, вы можете сделать это сейчас - просто проверьте правильную вещь. Если вы отсоединили свою HEAD (т. Е. Ветвь не проверена), вы захотите проверить правильную ветку, а затем, если вы сделали коммиты, пока HEAD был отсоединен, объедините эти коммиты.
- Просмотр истории, предпочтительно с использованием
gitk --branches e48c156
, которая гарантирует, что он показывает все ветви и коммит, который вам небезразличен. Вы также можете использовать git log [--decorate] [--graph] ...
, если вам удобнее, но gitk
лучше умеет визуально отображать большое количество сложной истории.
Вы должны быть в состоянии увидеть, как ваша текущая ветвь / коммит связана с тем местом, где, по вашему мнению, вы должны быть.
Чтобы увидеть, что вы сделали, чтобы испортить себя, самым полезным инструментом будет git reflog
. Здесь перечислены предыдущие позиции HEAD
. В обратном хронологическом порядке будут перечислены все предыдущие позиции HEAD вместе со сводкой операций, которые вызвали каждое перемещение. Возможно, в сочетании с gitk
, чтобы увидеть, где находятся коммиты, вы сможете отслеживать, что вы сделали. (Вы также можете использовать его на ветке с git reflog show <branch>
.) Если вы хотите получить реальный коммит на один мимо e48c156, это будет способ обнаружить его.
Когда вы найдете то, что ожидаете от себя, вы можете вернуться к этому. В большинстве случаев это так просто, как git merge <desired-commit>
. Если вы не сделали коммитов с тех пор, как вернулись, это будет слияние с ускоренной перемоткой вперед, которое просто продвинет вас вперед, а если это произойдет, это будет нетривиальное слияние, которое должно дать вам то, что вы хотите. Если у вас есть локальные модификации, вам может понадобиться сначала их спрятать. Однако, если проблема заключается в том, что вы сделали ребаз или, возможно, изменили коммит и удалили тот, который хотите, вам нужно быть более осторожным - скорее всего, создайте ветку, в которой все было до ошибки, и объедините / rebase / вишня в изменениях, которые были сделаны после этого.
В крайнем случае, есть также git fsck
, который напечатает список всех объектов, которые недоступны из ваших текущих ссылок. Вы будете хотеть искать висячие коммиты; затем вы можете использовать любые инструменты, которые вам наиболее удобны, чтобы определить, являются ли они тем, что вас волнует. Но это не должно быть необходимым; наихудший случай, что вещи находятся в reflogs.
Что касается того, как избежать этого снова, хорошо, выясните, что вы сделали неправильно, и не делайте этого снова. Если это что-то, связанное с проверкой неправильной вещи, вы можете подумать об изменении вашего приглашения, чтобы оно включало текущее имя ветки (и другие полезные вещи):
export PS1="...$(__git_ps1 "(%s)")..."