Как разблокировать последний un-push git commit без потери изменений

541

Есть ли способ отменить коммит, чтобы моя локальная копия сохранила изменения, сделанные в этом коммите, но они стали не зафиксированными изменениями в моей рабочей копии? Откат коммита приведет вас к предыдущему коммиту - я хочу сохранить внесенные изменения, но перенес их в неправильную ветку.

Это не было выдвинуто, только совершено.

Мистер Бой
источник
6
git reset --softи git reset --mixedоба делают это (немного по-разному), см. git-reset
torek

Ответы:

933

Есть много способов сделать это, например:

если вы еще не опубликовали коммит публично:

git reset HEAD~1 --soft   

Вот и все, изменения вашего коммита будут в вашем рабочем каталоге, тогда как коммит LAST будет удален из вашей текущей ветки. Смотри git reset man


В случае, если вы сделали публичный пуш (в ветке с именем 'master'):

git checkout -b MyCommit //save your commit in a separate branch just in case (so you don't have to dig it from reflog in case you screw up :) )

вернуть коммит нормально и нажать

git checkout master
git revert a8172f36 #hash of the commit you want to destroy
# this introduces a new commit (say, it's hash is 86b48ba) which removes changes, introduced in the commit in question (but those changes are still visible in the history)
git push origin master

Теперь, если вы хотите, чтобы эти изменения были локальными изменениями в вашей рабочей копии («чтобы ваша локальная копия сохранила изменения, сделанные в этом коммите») - просто отмените коммит с --no-commitопцией:

git revert --no-commit 86b48ba (hash of the revert commit).

Я создал небольшой пример: https://github.com/Isantipov/git-revert/commits/master

Isantipov
источник
5
Огромное спасибо, в моем случае у меня было два коммита, которые я хотел отменить, и дважды выполнив команду «git reset HEAD ~ 1 --soft», я оказался там, где мне нужно было.
Джефф Гантер
2
Чтобы немного прояснить ситуацию, если вы не используете CLI, первая resetупомянутая команда говорит «мягко» сбросить до 1 об. перед заголовком, что сохраняет все локальные изменения. это не было сразу видно для использования в SourceTree. просто убедитесь, что вы мягко сбрасываете на предыдущую версию, а не на ту, которую пытаетесь сбросить
Jon B
1
Я попробовал «уже выдвинутый» подход, и он не работает для меня, с git 2.14.1: он говорит "Already up to date"при выполнении слияния.
Фабио А.
1
@FabioA. Я обновил ответ рабочей версией. Спасибо, что заметили это!
Исантипов
1
Это не работает Я пропустил сброс и фиксацию и только сделал git, чтобы вернуться и вытолкнуть ... теперь, возможно, изменения потеряны, еще не уверен ... к счастью, я сделал резервную копию простым способом, надеюсь, что он все еще будет работать;) в противном случае можно скопировать изменения из этого ,
Skybuck Flying
13

Если вы отправили изменения, вы можете сделать undoэто и переместить файлы обратно на сцену, не используя другую ветку.

git show HEAD > patch
git revert HEAD
git apply patch

Это создаст файл патча, который содержит последние изменения ветки. Затем он отменяет изменения. И наконец, примените файлы исправлений к рабочему дереву.

Аминадав Гликштейн
источник
ты rm patchтоже хочешь
Макс Коплан
6

Для случая: «Это не было выдвинуто, только совершено ». - если вы используете IntelliJ (или другую интегрированную среду JetBrains) и еще не отправили изменения, вы можете сделать следующее.

  1. Перейдите в окно контроля версий ( Alt + 9 / Command + 9 ) - вкладка «Журнал».
  2. Щелкните правой кнопкой мыши на коммите до вашего последнего.
  3. Сбросить текущую ветку сюда
  4. выбрать Soft (!!!)
  5. нажмите кнопку сброса в нижней части диалогового окна.

Выполнено.

Это «отменит» ваши изменения и вернет ваш git-статус на уровень, предшествующий вашей последней локальной фиксации. Вы не потеряете сделанные вами изменения.

Эдуард Стрельцов
источник
2
Я люблю изучать способ JetBrains, спасибо! Это эквивалентно git reset --soft "HEAD^"Windows, кстати. :)
Пейн
3

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

git revert commit-hash
git push

git checkout my-other-branch
git revert revert-commit-hash
git push
  1. отменить коммит
  2. (создать и) оформить заказ в другой ветке
  3. вернуть назад
Mubashar
источник
1
Я проверял это. Ваш подход также работает, если вы не нажали на удаленный. $ git revert <commit-hash> ... затем извлеките какую-нибудь другую ветку, затем введите $ git revert <revert-commit-hash> (без толчков). Спасибо, что поделились этим простым подходом!
Натали Коттрилл
2

2020 простой способ:

git reset <commit_hash>

Зафиксируйте хэш последнего коммита, который вы хотите сохранить.

XYS
источник
1

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

git checkout branch_name

Оформить заказ в вашей ветке

git merge --abort

Прервать слияние

мерзавец статус

Проверьте статус кода после прерывания слияния

git reset --hard origin / branch_name

эти команды сбросят ваши изменения и приведут ваш код в соответствие с кодом branch_name (branch).

Мохит Сингх
источник