Повторить несколько git совершает

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

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

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

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

499
задан 23 сент. '09 в 3:27
источник поделиться
11 ответов

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

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

Итак, решение состоит в создании нового комманда, который возвращает изменения, от которых вы хотите избавиться. Вы можете сделать это, используя 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 B ^ - 1, поэтому вы можете получить требуемую ситуацию, используя следующие команды:

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"

Альтернативное решение будет checkout содержимого commit A и зафиксировать это состояние:

$ git checkout -f A -- .
$ git commit -a

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

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

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

Решение Джефф Ферланд, модифицированное Чарльзом Бейли, основывается на той же идее, но использует git reset:

$ git reset --hard A
$ git reset --soft @{1}  # (or ORIG_HEAD), which is D
$ git commit
778
ответ дан 24 сент. '09 в 11:44
источник

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

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

git revert master~3..master

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

A <- B <- C <- D <- BCD' <- HEAD
126
ответ дан 31 июля '12 в 18:00
источник
git reset --hard a
git reset --mixed d
git commit

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

36
ответ дан 23 сент. '09 в 3:45
источник

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

# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD  
$ git commit -m 'message'
34
ответ дан 31 июля '14 в 21:49
источник

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

git diff HEAD commit_sha_you_want_to_revert_to | git apply

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

19
ответ дан 09 сент. '14 в 16:13
источник

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

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

Эта команда возвращает последние 3 коммита с одной фиксацией.

Также не переписывает историю.

12
ответ дан 29 марта '17 в 3:00
источник

Я настолько расстроен, что на этот вопрос нельзя просто ответить. Каждый другой вопрос касается того, как правильно возвращаться и сохранять историю. Этот вопрос гласит: "Я хочу, чтобы глава ветки указывал на 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) и просто запустил базовый script:

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

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

11
ответ дан 12 июля '16 в 2:29
источник

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

Есть два способа сделать это. Если вы хотите, чтобы повторные множественные коммиты в одной фиксации использовали:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $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
4
ответ дан 04 авг. '11 в 14:29
источник

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

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

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

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

(Уверенность интерпретируется как коммит, а не файл, а. ссылается на текущий каталог.)

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

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

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

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

Наконец, завершите реверсию:

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

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

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

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

3
ответ дан 08 нояб. '16 в 9:39
источник

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

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

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

0
ответ дан 24 янв. '17 в 3:28
источник

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

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

git log --pretty = oneline | grep 'feature_name' | cut -d '' -f1 | xargs -n1 git revert --no-edit

-1
ответ дан 11 февр. '16 в 21:47
источник

Другие вопросы по меткам или Задайте вопрос