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

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

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

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

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

499
задан Bill 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
ответ дан Jakub Narębski 24 сент. '09 в 11:44
источник поделиться

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

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

git revert master~3..master

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

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

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

36
ответ дан Jeff Ferland 23 сент. '09 в 3:45
источник поделиться

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

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

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

git diff HEAD commit_sha_you_want_to_revert_to | git apply

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

19
ответ дан mateusz.fiolka 09 сент. '14 в 16:13
источник поделиться

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

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

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

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

12
ответ дан deepdive 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
ответ дан Suamere 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
ответ дан Ruslan Kabalin 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
ответ дан Warren Dew 08 нояб. '16 в 9:39
источник поделиться

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

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

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

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

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

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

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

-1
ответ дан Ajit Singh 11 февр. '16 в 21:47
источник поделиться

Другие вопросы по меткам