Aby to osiągnąć, należy wykonać 2 kroki:
- Utwórz nowy pusty zatwierdzenie
- Przepisz historię, aby zacząć od tego pustego zatwierdzenia
newroot
Dla wygody umieścimy nowy pusty zatwierdzenie w tymczasowej gałęzi .
1. Utwórz nowy pusty zatwierdzenie
Można to zrobić na wiele sposobów.
Używając tylko hydrauliki
Najczystszym podejściem jest użycie hydrauliki Gita do bezpośredniego utworzenia zatwierdzenia, co pozwala uniknąć dotykania kopii roboczej lub indeksu lub gałęzi, która jest pobierana itp.
Utwórz obiekt drzewa dla pustego katalogu:
tree=`git hash-object -wt tree --stdin < /dev/null`
Zawiń wokół niego zatwierdzenie:
commit=`git commit-tree -m 'root commit' $tree`
Utwórz odniesienie do niego:
git branch newroot $commit
Możesz oczywiście przestawić całą procedurę na jednowarstwową, jeśli dobrze znasz swoją powłokę.
Bez kanalizacji
Za pomocą zwykłych poleceń porcelany nie można utworzyć pustego zatwierdzenia bez sprawdzenia newroot
gałęzi i wielokrotnego aktualizowania indeksu i kopii roboczej, bez wyraźnego powodu. Ale niektórym może to być łatwiejsze do zrozumienia:
git checkout --orphan newroot
git rm -rf .
git clean -fd
git commit --allow-empty -m 'root commit'
Zauważ, że w bardzo starych wersjach Gita, które nie mają --orphan
przełącznika na checkout
, musisz zastąpić pierwszy wiersz tym:
git symbolic-ref HEAD refs/heads/newroot
2. Przepisz historię, aby zacząć od tego pustego zatwierdzenia
Masz tutaj dwie opcje: bazowanie lub czyste przepisywanie historii.
Rebasing
git rebase --onto newroot --root master
Ma to zaletę prostoty. Jednak zaktualizuje także nazwę i datę osoby zatwierdzającej przy każdym ostatnim zatwierdzeniu w oddziale.
Ponadto, w przypadku niektórych historii przypadków, może nawet zawieść z powodu konfliktów scalania - pomimo tego, że bazujesz na zatwierdzeniu, które nie zawiera niczego.
Przepisywanie historii
Czystsze podejście polega na przepisaniu gałęzi. W przeciwieństwie do git rebase
, musisz sprawdzić, które zatwierdzenie rozpoczyna się w twoim oddziale:
git replace <currentroot> --graft newroot
git filter-branch master
Oczywiście przepisywanie odbywa się na drugim etapie; to pierwszy krok, który wymaga wyjaśnienia. Co git replace
mówi Git, że ilekroć widzi odniesienie do obiektu, który chcesz zastąpić, Git powinien zamiast tego spojrzeć na zastąpienie tego obiektu.
Za pomocą --graft
przełącznika mówisz mu coś nieco innego niż zwykle. Mówisz, że nie masz jeszcze obiektu zastępującego, ale chcesz zastąpić <currentroot>
obiekt zatwierdzenia jego dokładną kopią, z wyjątkiem tego, że nadrzędne zatwierdzenia zastąpienia powinny być tymi wymienionymi przez Ciebie (tj. newroot
Zatwierdzeniem ). Następnie git replace
idzie do przodu i tworzy to zatwierdzenie dla ciebie, a następnie deklaruje to jako zamiennik oryginalnego zatwierdzenia.
Teraz, jeśli to zrobisz git log
, zobaczysz, że rzeczy już wyglądają tak, jak chcesz: gałąź zaczyna się newroot
.
Należy jednak pamiętać, że git replace
tak naprawdę nie modyfikuje historii - ani nie rozprzestrzenia się poza repozytorium. Po prostu dodaje lokalne przekierowanie do twojego repozytorium z jednego obiektu do drugiego. Oznacza to, że nikt inny nie widzi efektu tej zamiany - tylko ty.
Dlatego ten filter-branch
krok jest konieczny. Po git replace
utworzeniu dokładnej kopii ze skorygowanymi zatwierdzeniami nadrzędnymi dla zatwierdzenia głównego; git filter-branch
następnie powtarza ten proces dla wszystkich następujących zatwierdzeń. Właśnie tam historia jest przepisywana, abyś mógł ją udostępnić.