Как удалить конкретную ревизию в истории GIT?
-
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]
В: Комплект просто следуя за совершением удаления (чисто)
р: Комминер снят
Беременный: Компет, предшествующий совершению, чтобы быть удаленным (база)
Из-за ограничения «сотни пересмотров» я предполагаю следующие предварительные условия:
- Есть какой -то неловкий коммит, которого вы не хотите
- Существуют нулевые последующие коммиты, которые на самом деле зависят от этого смущающего коммита (нулевые конфликты в возврате)
- Вам не все равно, что вы будете перечислены как «комитет» сотен промежуточных коммитов («Автор» будет сохранен)
- Вы никогда не разделяли репозиторий
- Или вы на самом деле имеете достаточное влияние на всех людей, которые когда -либо клонировали историю с этим совершением, чтобы убедить их использовать вашу новую историю
- а ты не волнует о Переписывание истории
Это довольно ограничительный набор ограничений, но есть интересный ответ, который действительно работает в этом угловом случае.
Вот шаги:
git branch base B
git branch remove-me R
git branch save
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