Для досягнення цього є два кроки:
- Створіть нову порожню комітку
- Перепишіть історію, щоб почати з цього порожнього комітету
Ми поставимо нову порожню комісію на тимчасову гілку newroot
для зручності.
1. Створіть нову порожню комітку
Існує кілька способів зробити це.
Використовуючи просто сантехніку
Найчистіший підхід полягає у використанні сантехніки Git, щоб просто створити комісію безпосередньо, що дозволяє уникнути торкання робочої копії чи індексу, або якої гілки перевірено тощо.
Створіть об’єкт дерева для порожнього каталогу:
tree=`git hash-object -wt tree --stdin < /dev/null`
Оберніть навколо неї комітку:
commit=`git commit-tree -m 'root commit' $tree`
Створіть посилання на нього:
git branch newroot $commit
Звичайно, ви можете переставити всю процедуру в одношаровий, якщо ви добре знаєте свою оболонку.
Без сантехніки
За допомогою звичайних порцелянових команд ви не можете створити порожню комісію, не перевіряючи newroot
гілку та оновлюючи покажчик та робочу копію повторно, без поважних причин. Але деяким може бути легше зрозуміти:
git checkout --orphan newroot
git rm -rf .
git clean -fd
git commit --allow-empty -m 'root commit'
Зауважте, що для дуже старих версій Git, у яких відсутній --orphan
перехід на checkout
, ви повинні замінити перший рядок цим:
git symbolic-ref HEAD refs/heads/newroot
2. Перепишіть історію, щоб почати з цього порожнього введення
Тут у вас є два варіанти: перезавантаження чи перезапис чистої історії.
Звільнення
git rebase --onto newroot --root master
У цьому є чеснота простоти. Однак він також оновить ім'я та дату виконавця для кожного останнього комітету у філії.
Крім того, за певної історії справ він може навіть вийти з ладу через конфлікти злиття - незважаючи на те, що ви переходите на комісію, яка нічого не містить.
Перепишіть історію
Більш чистий підхід - переписати гілку. На відміну від git rebase
, вам потрібно буде шукати, з яких філій починається ваша філія:
git replace <currentroot> --graft newroot
git filter-branch master
Переписування відбувається, очевидно, на другому кроці; це перший крок, який потребує пояснення. Що git replace
це означає, це говорить Git, що коли він бачить посилання на об'єкт, який ви хочете замінити, Git повинен замість цього шукати заміну цього об’єкта.
За допомогою --graft
перемикача ви говорите це щось дещо інше, ніж зазвичай. Ви говорите, що ще не має об’єкта заміни, але ви хочете замінити <currentroot>
об'єкт фіксації точною копією самого себе, за винятком того, що батьківська комісія заміни повинна бути тією, яку ви вказали (тобто newroot
виконувати ). Тодіgit replace
йде далі і створює цю комісію для вас, а потім оголошує це зобов’язання як заміну оригіналу.
Тепер, якщо ви зробите це git log
, ви побачите, що речі вже виглядають так, як ви їх хочете: гілка починається з newroot
.
Однак зауважте, що git replace
насправді історія не змінюється - і не поширюється з вашого сховища. Він просто додає локальне переспрямування у ваше сховище з одного об'єкта на інший. Це означає, що ніхто не бачить ефекту від цієї заміни - лише ви.
Ось чому filter-branch
крок необхідний. Коли git replace
ви створюєте точну копію з коригуваними батьківськими комітами для кореневої фіксації; git filter-branch
потім повторює цей процес також і для всіх наступних фактів. Саме там історія переписується, щоб ви могли нею поділитися.