Как удалить конкретную ревизию в истории GIT?

StackOverflow https://stackoverflow.com/questions/37219

  •  09-06-2019
  •  | 
  •  

Вопрос

Предположим, ваша история GIT выглядит так:

1 2 3 4 5

1–5 являются отдельными изменениями. Вам нужно удалить 3, сохраняя при этом 1, 2, 4 и 5. Как это можно сделать?

Есть ли эффективный метод, когда есть сотни пересмотров после удаления?

Это было полезно?

Решение

Чтобы объединить ревизию 3 и 4 в одну ревизию, вы можете использовать git rebase. Если вы хотите удалить изменения в ревизии 3, вам необходимо использовать команду «Редактировать» в режиме интерактивного повторного режима. Если вы хотите объединить изменения в одну ревизию, используйте сквош.

Я успешно использовал эту технику сквоша, но мне никогда не нужно было удалять ревизию раньше. Надеемся, что документация по GIT-Rebase в разделе «разделение коммитов» должна дать вам достаточно идеи, чтобы выяснить это. (Или кто -то еще может знать).

Из GIT документация:

Начните его с самого старого коммита, который вы хотите сохранить как есть:

git rebase -i <after-this-commit>

Редактор будет выпущен со всеми коммитами в вашем нынешнем филиале (игнорируя коммиты Merge), которые приходят после данного коммита. Вы можете переупорядочить коммиты в этом списке до контента вашего сердца, и вы можете удалить их. Список выглядит более или менее похоже на это:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Описания Oneline предназначены исключительно для вашего удовольствия; Git-Rebase не будет смотреть на них, но на имена коммит («Deadbee» и «Fa1afe1» в этом примере), поэтому не удаляйте и не редактируйте имена.

Заменив команду «выбирайте» на команду «редактирование», вы можете сказать Git-Rebase остановиться после применения этого коммита, чтобы вы могли редактировать файлы и/или сообщение о коммите, изменить коммит и продолжать перебазнуть.

Если вы хотите сложить два или более коммита в один, замените команду «выбирать» на «сквош» для второго и последующего коммита. Если у коммитов были разные авторы, это приписывает раздавленную коммитию автору первого коммита.

Другие советы

Вот способ неинтрактативного удаления конкретного <commit-id>, зная только <commit-id> Вы хотели бы удалить:

git rebase --onto <commit-id>^ <commit-id> HEAD

Перемещение этот комментарий (И я проверил, что это правда), ответ Радо очень близок, но оставляет git в отдельном состоянии головы. Вместо этого удалить HEAD и используйте это, чтобы удалить <commit-id> Из ветви вы включено:

git rebase --onto <commit-id>^ <commit-id>

Как отмечалось ранее git-rebase (1) твой друг. Предполагая, что коммиты в вашем master ветвь, вы бы сделали:

git rebase --onto master~3 master~2 master

До:

1---2---3---4---5  master

После:

1---2---4'---5' master

От git-rebase (1):

Ряд коммитов также может быть удален с помощью Rebase. Если у нас есть следующая ситуация:

E---F---G---H---I---J  topicA

тогда команда

git rebase --onto topicA~5 topicA~3 topicA

приведет к удалению коммитов F и G:

E---H'---I'---J'  topicA

Это полезно, если F и G были в некотором роде ошибочны или не должны быть частью топики. Обратите внимание, что аргумент-onto и параметр может быть любым действительным коммитиром.

Если все, что вы хотите сделать, это удалить изменения, внесенные в ревизию 3, вы можете использовать git reverse.

Git revert просто создает новую ревизию с изменениями, которые отменяют все изменения в ревизии, которую вы возвращаете.

Это означает, что вы сохраняете информацию как о нежелательном коммите, так и о коммите, который устраняет эти изменения.

Это, вероятно, намного более дружелюбно, если это вообще возможным, кто -то вытащил из вашего репозитория в то же время, так как возврат в основном является просто стандартным коммитом.

Все ответы до сих пор не решают следующий за проблемой:

Есть ли эффективный метод, когда есть сотни пересмотров после удаления?

Следуют шаги, но для справки, давайте предположим, что следующая история:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

В: Комплект просто следуя за совершением удаления (чисто)

р: Комминер снят

Беременный: Компет, предшествующий совершению, чтобы быть удаленным (база)

Из-за ограничения «сотни пересмотров» я предполагаю следующие предварительные условия:

  1. Есть какой -то неловкий коммит, которого вы не хотите
  2. Существуют нулевые последующие коммиты, которые на самом деле зависят от этого смущающего коммита (нулевые конфликты в возврате)
  3. Вам не все равно, что вы будете перечислены как «комитет» сотен промежуточных коммитов («Автор» будет сохранен)
  4. Вы никогда не разделяли репозиторий
    • Или вы на самом деле имеете достаточное влияние на всех людей, которые когда -либо клонировали историю с этим совершением, чтобы убедить их использовать вашу новую историю
    • а ты не волнует о Переписывание истории

Это довольно ограничительный набор ограничений, но есть интересный ответ, который действительно работает в этом угловом случае.

Вот шаги:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

Если действительно нет конфликтов, то это должно продолжаться без дальнейших перерывов. Если есть конфликты, вы можете их разрешить и rebase --continue или решите просто жить с смущением и rebase --abort.

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

Как вы хотите организовать перевод всех остальных в вашу новую историю, зависит от вас. Вам нужно будет познакомиться с stash, reset --hard, и cherry-pick. Полем И вы можете удалить base, remove-me, и save ветви

Итак, вот сценарий, с которым я столкнулся, и как я его решил.

[branch-a]

[Hundreds of commits] -> [R] -> [I]

здесь R это коммит, который мне нужно было удалить, и I это единственный коммит, который идет после R

Я сделал возвратный коммит и раздавил их вместе

git revert [commit id of R]
git rebase -i HEAD~3

Во время интерактивной перезамачивания сквош последние 2 коммита.

Я также приземлился в аналогичной ситуации. Используйте Interactive Rebase, используя команду ниже и при выборе выбросьте 3 -й коммит.

git rebase -i remote/branch

Ответы Радо и Карима ничего не делают для меня (только сообщение «Текущая ветвь обновлена». Появится). Возможно, это происходит потому, что символ '^' не работает в консоли Windows. Однако, согласно этот Комментарий, замена '^' by '~ 1' решает проблему.

git rebase --onto <commit-id>^ <commit-id>

Чтобы удалить старую историю коммита из Git Repo:

Сначала запустить ниже CMD

rm -rf .git

- воссоздать репо из текущего

git init                                                                           
git add .                                                  
git commit -m "first commit"

- подтолкнуть к удаленным репозициям GitHub

git remote add origin git@github.com<your git mail>   
git push -u --force origin master
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top