Как отменить несколько коммитов git?

У меня есть репозиторий git, который выглядит так:

A <- B <- C <- D <- HEAD

Я хочу, чтобы голова ветки указывала на A, то есть я хочу, чтобы B, C, D и HEAD исчезли, и я хочу, чтобы голова была синонимом A.

Похоже, я могу либо попробовать перебазировать (не применяется, поскольку я внес изменения между ними), либо вернуться. Но как мне отменить несколько коммитов? Могу ли я возвращаться по одному? Порядок важен?


person Bill    schedule 23.09.2009    source источник
comment
Если вы просто хотите перезагрузить пульт, вы можете заткнуть его чем угодно! Но давайте воспользуемся четвертой фиксацией назад: git push -f HEAD~4:master (при условии, что удаленная ветка является главной). Да, вы можете нажать любую такую ​​фиксацию.   -  person u0b34a0f6ae    schedule 23.09.2009
comment
Если люди вытащили, вы должны сделать коммит, который отменяет изменения с помощью git revert.   -  person Jakub Narębski    schedule 23.09.2009
comment
Используйте git show HEAD ~ 4, чтобы убедиться, что вы нажимаете правый на удаленный   -  person Mâtt Frëëman    schedule 11.06.2016
comment
Возможный дубликат Как отменить последние фиксации в Git?   -  person Jim Fell    schedule 14.02.2017
comment
Порядок важен? Да, если коммиты затрагивают одни и те же строки в одних и тех же файлах. Затем вы должны начать откат самого последнего коммита и вернуться обратно.   -  person avandeursen    schedule 22.04.2017


Ответы (15)


Расширение того, что я написал в комментарии

Общее правило состоит в том, что вы не должны переписывать (изменять) историю, которую вы опубликовали, потому что кто-то мог основывать свою работу на ней. Если вы переписываете (изменяете) историю, у вас могут возникнуть проблемы с объединением их изменений и с их обновлением.

Итак, решение состоит в том, чтобы создать новую фиксацию, которая отменяет изменения, от которых вы хотите избавиться. Вы можете сделать это с помощью git revert".

У вас следующая ситуация:

A <-- B  <-- C <-- D                                  <-- master <-- HEAD

(здесь стрелки указывают направление указателя: родительская ссылка в случае фиксации, верхняя фиксация в случае заголовка ветки (ссылка ветки) и имя ветки в случае ссылки HEAD).

Вам нужно создать следующее:

A <-- B  <-- C <-- D <-- [(BCD)-1]                   <-- master <-- HEAD

где [(BCD)^-1] означает фиксацию, которая отменяет изменения в коммитах B, C, D. Математика говорит нам, что (BCD) -1 = D -1 C -1 < / sup> B -1, поэтому вы можете получить требуемую ситуацию, используя следующие команды:

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message for all of them"

Работает для всего, кроме коммитов слияния.


Альтернативным решением было бы проверить содержимое фиксации A и зафиксировать это состояние. Также работает с коммитами слияния. Однако добавленные файлы не будут удалены. Если у вас есть какие-либо локальные изменения git stash сначала:

$ git checkout -f A -- . # checkout that revision over the top of local files
$ git commit -a

Тогда у вас будет следующая ситуация:

A <-- B  <-- C <-- D <-- A'                       <-- master <-- HEAD

Фиксация A 'имеет то же содержимое, что и фиксация A, но представляет собой другую фиксацию (сообщение фиксации, родители, дата фиксации).


Альтернативное решение Джеффа Ферланда, измененное Чарльзом Бейли, основано на той же идее, но использует git reset. Здесь он немного видоизменен, так РАБОТАЕТ НА ВСЕ:

$ git reset --hard A
$ git reset --soft D # (or ORIG_HEAD or @{1} [previous location of HEAD]), all of which are D
$ git commit
person Jakub Narębski    schedule 24.09.2009
comment
Если вы добавили файлы в B, C или D. git checkout -f A -- . Не удалит их, вам придется сделать это вручную. Я применил эту стратегию сейчас, спасибо Якуб - person oma; 31.03.2011
comment
Эти решения не эквивалентны. Первый не удаляет вновь созданные файлы. - person m33lky; 26.01.2012
comment
FWIW, если вам нужно удалить эти новые файлы, git clean - ваш друг. - person Ben Hamill; 03.07.2012
comment
привет, ты можешь объяснить все флаги и переключатели здесь? git checkout -f A -. - ›что означает '-' и '.' иметь в виду? - person chriz; 20.07.2012
comment
@mastah: -- может понадобиться для отделения имени ветки от пути. . означает текущий каталог, и поскольку здесь пути относятся к верхнему каталогу проекта, это означает получение всего проекта, всех файлов проекта. - person Jakub Narębski; 20.07.2012
comment
@ JakubNarębski Что может значить? Я тоже считаю эту команду очень загадочной ... - person Ji ZHANG; 23.01.2013
comment
@Jerry: git checkout foo может означать checkout branch foo (переключиться на ветку) или checkout file foo (из индекса). -- используется для устранения неоднозначности, например git checkout -- foo всегда о файле. - person Jakub Narębski; 23.01.2013
comment
В дополнение к отличному ответу. Мне подходит это сокращение git revert --no-commit D C B - person welldan97; 09.08.2013
comment
@ welldan97: Спасибо за комментарий. При написании этого ответа git revert не принимал несколько коммитов; это довольно новое дополнение. - person Jakub Narębski; 09.08.2013
comment
Этот ответ очень хорошо объясняет все варианты, но не должны ли мы поместить решение git reset --soft @{1} вверху? Очевидно, это лучшее решение проблемы. - person Robin Winslow; 20.09.2013
comment
Чтобы прояснить git checkout -f A -- ., я думаю, это означает проверку изменений фиксации A в текущем каталоге, не переходя в режим отсоединенной HEAD, в основном, вы остаетесь в мастере, но переносите изменения фиксации A в текущее место во времени. По крайней мере, я так интерпретирую, пожалуйста, поправьте меня, если я ошибаюсь. - person Flatline; 04.10.2013
comment
@Flatline: git checkout -f A -- . означает проверку состояния фиксации A в текущем каталоге, перезапись файлов ... но не удаляет файлы, чтобы привести его в состояние A. - person Jakub Narębski; 04.10.2013
comment
Это наиболее эффективный и ответственный способ отката на git. - person ffffranklin; 23.09.2015
comment
Перебазируйте только локально! Как мы уже обсуждали с git commit --amend и git reset, никогда не следует перебазировать коммиты, которые были отправлены в общедоступный репозиторий. Перебазирование заменит старые коммиты новыми, и будет выглядеть так, как будто эта часть истории вашего проекта внезапно исчезла. ссылка - person Peeter Kokk; 16.05.2016
comment
git checkout -f A -- . не сработал для меня. Когда я попытался протолкнуть его, я не смог без слияния удаленной версии, чего я не хотел. Я пытаюсь отменить последние несколько коммитов, поэтому не хочу, чтобы удаленная версия была объединена. - person Mars; 30.10.2016
comment
Просто хочу добавить одну вещь, которая нам помогала. Никогда не совершайте коммит между возвратами. Ключевой частью является --no-commit. Если вы выполняете коммиты между возвратами, в конце вы можете получить странные сравнения между разными коммитами. - person 100r; 26.01.2017
comment
Третье решение было тем, что сработало в моем сложном случае, включающем несколько коммитов и слияний, а также добавление и удаление файлов. - person entpnerd; 07.06.2017
comment
Я пошел с git checkout -f A -. поскольку у меня было 8 коммитов, и мне понравилась идея 1 шага. В основном это сработало, однако я хотел бы отметить, что новые файлы не удалялись, просто измененные файлы отменялись, я сравнил удаленную головку с моей веткой, выбранной вишней, после запуска этой команды и нажатия и видел только новые файлы после их удаления, а затем фиксации / нажатия , ветви были идентичны. - person edencorbin; 03.09.2017
comment
ты мой герой, ты спасаешь мой день, ты мне очень помог, это отличный ответ, твое решение отличное, я хочу сказать спасибо, ты такой профессионал ‹3‹ 3 ‹3‹ 3 ‹3‹ 3 ‹3 - person 尤川豪; 23.11.2017
comment
Я никогда раньше не думал о коммитах как о матрицах. Удивительный. - person Daniel says Reinstate Monica; 07.12.2017
comment
git revert терпит неудачу при коммитах слияния, однако проверка содержимого предыдущего хэша и их фиксация великолепны, спасибо! - person T to the J; 17.01.2019
comment
Еще больше неработающего дерьма Git ... Как только выполняется первый откат, получается error: your index file is unmerged. Этот инструмент - неудачная шутка. - person jww; 09.06.2019
comment
git revert также не принимает коммиты слиянием. Я использовал git checkout -f A -- ., и он отлично работал. - person Daniel R Carletti; 23.03.2020
comment
@DanielRCarletti: в случае фиксации слияния git revert необходимо знать, какое изменение (относительно какого родителя) вы хотите отменить, с опцией -m. Но в этом случае может быть лучше другое решение. - person Jakub Narębski; 24.03.2020
comment
именно то, что я искал. Отличное объяснение - person Prasanna Mondkar; 11.08.2020
comment
Еще одна вещь, о которой следует остерегаться git checkout -f A -- ., - это то, что она отбросит все неэтапные изменения, которые у вас есть. Сделайте сначала git stash, если хотите их сохранить. - person Kyle; 25.09.2020
comment
@JiZHANG -- потребуется в случае, если имя вашего файла начинается с один или несколько дефисов. Якуб был тщательным. - person Nathaniel Jones; 21.07.2021

Чистый способ, который я нашел полезным

git revert --no-commit HEAD~3..

Эта команда отменяет последние 3 фиксации только с одной фиксацией.

И не переписывает историю.

.. помогает создать диапазон. Значение HEAD~3.. совпадает с HEAD~3..HEAD

person deepdive    schedule 29.03.2017
comment
как это может работать, если нет фиксации? Что нужно сделать помимо указанной выше команды? какие команды git необходимы до / после этой команды? - person John Little; 23.10.2017
comment
@JohnLittle вносит изменения. git commit оттуда фактически выполнит фиксацию. - person x1a4; 01.11.2017
comment
Это не сработает, если некоторые коммиты являются коммитами слияния. - person MegaManX; 07.09.2018
comment
Что делают две точки в конце? - person cardamom; 18.12.2018
comment
@cardamom Те указывают диапазон. HEAD~3.. совпадает с HEAD~3..HEAD - person Toine H; 18.12.2018
comment
- это слияние, но опция -m не указана. фатальный: возврат не выполнен - person ScottyBlades; 16.01.2021

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

Принимая во внимание ваш пример, вам нужно будет сделать это (при условии, что вы находитесь в ветке master):

git revert master~3..master

or git revert B...D or git revert D C B

Это создаст новую фиксацию на вашем локальном компьютере с обратной фиксацией B, C и D (что означает, что она отменит изменения, внесенные этими фиксациями):

A <- B <- C <- D <- BCD' <- HEAD
person Victor    schedule 31.07.2012
comment
git revert --no-commit HEAD~2.. - это немного более идиоматический способ сделать это. Если вы находитесь в главной ветке, нет необходимости снова указывать мастер. Параметр --no-commit позволяет git попытаться отменить все коммиты сразу, вместо того, чтобы засорять историю несколькими revert commit ... сообщениями (если это то, что вы хотите). - person kubi; 15.01.2013
comment
@Victor Я исправил ваш диапазон фиксации. Начало диапазона является эксклюзивным, то есть не включено. Итак, если вы хотите отменить последние 3 коммита, вам нужно начать диапазон с родительского третьего коммита, то есть master~3. - person ; 25.04.2014
comment
@kubi нет возможности включить SHA в сообщение фиксации, используя одну фиксацию (ваш метод, но без необходимости вручную вводить отмененные фиксации)? - person Chris S; 01.10.2015
comment
@ChrisS Моей первой мыслью было бы не использовать --no-commit (чтобы вы получали отдельную фиксацию для каждого отката), а затем скомбинировать их все вместе в интерактивном перебазировании. Комбинированное сообщение фиксации будет содержать все SHA, и вы можете расположить их, как вам нравится, используя свой любимый редактор сообщений фиксации. - person Radon Rosborough; 15.11.2016
comment
Конечно, если вы сделаете это без --no-commit, он сделает их по одному, и вам придется набирать git revert --continue снова и снова для каждого ... черт, я надеялся, что у git будет удобная опция фиксации, например, сделать их все и перечислить все хеши для меня в одном коммите, но не отображаются: | - person rogerdpack; 12.10.2020

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

# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD  
$ git commit -m 'message'
person konyak    schedule 31.07.2014
comment
Ваше решение сработало для меня, но с небольшими изменениями. Если у нас есть случай Z - ›A -› B - ›C -› D - ›HEAD, и если я хочу вернуться в состояние A, то, как ни странно, мне пришлось бы выполнить git revert --no-commit Z .. ГОЛОВА - person Bogdan; 22.02.2016
comment
Согласитесь с @Bogdan, диапазон возврата такой: SHA_TO_REVERT_TO..HEAD - person Vadym Tyemirov; 10.05.2016
comment
Диапазон неправильный. Он должен быть B^..HEAD, иначе B исключен. - person tessus; 28.04.2018
comment
Согласитесь с @tessus, поэтому правильнее будет: git revert --no-commit B^..HEAD или git revert --no-commit A..HEAD - person Yoho; 29.09.2018

git reset --hard a
git reset --mixed d
git commit

Это будет действовать как возврат для всех сразу. Дайте хорошее сообщение о фиксации.

person Jeff Ferland    schedule 23.09.2009
comment
Если он хочет, чтобы HEAD выглядел как A, то он, вероятно, хочет, чтобы индекс соответствовал, поэтому git reset --soft D, вероятно, будет более подходящим. - person CB Bailey; 23.09.2009
comment
--soft resetting не перемещает индекс, поэтому, когда он фиксирует, это будет выглядеть так, как будто фиксация пришла непосредственно из a, а не из D. Это приведет к разделению ветки. --mixed оставляет изменения, но перемещает указатель индекса, поэтому D станет родительским коммитом. - person Jeff Ferland; 25.09.2009
comment
Да, я думаю, что git reset --keep - это именно то, что я написал выше. Он вышел в версии 1.7.1, выпущенной в апреле 2010 года, так что ответа в то время не было. - person Jeff Ferland; 11.11.2010
comment
git checkout A, затем git commit выше у меня не сработало, но этот ответ сработал. - person SimplGy; 29.08.2013
comment
Почему требуется git reset --mixed D? Конкретно почему reset? Это потому, что без сброса на D, HEAD будет указывать на A, в результате чего B, C и D будут зависать и собирать мусор - чего он не хочет? Но тогда почему --mixed? Вы уже ответили --soft сброс не перемещает индекс ... Таким образом, перемещение индекса означает, что индекс будет содержать изменения D, а рабочий каталог будет содержать изменения A - таким образом, git status или git diff (который сравнивает индекс [D] в рабочий каталог [A]) покажет содержание; этот пользователь возвращается с D на A? - person The Red Pea; 10.01.2016
comment
--mixed не работает в случае отмены фиксации, которая удалила файл, но --soft работает хорошо ... - person rogerdpack; 12.10.2020

Сначала убедитесь, что ваша рабочая копия не изменена. Потом:

git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply

а затем просто зафиксируйте. Не забудьте указать причину возврата.

person mateusz.fiolka    schedule 09.09.2014
comment
Не работает с двоичными файлами: error: cannot apply binary patch to 'some/image.png' without full index line error: some/image.png: patch does not apply - person GabLeRoux; 10.07.2017
comment
Это гораздо более гибкое решение, чем принятый ответ. Спасибо! - person Brian Kung; 29.09.2017
comment
re: двоичные файлы используют параметр --binary: git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply - person weinerk; 03.01.2018
comment
Это будет работать, даже если вы хотите отменить диапазон коммитов, содержащих коммиты слияния. При использовании git revert A..Z вы получите error: commit X is a merge but no -m option was given. - person Juliusz Gonera; 22.08.2018
comment
Вау, круто, именно то, что я искал. Таким образом, выполняется обратное сравнение, а затем эти изменения применяются к существующему коду. Очень умно, спасибо. ;) - person Somebody; 17.02.2020
comment
Это помогло мне отменить целую партию коммитов, которые уже были отправлены на удаленный компьютер - отличное решение! - person confirmator; 11.11.2020
comment
Используя эту команду, вам не нужно беспокоиться о коммитах слияния. Очень полезный - person Redar; 01.06.2021

Я так расстроен, что на этот вопрос нельзя просто ответить. Все остальные вопросы касаются того, как правильно повернуть вспять и сохранить историю. В этом вопросе говорится: "Я хочу, чтобы голова ветки указывала на A, т.е. я хочу, чтобы B, C, D и HEAD исчезли, и я хочу, чтобы голова была синонимом A."

git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f

Я многому научился, читая пост Якуба, но какой-то парень в компании (с доступом к нашей «тестовой» ветке без Pull-Request) выдвинул как 5 плохих коммитов, пытаясь исправить и исправить ошибку, которую он сделал 5 коммитов назад. Не только это, но и один или два запроса на извлечение были приняты, что теперь было плохо. Так что забудьте, я нашел последнюю удачную фиксацию (abc1234) и просто запустил базовый скрипт:

git checkout testing
git reset --hard abc1234
git push -f

Я сказал другим 5 парням, работающим в этом репо, что им лучше записать свои изменения за последние несколько часов и стереть / повторно ветвиться из последнего тестирования. Конец истории.

person Suamere    schedule 11.07.2016
comment
Я не публиковал коммиты, так что это был тот ответ, который мне нужен. Спасибо, @Suamere. - person Tom Barron; 30.11.2016
comment
Лучший способ сделать это - git push --force-with-lease, который перезапишет историю только в том случае, если никто другой не зафиксировал ветку после или в пределах диапазона коммитов на vapourize. Если ветку использовали другие люди, ее историю никогда не следует переписывать, а фиксацию следует просто отменить. - person frandroid; 01.12.2017
comment
Историю @frandroid никогда не следует переписывать, только ситхи имеют дело с абсолютом. Вопрос этой ветки и суть моего ответа заключается в том, что для определенного сценария вся история должна быть стерта. - person Suamere; 24.04.2018
comment
@Suamere Конечно, вот в чем вопрос. Но поскольку в вашем ответе упоминается о том, что вы должны были сказать другим парням, есть вероятность неприятностей. По личному опыту, push -f может испортить вашу базу кода, если другие люди сделали это после того, что вы пытаетесь стереть. --force-with-lease дает тот же результат, за исключением того, что он спасает вашу задницу, если вы собирались испортить свое репо. Зачем рисковать? Если --force-with-lease не удается, вы можете увидеть, какая фиксация мешает, правильно оценить, отрегулировать и попробовать еще раз. - person frandroid; 28.04.2018
comment
@frandroid А! Вы говорили, что вместо третьей строки git push -f вместо git push --force-with-lease Кажется очевидным, но ваш комментарий не так читается. Более того, казалось, что это было ваше однострочное, ни в чем не нуждающееся, точное решение. Я согласен с тем, что изменение последней строки моего ответа обеспечит дополнительную защиту (и дополнительную работу). Я просто лично не стал бы этого делать, если бы над кодом не работали люди, которых я не контролировал. Так что ваша точка зрения, безусловно, хороша для чего-либо с открытым исходным кодом или для всего нескольких отделов. Хотя я не Git Savant и даже не знаю эту команду, лол. - person Suamere; 01.05.2018
comment
@Suamere Спасибо! Я согласен, в вопросе ясно сказано, что он хочет переписать историю. Я нахожусь в той же ситуации, что и вы, и я предполагаю, что OP в том, что кто-то сделал десятки уродливых возвратов и странных коммитов и возвратов возвратов случайно (пока я был в отпуске), и состояние нужно вернуть. В любом случае, наряду с хорошим предупреждением о здоровье, это должен быть принятый ответ. - person Lee Richardson; 19.06.2019
comment
Спасибо, @Suamere, это тоже ответ, который мне нужен, поскольку я еще не нажимал на пульт. У меня был большой файл в коммите, который я позже проигнорировал, и мне пришлось просто избавиться от первого коммита, потому что я застрял, не имея возможности нажимать. Мне буквально нужно было, чтобы обязательства ушли. Это сработало :). - person BradStell; 07.05.2020

Это расширение одного из решений, представленных в ответе Якуба

Я столкнулся с ситуацией, когда коммиты, которые мне нужно было откатить, были довольно сложными, некоторые из которых были коммитами слияния, и мне нужно было избегать перезаписи истории. Мне не удалось использовать серию git revert команд, потому что в конечном итоге я столкнулся с конфликтами между добавляемыми изменениями реверсии. В итоге я использовал следующие шаги.

Сначала проверьте содержимое целевого коммита, оставив HEAD на конце ветки:

$ git checkout -f <target-commit> -- .

(- гарантирует, что <target-commit> интерпретируется как фиксация, а не как файл;. Относится к текущему каталогу.)

Затем определите, какие файлы были добавлены в откат коммитов и, следовательно, должны быть удалены:

$ git diff --name-status --cached <target-commit>

Добавленные файлы должны отображаться с буквой «A» в начале строки, и других различий быть не должно. Теперь, если необходимо удалить какие-либо файлы, подготовьте эти файлы для удаления:

$ git rm <filespec>[ <filespec> ...]

Наконец, зафиксируйте возврат:

$ git commit -m 'revert to <target-commit>'

При желании убедитесь, что мы вернулись в желаемое состояние:

$git diff <target-commit> <current-commit>

Никаких отличий быть не должно.

person Warren Dew    schedule 08.11.2016
comment
Вы уверены, что можете git ГОЛОВУ только с кончика ветки? - person Suamere; 08.11.2016
comment
Для меня это было намного лучшим решением, так как в моем случае у меня были коммиты слияния. - person sovemp; 18.11.2016

Самый простой способ отменить группу коммитов в общем репозитории (который люди используют и вы хотите сохранить историю) - использовать git revert в сочетании с git rev-list. Последний предоставит вам список коммитов, первый сделает откат самостоятельно.

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

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-commit $i; done

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

Другой вариант - иметь одну фиксацию для каждого отмененного изменения:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done

Например, если у вас есть дерево фиксации вроде

 o---o---o---o---o---o--->    
fff eee ddd ccc bbb aaa

чтобы отменить изменения с eee на bbb, запустите

for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
person Ruslan Kabalin    schedule 04.08.2011

Ни один из них не сработал для меня, поэтому у меня было три коммита, которые нужно было отменить (последние три коммита), поэтому я сделал:

git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash

Сработало как шарм :)

person Dorian    schedule 24.01.2017
comment
Это жизнеспособный вариант, только если ваши изменения еще не отправлены. - person kboom; 18.03.2018

На мой взгляд, очень простой и понятный способ:

вернуться к А

git checkout -f A

навести голову мастера на текущее состояние

git symbolic-ref HEAD refs/heads/master

спасти

git commit
person nulll    schedule 16.11.2018
comment
Не могли бы вы объяснить причину голосования против? - person nulll; 13.02.2019
comment
Это нормально работает. Какой смысл давать отрицательный ответ за этот полезный ответ или кто-нибудь может объяснить, что является наилучшей практикой? - person Levent Divilioglu; 01.07.2019
comment
Это то же самое, что git checkout master; git reset --hard A? Или, если нет, не могли бы вы подробнее объяснить, что это делает? - person M.M; 19.11.2019

Вероятно, менее элегантно, чем другие подходы здесь, но я всегда использовал get reset --hard HEAD~N для отмены нескольких коммитов, где N - количество коммитов, которые вы хотите вернуть.

Или, если вы не уверены в точном количестве коммитов, просто запустите git reset --hard HEAD^ (который возвращает одну фиксацию) несколько раз, пока не достигнете желаемого состояния.

person Ian    schedule 20.01.2021

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

A -> B -> C -> D -> HEAD

Чтобы вернуться к A (что на 4 шага назад):

git pull                  # Get latest changes
git reset --soft HEAD~4   # Set back 4 steps
git stash                 # Stash the reset
git pull                  # Go back to head
git stash pop             # Pop the reset 
git commit -m "Revert"    # Commit the changes
person Nebulastic    schedule 30.06.2020

если ты

  1. есть объединенная фиксация и
  2. вы не можете вернуться, и
  3. Вы не против раздавить историю, которую хотите вернуть,

тогда ты можешь

git reset --soft HEAD~(number of commits you'd like to revert)
git commit -m "The stuff you didn't like."
git log
# copy the hash of your last commit
git revert <hash of your last (squashed) commit>

Затем, когда вы хотите отправить свои изменения, не забудьте использовать флаг -f, потому что вы изменили историю

git push <your fork> <your branch> -f
person ScottyBlades    schedule 16.01.2021

Если вы хотите временно отменить коммиты функции, вы можете использовать серию следующих команд.

Вот как это работает

git log --pretty = oneline | grep 'feature_name' | вырезать -d '' -f1 | xargs -n1 git revert --no-edit

person Ajit Singh    schedule 11.02.2016