Для импорта старых снимков вы найдете некоторые инструменты в Git's contrib / fast-import каталог полезными. Или, если у вас уже есть каждый старый снимок в каталоге, вы можете сделать что-то вроде этого:
# Assumes the v* glob will sort in the right order
# (i.e. zero padded, fixed width numeric fields)
# For v1, v2, v10, v11, ... you might try:
# v{1..23} (1 through 23)
# v?{,?} (v+one character, then v+two characters)
# v?{,?{,?}} (v+{one,two,three} characters)
# $(ls -v v*) (GNU ls has "version sorting")
# Or, just list them directly: ``for d in foo bar baz quux; do''
(git init import)
for d in v*; do
if mv import/.git "$d/"; then
(cd "$d" && git add --all && git commit -m"pre-Git snapshot $d")
mv "$d/.git" import/
fi
done
(cd import && git checkout HEAD -- .)
Затем загрузите старую историю в ваш рабочий репозиторий:
cd work && git fetch ../import master:old-history
Если у вас есть и старая история, и ваша история на основе Git в одном и том же хранилище, у вас есть пара опций для операции prepend: пересадки и замены.
Трансплантаты - это механизм для каждого репозитория, который (возможно временно) редактирует происхождение различных существующих коммитов. Трансплантаты контролируются файлом $GIT_DIR/info/grafts
(описанным в разделе «информация / трансплантаты» справочной страницы макета репозитория ).
INITIAL_SHA1=$(git rev-list --reverse master | head -1)
TIP_OF_OLD_HISTORY_SHA1=$(git rev-parse old-history)
echo $INITIAL_SHA1 $TIP_OF_OLD_HISTORY_SHA1 >> .git/info/grafts
С трансплантатом на месте (исходный первоначальный коммит не имел родителей, у него был один родитель), вы можете использовать все обычные инструменты Git для поиска и просмотра расширенной истории (например, git log
должен теперь покажу вам старую историю после ваших коммитов).
Основная проблема с трансплантатами заключается в том, что они ограничены вашим хранилищем. Но если вы решите, что они должны быть постоянной частью истории, вы можете использовать git filter-branch , чтобы сделать их такими (сначала сделайте резервную копию tar / zip вашего .git
dir; git filter-branch сохранит исходные ссылки, но иногда проще использовать простую резервную копию).
git filter-branch --tag-name-filter cat -- --all
rm .git/info/grafts
Механизм замены более новый (Git 1.6.5 +), но их можно отключить для каждой команды (git --no-replace-objects …
) и использовать для упрощения совместного использования. Замена работает с отдельными объектами (BLOB-объектами, деревьями, коммитами или аннотированными тегами), поэтому механизм также является более общим. Механизм замены описан в git replace manpage . Из-за общности «предварительная» настройка немного сложнее (нам нужно создать новый коммит, а не просто назвать нового родителя):
# the last commit of old history branch
oldhead=$(git rev-parse --verify old-history)
# the initial commit of current branch
newinit=$(git rev-list master | tail -n 1)
# create a fake commit based on $newinit, but with a parent
# (note: at this point, $oldhead must be a full commit ID)
newfake=$(git cat-file commit "$newinit" \
| sed "/^tree [0-9a-f]\+\$/aparent $oldhead" \
| git hash-object -t commit -w --stdin)
# replace the initial commit with the fake one
git replace -f "$newinit" "$newfake"
Обмен этой заменой не является автоматическим. Вы должны нажать часть (или все) refs/replace
, чтобы поделиться заменой.
git push some-remote 'refs/replace/*'
Если вы решили сделать замену постоянной, используйте git filter-branch (так же, как с трансплантатами; сначала сделайте резервную копию tar / zip для вашего каталога .git
):
git filter-branch --tag-name-filter cat -- --all
git replace -d $INITIAL_SHA1