Як скасувати "git commit --amend", зроблене замість "git commit"


1294

Я випадково змінив свої попередні зобов'язання. Комітет повинен був бути окремим, щоб зберігати історію змін, внесених до певного файлу.

Чи є спосіб скасувати останнє виконання? Якщо я щось роблюgit reset --hard HEAD^ , перше зобов’язання також не скасовується.

(Я ще не переходив у жодні віддалені каталоги)

Відповіді:


2289

Що вам потрібно зробити, це створити нову команду з тими ж деталями, що і поточна HEADкомісія, але з батьківською версією, як і попередня версія HEAD. git reset --softперемістить вказівник гілки так, що наступний фіксатор відбудеться поверх іншого коміту від того, де зараз знаходиться керівник гілки.

# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}

33
Дуже круто, +1. Я навіть зробив це з другим останнім внести поправки в цілях , git reflogщоб знайти правильний номер , наприклад {2}.
JJD

178
Щоб було зрозуміло, перша команда - це справжнє "скасування". Він виробляє HEAD, робочий каталог (без змін) та стан індексу до git commit --amend. 2-й - це "повтор" у новий коміт. Ці працюють для будь-якого git commit, не просто --amend.
cdunn2001

60
Тож якщо ви не внесли поправки в нове повідомлення про фіксацію, що вам потрібно виправити, друга частина може бути просто звичайною git commit.
Метт Монтаг

18
З якої - то причини, я отримую повідомлення про помилку при запуску git reset --soft HEAD@{1}: fatal: ambiguous argument 'HEAD@1': unknown revision or path not in the working tree. Use '--' to separate paths from revisions. Коли я замінив HEAD@{1}еквівалентний хеш git reflogкомітів, показаний у (дякую JJD!), Ця відповідь спрацювала чудово!
Тім Камбер

20
@TimArnold, залежно від вашої оболонки, можливо, вам знадобиться поставити окремі або подвійні лапки HEAD@{1}. Якщо я, наприклад, запускаю echo HEAD@{1}tcsh, результат виходить HEAD@1через те, що дужки інтерпретуються tcsh. Якщо я використовую одинарні лапки, дужки зберігаються.
Келвін

136

використовувати журнал ref :

git branch fixing-things HEAD@{1}
git reset fixing-things

тоді у вас повинні бути всі ваші раніше внесені зміни лише у вашій робочій копії, і ви зможете зробити їх знову

щоб побачити повний список попередніх типів індексів git reflog


7
Це також стирає індекс - все ще корисно, але виходить за рамки простого "скасування".
cdunn2001

3
чи є різниця між HEAD@{1}і HEAD~1?
неавмузичний

15
@neaumusic: так! HEAD~1точно такий же, як HEAD^і ідентифікатори батьків поточної комісії. HEAD@{1}з іншого боку, йдеться про зобов’язання, на які HEAD вказував перед цим, тобто вони означають різні зобов’язання, коли ви перевіряєте іншу гілку чи змінюєте комісію.
knittl

@knittl ах, недарма, я не думав, що це було можливо раніше, ще раз дякую, хороша інформація
neaumusic

9
крок кулака зайвий. Простий git reset HEAD@{1}досить.
dwelle

79

Знайдіть змінені зобов’язання:

git log --reflog

Примітка. Ви можете додати, --patchщоб побачити основу комітетів для ясності. Те саме, що git reflog.

потім скиньте свою голову до будь-якої попередньої фіксації в момент, коли це було добре:

git reset SHA1 --hard

Примітка. Замініть SHA1 вашим справжнім хешем фіксації. Також зауважте, що ця команда втратить будь-які неспроможні зміни, тому ви можете їх зберігати раніше. Крім того, використовуйте --softнатомість, щоб зберегти останні зміни, а потім здійснити їх.

Потім виберіть інший комітет, який вам потрібен поверх:

git cherry-pick SHA1

26
Якщо ви це зробите git reset SHA1 --soft, ви можете зберегти останні зміни, а потім виконати їх.
pravj

24

Ви завжди можете розділити комір, із посібника

  • Запустіть інтерактивну ребазу з git rebase -i commit ^, де commit - це фіксація, яку ви хочете розділити. Насправді, будь-який діапазон комісій буде виконуватись, доки він містить цю комісію.
  • Позначте команду, яку ви хочете розділити, дією "редагувати".
  • Якщо справа стосується редагування цього коміту, виконайте скидання Git HEAD ^. Ефект полягає в тому, що HEAD перемотується на одиницю, а індекс іде відповідно. Однак робоче дерево залишається таким же.
  • Тепер додайте зміни до індексу, який ви хочете мати під час першого виконання. Ви можете використовувати git add (можливо, інтерактивно) або git-gui (або обидва) для цього.
  • Зв'яжіть поточний індекс із будь-яким повідомленням про фіксацію.
  • Повторіть останні два кроки, поки ваше робоче дерево не очиститься.
  • Продовжуйте ребазувати за допомогою git rebase - продовжуйте.

26
спосіб занадто складний. git reflogце все, що вам потрібно
knittl

2
Так багато кроків, але кожен крок нескладний і простий у виконанні. Це працювало на мене і отримує мій голос.
OzBandit

5
окрім цього, ця відповідь дозволяє вибірково вибирати зміни, які ви випадково "змінили", і надає деяку додаткову цінність для скидання git - програмного забезпечення HEAD @ {1} (що вирішило мою проблему BTW)
Wiebe Tijsma

2
Ви також можете вибірково вибирати зміни за допомогою методу reflog. Просто зробіть git resetзамість git reset --soft, потім зробіть git add --patch.
geekofalltrades

1
Це все ще переписує історію і вимагає силового натиску. Залежно від вашої ситуації це може бути або не бути проблемою.
Пайн

20

Можливо, варто відзначити, що якщо ви все ще знаходитесь в своєму редакторі із повідомленням про фіксацію, ви можете видалити повідомлення про фіксацію, і воно скасує git commit --amend команду.


Це одне.
atilkan

Збережено моє, але ^^
інженерне

14

Можливо, може використовувати git reflog для отримання двох зобов'язань перед поправкою та після внесення змін.

Потім використовуйте git diff before_commit_id after_commit_id > d.diff для отримання різниці між до внесення змін та після внесення змін.

Наступне використання git checkout before_commit_id для повернення до здійснення

І останнє використання git apply d.diff щоб застосувати реальні зміни, які ви зробили.

Це вирішує мою проблему.


11

Якщо ви перенесли комісію на віддалений і потім помилково внесені зміни до цього комітету, це вирішить вашу проблему. Випустіть a, git logщоб знайти SHA перед фіксацією. (це передбачає віддалене ім'я походження). Тепер видайте ці команди за допомогою цієї SHA.

git reset --soft <SHA BEFORE THE AMMEND>
#you now see all the changes in the commit and the amend undone

#save ALL the changes to the stash
git stash

git pull origin <your-branch> --ff-only
#if you issue git log you can see that you have the commit you didn't want to amend

git stash pop
#git status reveals only the changes you incorrectly amended

#now you can create your new unamended commit

3
Це особливий випадок із більш загального питання, але він саме охопив мою негайну потребу.
dmckee --- кошеня колишнього модератора

8

Ви можете зробити це нижче, щоб скасувати своє git commit —amend

  1. git reset --soft HEAD^
  2. git checkout files_from_old_commit_on_branch
  3. git pull origin your_branch_name

======================================

Тепер ваші зміни є такими, як попередні. Отже, ви закінчили з відміноюgit commit —amend

Тепер ви можете зробити git push origin <your_branch_name>, щоб підштовхнути до гілки.


3

Майже на 9 років з цим запізнився, але не бачив, щоб ця варіація згадала таку саму річ (це свого роду комбінація декількох із них, схожа на верхню відповідь ( https://stackoverflow.com/a/1459264/4642530 ) .

Шукати по всіх відокремлених головках на гілці

git reflog show origin/BRANCH_NAME --date=relative

Потім знайдіть хеш SHA1

Скинути на старий SHA1

git reset --hard SHA1

Потім натисніть назад.

git push origin BRANCH_NAME

Зроблено.

Це поверне вас до старого завершення цілком.

(Включаючи дату попереднього перезаписаного відокремленого голови комісії)


Так, але я, як правило, хочу скинути, --softщоб зберегти зміни. Я просто хочу, щоб це було вчинено окремо
Хуан Мендес

2
  1. Замовлення до тимчасового відділення з останньою комісією

    git branch temp HEAD@{1}

  2. Скидання останньої комісії

    git reset temp

  3. Тепер у вас будуть всі файли, які ви здійснюєте, а також попередні. Перевірте стан усіх файлів.

    git status

  4. Скидання файлів фіксації зі стадії git.

    git reset myfile1.js (так далі)

  5. Повторно прикріпіть цю комісію

    git commit -C HEAD@{1}

  6. Додайте та фіксуйте свої файли до нових фіксацій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.