Я думаю, что использование git replace
и git filter-branch
является лучшим решением, чем использование git rebase
:
- лучшее исполнение
- проще и менее рискованно (вы можете проверить свой результат на каждом шаге и отменить то, что вы сделали ...)
- хорошо работает с несколькими ветками с гарантированными результатами
Идея заключается в следующем:
- Создать новый пустой коммит далеко в прошлом
- Заменить старый корневой коммит на точно такой же, за исключением того, что новый корневой коммит добавляется как родительский
- Убедитесь, что все в порядке и выполните команду
git filter-branch
- Еще раз проверьте, что все в порядке и очистите ненужные файлы git.
Вот скрипт для 2 первых шагов:
#!/bin/bash
root_commit_sha=$(git rev-list --max-parents=0 HEAD)
git checkout --force --orphan new-root
find . -path ./.git -prune -o -exec rm -rf {} \; 2> /dev/null
git add -A
GIT_COMMITTER_DATE="2000-01-01T12:00:00" git commit --date==2000-01-01T12:00:00 --allow-empty -m "empty root commit"
new_root_commit_sha=$(git rev-parse HEAD)
echo "The commit '$new_root_commit_sha' will be added before existing root commit '$root_commit_sha'..."
parent="parent $new_root_commit_sha"
replacement_commit=$(
git cat-file commit $root_commit_sha | sed "s/author/$parent\nauthor/" |
git hash-object -t commit -w --stdin
) || return 3
git replace "$root_commit_sha" "$replacement_commit"
Вы можете запустить этот сценарий без риска (даже если создание резервной копии перед выполнением действия, которое вы никогда не делали ранее, является хорошей идеей;)), и если результат не тот, который ожидается, просто удалите файлы, созданные в папке .git/refs/replace
и попробуйте еще раз;)
Убедившись, что состояние хранилища соответствует ожидаемому, выполните следующую команду, чтобы обновить историю всех ветвей :
git filter-branch -- --all
Теперь вы должны увидеть 2 истории: старую и новую (дополнительную информацию см. В справке по filter-branch
). Вы можете сравнить 2 и еще раз проверить, все ли в порядке. Если вы удовлетворены, удалите ненужные файлы:
rm -rf ./.git/refs/original
rm -rf ./.git/refs/replace
Вы можете вернуться в ветку master
и удалить временную ветку:
git checkout master
git branch -D new-root
Теперь все должно быть сделано;)