Выбрасывать местные коммиты в Git

1470

Из-за некоторого плохого сбора вишни мой локальный репозиторий Git в настоящее время на пять коммитов опережает источник, и не в хорошем состоянии. Я хочу избавиться от всех этих коммитов и начать все заново.

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

Может быть, git revertэто то, что мне нужно, но я не хочу в конечном итоге 10 коммитов до начала (или даже шести), даже если он вернет сам код в правильное состояние. Я просто хочу притвориться, что последние полчаса не было.

Есть ли простая команда, которая сделает это? Это похоже на очевидный вариант использования, но я не нахожу никаких примеров.


Обратите внимание, что этот вопрос конкретно о коммитах , а не о:

  • неотслеживаемые файлы
  • неустановленные изменения
  • постановочные, но незафиксированные изменения
Дэвид Моулз
источник

Ответы:

2471

Если ваши лишние коммиты видны только вам, вы можете просто сделать git reset --hard origin/<branch_name> вернуться туда, где находится источник. Это сбросит состояние хранилища до предыдущего коммита и отменит все локальные изменения.

Выполнение git revertделает новые коммиты, чтобы удалить старые коммиты таким образом, чтобы сохранить историю каждого в здравом уме.

Бен Джексон
источник
91
git reset --hard <commit hash, branch, or tag>если вы хотите перейти к определенной ссылке, кроме удаленной ветви.
Сэм Соффс
55
Просто чтобы прояснить, если вы работаете не над masterдругой веткой, вам нужно запуститьgit reset --hard origin/<your-branch-name>
Золтан
33
Это не только отменит локальные коммиты, но и отбросит все в вашем рабочем дереве (т. Е. Ваши локальные файлы). Если все, что вы хотите сделать, это снять с себя, но оставить свою работу нетронутой, вы должны сделать «git reset HEAD ^» ... per stackoverflow.com/questions/2845731/…
aaronbauman
3
Вы можете сделать Fetch после этого. Это исправило счетчик количества ожидающих коммитов на SourceTree.
Стэн
2
git reset --hard origin/<branch_name>Это также сбросит конфигурацию проекта, поэтому позаботьтесь об этом. У меня есть большой .cfgфайл, который был сброшен по умолчанию. Я должен был потратить часы на это снова.
MAC
271

Просто удалите свою локальную главную ветку и создайте ее так:

git branch -D master
git checkout origin/master -b master
Рамон Заразуа Б.
источник
2
Это хорошо работает, когда откат ваших изменений будет стоить слишком много времени, что случилось со мной после пары перебазировок.
aross
1
Полезно для проблем подтягивания / подталкивания между членами команды!
Хорхе Орпинел
Это идеально, когда вы хотите восстановить ветку, а не просто мастер.
Владимир Ралев
1
это не хороший способ удалить один локальный коммит. Лучше использоватьgit reset --hard origin/<branch_name>
Кирит Вагела
1
Может быть, это решение сработает, но это не значит, что оно правильное.
Adly
202

Пытаться:

git reset --hard <the sha1 hash>

чтобы вернуть голову туда, где вы хотите быть. Используйте gitk, чтобы увидеть, на какой коммит вы хотите попасть. Вы можете сделать сброс в Gitk, а также.

Андерс Зоммарин
источник
5
Поднято это б / с, это полезная информация, но ответ Бена Джексона помечается галочкой для точного решения того, что я хотел - таким образом, чтобы мне не пришлось искать хеши коммитов. :)
Дэвид Моулз
2
Это один , когда ваша новая отрасль никогда не была нажата до начала еще
Jan
126

Удалить самый последний коммит:

git reset --hard HEAD~1

Удалите самый последний коммит, не разрушая работу, которую вы сделали:

git reset --soft HEAD~1

Джеймс Л.
источник
5
Полезный ответ. Спасибо! Я использовал git reset --soft origin / master
Тарун Кумар
2
@TarunKumar СПАСИБО! Я использую VS-интеграцию, и ваше решение было единственным способом, которым я смог стереть кучу коммитов слияний, которые я не хотел в ветке, у меня не было разрешения на регистрацию.
DVK
Спасибо, именно то, что я искал, «git reset --soft HEAD ~ 1» выполнил работу, которую я сделал непреднамеренно и хотел вернуть, но имел другие файлы, которые я не хотел уничтожать после возврата.
edvard_munch
47

Если вы используете приложение Atlassian SourceTree , вы можете использовать опцию сброса в контекстном меню.

введите описание изображения здесь

muruge
источник
42

На вашей ветке попытка:

git reset --hard origin/<branch_name>

Подтвердите обращение (к состоянию, без локальных фиксаций), используя " git log" или " git status" следовательно.

parasrish
источник
1
@Troyseph: все ответы, перечисленные выше, я попытался, как есть, и не удалось исправить сценарий. Общий подход, который не был проиллюстрирован ни в одном из приведенных выше ответов, является тем, на что здесь пытались ответить.
parasrish
3
Принятый ответ такой же, как и у вас, за исключением общего названия ветви, и в комментариях @Zoltan прямо говоритсяJust to be clear, if you're not working on master but on another branch, you should run git reset --hard origin/<your-branch-name>
Troyseph
1
Это лучший ответ на мой взгляд.
Двонстон
21

git reset --hard @{u}* удаляет все ваши локальные изменения в текущей ветке, включая коммиты. Я удивлен, что никто еще не опубликовал это, учитывая, что вам не нужно будет искать, что делать, чтобы вернуться или играть с ветками.

* То есть сброс в текущую ветку в — @{upstream}обычно origin/<branchname>, но не всегда

Кевин Чен
источник
1
Некоторые оболочки, например рыба, будут интерпретировать «@», поэтому вам, возможно, придется заключать «@ {u}» в кавычки, например, «git reset --hard» @ {u} '. Во всяком случае, хорошая находка!
Trysis,
Удивительный ответ потрясающий
Марко
1
Как вы печатаете значение @ {u}?
Филипп Рего
12

Чтобы увидеть / получить идентификатор SHA-1 коммита, к которому вы хотите вернуться

gitk --all

Откат к этому коммиту

git reset --hard sha1_id

!Запись. Все коммиты, которые были сделаны после этого коммита, будут удалены (и все ваши изменения в проекте). Поэтому сначала лучше клонировать проект в другую ветку или скопировать в другой каталог.

Николас
источник
это отлично подходит для ситуаций, когда пульт больше не доступен, и нужно просто сбросить его до некоторой локальной фиксации. Гитк потрясающий - не знал об этом заранее.
theRiley
Если вы уже в gitk, вы можете просто щелкнуть правой кнопкой мыши на коммите и выбрать «сбросить ветку XY сюда».
mkrieger1
И новые коммиты не будут немедленно удалены. Там просто нет ветки, указывающей на них больше (помните, ветка - это не что иное, как «закладка» для определенного коммита).
mkrieger1
9

У меня была ситуация, когда я хотел удалить коммит, который не был передан, но коммит был раньше другого. Для этого я использовал следующую команду

git rebase -i HEAD~2 -> это отменит два последних коммита

И я использовал «drop» для подписи фиксации, которую я хотел удалить.

Роберт
источник
9

Удалить неотслеживаемые файлы (незафиксированные локальные изменения)

git clean -df

Безвозвратно удаляя все локальные коммиты и получая последние удаленные коммиты

git reset --hard origin/<branch_name>
ElasticCode
источник
8

Для локальных коммитов, которые не выдвигаются, вы также можете использовать git rebase -iдля удаления или сжатия коммита.

Нихил Катре
источник
1
Я знаю, что это может быть не самое короткое решение, но я проголосовал за вас, так как IMHO git rebase -i- более общий способ решения многих подобных проблем и может быть полезен в различных ситуациях.
Стефан Маринов
1
Используйте dropключевое слово (вместо удаления строки) при удалении всех коммитов, чтобы избежать отмены ребаза.
Михал Чизмазия
6

Простым решением будет сопоставить локальную главную ветку HEAD с источником / главной веткой HEAD

git reset --hard origin/master

PS: origin / master - удаленный указатель на ветку master. Вы можете заменить мастер с любым именем филиала

narwanimonish
источник
4

Прежде чем ответить, давайте добавим некоторую предысторию, объясняющую, что это такое HEAD. так как некоторые из вариантов ниже приведут к отсоединению головы

First of all what is HEAD?

HEADэто просто ссылка на текущий коммит (последний) в текущей ветке.
Там может быть только один HEADв любой момент времени. (исключая git worktree)

Содержимое HEADхранится внутри .git/HEADи содержит 40 байтов SHA-1 текущего коммита.


detached HEAD

Если вы не используете последний коммит, то HEADесть он указывает на предыдущий коммит в истории detached HEAD.

введите описание изображения здесь

В командной строке это будет выглядеть так - SHA-1 вместо имени ветви, так как HEADне указывает на конец текущей ветви

введите описание изображения здесь

введите описание изображения здесь

Несколько вариантов того, как восстановить систему с отключенной HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Это извлечет новую ветку, указывающую на желаемый коммит.
Эта команда вернется к данному коммиту.
На этом этапе вы можете создать ветку и начать работать с этого момента.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Вы всегда можете использовать reflogтакже.
git reflogбудет отображаться любое изменение, которое обновило, HEADи проверка желаемой записи reflog установитHEAD вернет этот коммит.

Каждый раз, когда ГОЛОВКА изменяется, в reflog

git reflog
git checkout HEAD@{...}

Это вернет вас к желаемой фиксации

введите описание изображения здесь


git reset --hard <commit_id>

«Переместите» ГОЛОВУ назад к желаемому коммиту.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Примечание: ( начиная с Git 2.7 )
    вы также можете использовать git rebase --no-autostash.

git revert <sha-1>

"Отменить" данный диапазон фиксации или фиксации.
Команда сброса «отменит» любые изменения, сделанные в данном коммите.
Новый коммит с патчем отмены будет зафиксирован, в то время как оригинальный коммит останется в истории.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Эта схема иллюстрирует, какая команда что делает.
Как вы можете видеть там, reset && checkoutизмените HEAD.

введите описание изображения здесь

CodeWizard
источник
3

Для тех, кто заинтересован в решении Visual Studio, вот упражнение:

  1. В Team Explorerокне подключитесь к целевому репо.
  2. Затем Branchesщелкните правой кнопкой мыши интересующую ветку и выберите View history.
  3. Щелкните правой кнопкой мыши на коммите в Historyокне и выберите Reset -> Delete changes (--hard).

Это отбросит ваши локальные коммиты и сбросит состояние вашего репо до выбранного коммита. Т.е. ваши изменения после вытащенного репо будут потеряны.

Божидар Стойнефф
источник
2

Если Ваша ветка опережает ' origin/XXX' на 5 коммитов.

Вы можете оформить:

git reset --hard HEAD~5

И это должно удалить последние 5 коммитов.

Ха Чу
источник
0
git reset --hard <SHA-Code>

Это пригодится, если вы допустили некоторые ошибки в своей локальной копии, и хотите, чтобы они не были по ошибке отправлены в удаленную ветку.

Код SHA можно получить, посмотрев на webVersion вашей git dashboard для последнего коммита в ветке.

Таким образом, вы можете синхронизироваться с последним коммитом на ветке.

Ты можешь сделать git pull после того, как вы успешно выполнили полный сброс, чтобы подтвердить ничего нового для синхронизации, т.е. вы увидите сообщение.

Ваш филиал обновлен с Origin/<Branch Name>

Самер Ашраф
источник
0

Если ваш локальный репо окажется в полном беспорядке, то надежный способ отбросить локальные коммиты в Git - это ...

  1. Используйте "git config --get remote.origin.url", чтобы получить URL удаленного источника
  2. Переименуйте локальную папку git в «my_broken_local_repo»
  3. Используйте "git clone <url_from_1>", чтобы получить свежую локальную копию удаленного репозитория git

По моему опыту, Eclipse хорошо справляется с изменяющимся миром. Однако вам может понадобиться выбрать затронутые проекты в Eclipse и очистить их, чтобы заставить Eclipse перестроить их. Я думаю, что другие IDE тоже могут нуждаться в принудительной перестройке.

Дополнительным преимуществом описанной выше процедуры является то, что вы узнаете, использует ли ваш проект локальные файлы, которые не были помещены в git. Если вы обнаружите, что у вас отсутствуют файлы, вы можете скопировать их из «my_broken_local_repo» и добавить их в git. Если вы уверены, что в вашем новом локальном репо есть все, что вам нужно, вы можете удалить «my_broken_local_repo».

Адам Гавн-Каин
источник
0

Если вы просто хотите отбросить локальные коммиты и сохранить изменения, сделанные в файлах, тогда выполните
git reset @ ~
Другие ответы, адресованные к hard reset

Ашиш Банкир
источник