Как мне удалить невыдвинутые коммиты git?

949

Я случайно совершил не ту ветку. Как мне удалить этот коммит?

NullVoxPopuli
источник

Ответы:

1812

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

git reset --soft HEAD~1

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

git reset --hard HEAD~1
dbyrne
источник
13
удостоверьтесь, что ГОЛОВА указывает на ветку .. (проверьте это сначала)
Фрэнк Швитерман
128
И убедитесь, что HEAD ~ 1 является коммитом ... Вы также можете сделатьgit reset --hard origin
Дейнит
13
git remoteСписки мыслей происхождения для меня, git reset --hard originговорит fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. Почему?
trss
7
Это круто. Просто спас мне жизнь.
NinjaBoy
2
git reset HEAD~1также сохранит все ваши изменения, но оставит вас с пустым индексом, а не сохранит все (как --softвариант).
Holloway
139

Интересно, почему лучший ответ, который я нашел, только в комментариях! ( Daenyth с 86 голосами против )

git reset --hard origin

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

git reset --hard origin/<branch>
Ашкан Сироус
источник
16
Спасибо за это, немного расширив объяснение: для конкретной ветки:git reset --hard origin/<branch>
cleary
4
Или git reset --soft origin/<branch>, если вы хотите избавиться от коммита, но продолжите локальную работу.
речной конь
1
я получаю fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., вам нужно указать ветку, как:git reset --hard origin/feature/my-cool-stuff
Кип
Brilliant! Это на самом деле работает, в отличие от «принятого» ответа, который просто отрывает голову и оставляет вас висеть.
Мэ
55

Не удаляйте его: достаточно одного коммита git cherry-pick.

Но если у вас было несколько коммитов на неправильной ветке, вот где git rebase --ontoсветит:

Предположим, у вас есть это:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, затем вы можете пометить masterи переместить его туда, где вы хотите быть:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, сбросьте y ветку, где она должна была быть:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

и, наконец, переместите свои коммиты (примените их заново, делая новые коммиты)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch
VonC
источник
к сожалению, это был не вопрос.
Катария
1
@KatariaA Это правильная альтернатива удалению коммита, выполненного в неправильной ветке, и поможет другим в той же ситуации (хороший коммит сделан в неправильной ветке).
VonC
14

Сделайте git rebase -i FAR_ENOUGH_BACKи оставьте строку для коммита, который вам не нужен.

Хэнк Гей
источник
6

Если вы хотите переместить этот коммит в другую ветку, получите SHA соответствующего коммита

git rev-parse HEAD

Затем переключите текущую ветку

git checkout other-branch

И cherry-pickобязательствоother-branch

git cherry-pick <sha-of-the-commit>
Александр Грос
источник
Исходя из моего опыта, это не отменяет коммит из оригинальной ветки, что требует git reset --hard HEAD~1последующих действий . Я думаю, что использование reset --softзатем переключения веток и повторной фиксации спасло бы дополнительную работу. С другой стороны, я использовал SourceTree для выполнения большинства моих базовых задач, только после того, как выполнил командную строку после ошибки.
Юзопи
3

Для справки, я полагаю, что вы можете «жестко вырезать» коммиты из вашей текущей ветки не только с помощью git reset --hard, но и с помощью следующей команды:

git checkout -B <branch-name> <SHA>

Фактически, если вы не заботитесь о проверке, вы можете установить ветку на что хотите:

git branch -f <branch-name> <SHA>

Это может быть программный способ удаления коммитов из ветви, например, для копирования в него новых коммитов (с использованием rebase).

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

Теперь у вас есть ветка, в которой вы применили изменения, давайте назовем это «тема».

Теперь вы создадите дубликат вашей ветки тем и затем переместите ее в дамп исходного кода, который находится в ветке «dump»:

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Теперь ваши изменения повторно применяются в ветке topic_duplicate, основываясь на начальной точке «dump», но только на тех коммитах, которые произошли после «master». Таким образом, ваши изменения, так как master теперь повторно применяются поверх «dump», но результат заканчивается в «topic_duplicate».

Затем вы можете заменить «dump» на «topic_duplicate», выполнив:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

Или с

git branch -M topic_duplicate dump

Или просто отбросив дамп

git branch -D dump

Возможно, вы также можете просто выбрать вишню после очистки текущей "topic_duplicate".

Я пытаюсь сказать, что если вы хотите обновить текущую «дублирующуюся» ветвь на основе другого предка, вы должны сначала удалить ранее «выбранные» коммиты, выполнив git reset --hard <last-commit-to-retain>или или git branch -f topic_duplicate <last-commit-to-retain>затем скопировав другие коммиты (из основного ветка темы) либо перебазировкой, либо сбором вишни.

Перебазирование работает только на ветке, в которой уже есть коммиты, поэтому вам нужно дублировать ветку темы каждый раз, когда вы захотите это сделать.

Cherrypicking гораздо проще:

git cherry-pick master..topic

Таким образом, вся последовательность будет сводиться к:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Когда ваша тема-дубликат ветки была проверена. Это позволит удалить ранее выбранные коммиты из текущего дубликата и просто повторно применить все изменения, происходящие в «топике» поверх вашего текущего «дампа» (другого предка). Кажется, это достаточно удобный способ, чтобы основывать свою разработку на «реальном» ведущем мастере, используя другой «нижестоящий» мастер, чтобы проверить, применимы ли ваши локальные изменения к этому. В качестве альтернативы вы можете просто сгенерировать diff и затем применить его за пределами любого исходного дерева Git. Но таким образом вы можете сохранить обновленную модифицированную (исправленную) версию, основанную на версии вашего дистрибутива, в то время как ваша фактическая разработка идет вразрез с реальным вышестоящим мастером.

Так что просто для демонстрации:

  • Сброс заставит вашу ветвь указывать на другую фиксацию (--hard также проверяет предыдущую фиксацию, --soft сохраняет добавленные файлы в индексе (что будет зафиксировано, если вы подтвердите снова), и значение по умолчанию (--mixed) не будет проверьте предыдущий коммит (стирая ваши локальные изменения), но он очистит индекс (пока ничего не было добавлено для коммита)
  • вы можете просто заставить ветку указывать на другой коммит
  • Вы можете сделать это, сразу же проверяя этот коммит, а также
  • перебазирование работает на коммитах, присутствующих в вашей текущей ветке
  • сбор вишни означает копирование из другой ветки

Надеюсь, это кому-нибудь поможет. Я хотел переписать это, но я не могу справиться сейчас. С уважением.

Xennex81
источник
0

Следующая команда сработала для меня, все локальные зафиксированные изменения отбрасываются, а локальный сбрасывается на то же, что и удаленная исходная / главная ветвь.

git reset --hard origin

Атул Сурека
источник