У меня есть git-репозиторий, который выглядит так:
A -> B -> C -> D -> HEAD
Я хочу, чтобы глава ветви указывал на A, т.е. я хочу, чтобы B, C, D и HEAD исчезали, и я хочу, чтобы head был синонимом A.
Похоже, я могу либо попытаться перебазировать (неприменимо, так как я поместил изменения между ними), либо вернуться. Но как мне отменить несколько коммитов? Вернуть ли мне по одному? Важен ли порядок?
git
commit
git-revert
Билл
источник
источник
git push -f HEAD~4:master
(при условии, что удаленная ветвь - master). Да, вы можете нажать любой коммит как этот.git revert
.Ответы:
Расширяя то, что я написал в комментарии
Общее правило заключается в том, что вы не должны переписывать (изменять) историю, которую вы опубликовали, потому что кто-то мог основывать свою работу на этом. Если вы переписываете (изменяете) историю, у вас возникают проблемы со слиянием их изменений и их обновлением.
Таким образом, решение заключается в создании нового коммита, который отменяет изменения , от которых вы хотите избавиться. Вы можете сделать это с помощью git revert команду .
У вас следующая ситуация:
(здесь стрелки указывают направление указателя: ссылка «родитель» в случае фиксации, верхняя фиксация в случае заголовка ветви (ссылка на ветвь) и имя ветви в случае ссылки на HEAD).
Вам нужно создать следующее:
где «[(BCD) ^ - 1]» означает коммит, который отменяет изменения в коммитах B, C, D. Математика говорит нам, что (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, поэтому Вы можете получить необходимую ситуацию, используя следующие команды:
Альтернативным решением будет извлечение содержимого коммита A и принятие этого состояния:
Тогда у вас будет следующая ситуация:
Коммит А 'имеет то же содержимое, что и коммит А, но это другой коммит (сообщение о коммите, родители, дата коммита).
Решение Джеффа Ферланд, модифицированное Чарльз Бейли основывается на ту же идею, но использует GIT сброс :
источник
git checkout -f A -- .
Они не будут удалены, вам придется сделать это вручную. Я применил эту стратегию сейчас, спасибо Jakubgit checkout foo
может означать ветку извлеченияfoo
(переключиться на ветку) или файл извлечения foo (из индекса).--
используется для устранения неоднозначности, напримерgit checkout -- foo
, всегда о файле.git revert --no-commit D C B
git revert
не принимал несколько коммитов; это довольно новое дополнение.Чистый путь, который я нашел полезным
Эта команда отменяет последние 3 коммита только с одним коммитом.
Также не переписывает историю.
источник
git commit
оттуда будет фактически делать коммит.HEAD~3..
такой же, какHEAD~3..HEAD
Для этого вам просто нужно использовать команду revert , указав диапазон коммитов, которые вы хотите вернуть.
Принимая во внимание ваш пример, вы должны сделать это (при условии, что вы находитесь на ветке 'master'):
Это создаст новый коммит в вашем local с обратным коммитом B, C и D (это означает, что он отменит изменения, внесенные этими коммитами):
источник
git revert --no-commit HEAD~2..
это немного более идиоматический способ сделать это. Если вы находитесь в основной ветке, нет необходимости указывать мастер снова.--no-commit
Опция позволяет GIT попытаться вернуть все коммиты сразу, вместо того , захламление истории с множествомrevert commit ...
сообщений (при условии , что это то , что вы хотите).master~3
.--no-commit
(таким образом, вы получаете отдельный коммит для каждого возврата), а затем раздавить их все вместе в интерактивной перебазировке. Сообщение комбинированной фиксации будет содержать все SHA, и вы можете расположить их так, как вам нравится, с помощью вашего любимого редактора сообщений фиксации.Подобно ответу Якуба, это позволяет вам легко выбирать последовательные коммиты для возврата.
источник
B^..HEAD
, иначе Б исключен.git revert --no-commit B^..HEAD
илиgit revert --no-commit A..HEAD
Это будет действовать как возврат для всех из них одновременно. Дайте хорошее сообщение коммита.
источник
HEAD
выглядеть так,A
он, вероятно, хочет, чтобы индекс соответствовал, поэтомуgit reset --soft D
, вероятно, более уместен.git checkout A
тогдаgit commit
выше не работал для меня, но этот ответ сделал.git reset --mixed D
требуется? Конкретно почемуreset
? Это потому, что без сброса на D HEAD будет указывать на A, в результате чего B, C и D будут «зависать» и собирать мусор - а это не то, что он хочет? Но тогда почему--mixed
? Вы уже ответили: «--soft
сброс не перемещает индекс ...». Таким образом, перемещение индекса означает, что индекс будет содержать изменения D, в то время как рабочий каталог будет содержать изменения A - таким образом, agit status
илиgit diff
(что сравнивает индекс [D] с Рабочий каталог [A]) покажет вещество; что пользователь идет от D обратно к A?Сначала убедитесь, что ваша рабочая копия не изменена. Затем:
а потом просто коммит. Не забудьте документально подтвердить причину возврата.
источник
error: cannot apply binary patch to 'some/image.png' without full index line error: some/image.png: patch does not apply
git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply
git revert A..Z
вы получитеerror: commit X is a merge but no -m option was given.
Я так расстроен, что на этот вопрос нельзя просто ответить. Любой другой вопрос касается того, как правильно вернуться и сохранить историю. Этот вопрос говорит: «Я хочу, чтобы руководитель ветви указывал на A, т.е. я хочу, чтобы B, C, D и HEAD исчезали, и я хочу, чтобы head был синонимом A.»
Я многому научился, читая пост Якуба, но какой-то парень в компании (с доступом к push в нашу «тестирующую» ветку без Pull-Request) выдвинул, как 5 плохих коммитов, пытаясь исправить и исправить ошибку, которую он совершил 5 коммитов назад. Мало того, но были приняты один или два Запроса на подтягивание, которые теперь были плохими. Так что забудьте, я нашел последний хороший коммит (abc1234) и просто запустил базовый скрипт:
Я сказал остальным 5 парням, работающим в этом репо, что они лучше запомнят их изменения за последние несколько часов и Wipe / Re-Branch после последнего тестирования. Конец истории.
источник
git push --force-with-lease
переписать историю только в том случае, если никто не подтвердил ветку после или в пределах диапазона коммитов для испарения. Если другие люди использовали ветку, то ее историю никогда не следует переписывать, а фиксация должна быть просто явно изменена.Это расширение одного из решений, представленных в ответе Якуба.
Я столкнулся с ситуацией, когда коммиты, которые мне нужно было откатить, были несколько сложными, причем некоторые из коммитов были коммитами слияния, и мне нужно было избегать переписывания истории. Я не смог использовать серию
git revert
команд, потому что в итоге столкнулся с конфликтами между добавляемыми изменениями реверсии. Я закончил тем, что использовал следующие шаги.Сначала проверьте содержимое целевого коммита, оставив HEAD на кончике ветки:
(- удостоверяется
<target-commit>
интерпретируется как коммит, а не файл;. Относится к текущему каталогу.)Затем определите, какие файлы были добавлены в откаты коммитов, и, следовательно, должны быть удалены:
Добавленные файлы должны отображаться с буквой «А» в начале строки, и никаких других отличий не должно быть. Теперь, если необходимо удалить какие-либо файлы, подготовьте эти файлы для удаления:
Наконец, совершите реверсию:
При желании убедитесь, что мы вернулись в желаемое состояние:
Там не должно быть никаких различий.
источник
git
ГОЛОВАТЬ только с верхушкой ветви?Простой способ вернуть группу коммитов в общий репозиторий (который используют люди, и вы хотите сохранить историю) - использовать
git revert
в сочетании с gitrev-list
. Последний предоставит вам список коммитов, первый сделает сам возврат.Есть два способа сделать это. Если вы хотите отменить несколько коммитов за один коммит:
это вернет группу коммитов, в которой вы нуждаетесь, но оставьте все изменения в вашем рабочем дереве, вы должны зафиксировать их все как обычно.
Другой вариант - иметь один коммит на одно возвращенное изменение:
Например, если у вас есть дерево коммитов вроде
чтобы отменить изменения от eee до bbb , запустите
источник
Ни один из них не работал для меня, поэтому у меня было три коммита (последние три коммита), поэтому я сделал:
Работал как шарм :)
источник
На мой взгляд, очень простой и чистый способ может быть:
вернуться к
направить голову мастера на текущее состояние
спасти
источник
git checkout master; git reset --hard A
? Или, если нет, не могли бы вы объяснить немного больше о том, что это делает?Если вы хотите временно отменить фиксацию функции, вы можете использовать серию следующих команд.
Вот как это работает
git log --pretty = oneline | grep 'feature_name' | cut -d '' -f1 | xargs -n1 git revert --no-edit
источник