Как удалить старую историю из репозитория git?
Боюсь, я не мог найти ничего похожего на этот конкретный сценарий.
У меня есть репозиторий git с большой историей: 500+ веток, более 500 тегов, начиная с середины 2007 года. Он содержит ~ 19 500 коммитов. Мы хотели бы удалить всю историю до 1 января 2010 года, чтобы сделать ее более легкой и простой в использовании (мы сохранили бы полную копию истории в архиве).
Я знаю коммит, который я хочу стать корнем нового репозитория. Я не могу, однако, выяснить правильный git mojo, чтобы урезать репо, чтобы начать с этой фиксации. Я предполагаю некоторый вариант
git filter-branch
с участием трансплантатов; также может потребоваться обработать каждый из 200 + веток, которые мы хотим сохранить отдельно, а затем снова скопировать репо (что-то, что я знаю, как это сделать).
Кто-нибудь когда-нибудь делал что-то подобное? У меня есть git 1.7.2.3, если это имеет значение.
Ответы
Ответ 1
Просто создайте graft родителя вашего нового корневого коммита без родителя (или пустого коммита, например реального корня фиксация вашего репозитория). Например. echo "<NEW-ROOT-SHA1>" > .git/info/grafts
После создания трансплантата он сразу же вступает в силу; вы должны иметь возможность смотреть git log
и видеть, что нежелательные старые коммиты исчезли:
$ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts
$ git log --decorate | tail --lines=11
commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c
Author: Your Name <[email protected]>
Date: Fri May 24 14:04:10 2013 +0200
Another message
commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted)
Author: Your Name <[email protected]>
Date: Thu May 23 22:27:48 2013 +0200
Some message
Если все выглядит так, как нужно, вы можете просто сделать простой git filter-branch -- --all
, чтобы сделать его постоянным.
BEWARE: после выполнения этапа ветвления фильтра, все идентификаторы commit будут изменены, поэтому любой, кто использует старое репо, никогда не должен сливаться с кем-либо, использующим новое репо.
Ответ 2
Этот метод легко понять и отлично работает. Аргумент script ($1
) является ссылкой (tag, hash,...) на фиксацию, начиная с которой вы хотите сохранить свою историю.
#!/bin/bash
git checkout --orphan temp $1 # create a new branch without parent history
git commit -m "Truncated history" # create a first commit on this branch
git rebase --onto temp $1 master # now rebase the part of master branch that we want to keep onto this branch
git branch -D temp # delete the temp branch
# The following 2 commands are optional - they keep your git repo in good shape.
git prune --progress # delete all the objects w/o references
git gc --aggressive # aggressively collect garbage; may take a lot of time on large repos
ПРИМЕЧАНИЕ, что старые теги будут по-прежнему оставаться; поэтому вам может потребоваться удалить их вручную.
: Я знаю, что это почти то же самое, что и @yoyodin, но здесь есть некоторые важные дополнительные команды и информация. Я попытался отредактировать ответ, но поскольку это существенное изменение в ответе @yoyodin, мое редактирование было отклонено, поэтому здесь информация!
Ответ 3
Попробуйте этот метод Как обрезать git историю:
#!/bin/bash
git checkout --orphan temp $1
git commit -m "Truncated history"
git rebase --onto temp $1 master
git branch -D temp
Здесь $1
есть SHA-1 комманды, который вы хотите сохранить, и script создаст новую ветку, содержащую все фиксации между $1
и master
, и вся старая история будет удалена. Обратите внимание, что этот простой script предполагает, что у вас нет существующей ветки под названием temp
. Также обратите внимание, что этот script не очищает данные git для старой истории. Запустите git gc --prune=all && git repack -a -f -F -d
после того, как вы подтвердите, что действительно хотите потерять всю историю. Вам также может понадобиться rebase --preserve-merges
, но следует предупредить, что реализация этой функции git не идеальна. Если вы используете это, просмотрите результаты вручную.
Ответ 4
Может быть, слишком поздно, чтобы опубликовать ответ, но поскольку эта страница является первым результатом Google, она может быть полезной.
Если вы хотите освободить место в своем репозитории git, но не хотите перестраивать все свои коммиты (переадресацию или трансплантацию) и все еще иметь возможность нажать/вытащить/слить из людей, у которых есть полное репо, вы можете использовать git клон мелкий клон (параметр -depth).
; Clone the original repo into limitedRepo
git clone file:///path_to/originalRepo limitedRepo --depth=10
; Remove the original repo, to free up some space
rm -rf originalRepo
cd originalRepo
git remote rm origin
Возможно, вы сможете ограничить свое существующее репо, выполнив следующие шаги:
; Shallow to last 5 commits
git rev-parse HEAD~5 > .git/shallow
; Manually remove all other branches, tags and remotes that refers to old commits
; Prune unreachable objects
git fsck --unreachable ; Will show you the list of what will be deleted
git gc --prune=now ; Will actually delete your data
Ps: Старые версии git не поддерживали клон /push/pull из/в мелкие репозитории.
Ответ 5
В качестве альтернативы переписыванию истории рассмотрите возможность использования git replace
, как в эту статью из книги Pro Git. В рассмотренном примере предусматривается замена родительского коммита для имитации начала дерева, сохраняя при этом всю историю как отдельную ветвь для сохранения.
Ответ 6
Если вы хотите сохранить репозиторий вверх по течению с полной историей, но локальные небольшие проверки, сделайте мелкий клон с git clone --depth=1 [repo]
.
После нажатия фиксации вы можете сделать
-
git fetch --depth=1
, чтобы обрезать старые коммиты. Это делает старые коммиты и их объекты недоступными.
-
git reflog expire --expire-unreachable=now --all
. Для истечения срока действия всех старых коммитов и их объектов
-
git gc --aggressive --prune=all
для удаления старых объектов
См. также Как удалить локальную историю git после фиксации?.
Обратите внимание, что вы не можете вытащить этот "мелкий" репозиторий в другое место: "мелкое обновление не разрешено". См. Удаленное отклонение (неглубокое обновление не разрешено) после изменения git удаленного URL. Если вы хотите этого, вы должны придерживаться прививки.
Ответ 7
Мне нужно было прочитать несколько ответов и другую информацию, чтобы понять, что я делаю.
1. Игнорировать все, что было раньше, чем определенная фиксация
Файл .git/info/grafts
может определять поддельные родители для фиксации. Строка с только идентификатором фиксации говорит, что у коммита нет родителя. Если бы мы хотели сказать, что мы заботимся только о последних коммитах за 2000 год, мы можем ввести:
git rev-parse HEAD~2000 > .git/info/grafts
git rev-parse дает нам идентификатор фиксации 2000-го родителя текущей фиксации. Вышеприведенная команда перезапишет файл графтов, если он есть. Проверьте его там.
2. Перепишите историю Git (необязательно)
Если вы хотите сделать этот привитый поддельный родитель реальным, запустите:
git filter-branch -- --all
Он изменит все идентификаторы фиксации. Каждая копия этого репозитория должна быть обновлена решительно.
3. Очистка дискового пространства
Я не делал шаг 3. Я хотел, чтобы моя копия оставалась совместимой с восходящим потоком. Я просто хотел сохранить дисковое пространство. Чтобы забыть все старые коммиты:
git prune
git gc
Альтернатива: мелкие копии
Если у вас есть мелкая копия другого репозитория и вы хотите сохранить некоторое дисковое пространство, вы можете обновить .git/shallow
. Но будьте осторожны, чтобы ничто не указывало на фиксацию ранее. Таким образом, вы можете запустить что-то вроде этого:
git fetch --prune
git rev-parse HEAD~2000 > .git/shallow
git prune
git gc
Вход в мелкие работы, такие как трансплантат. Но будьте осторожны, чтобы не использовать трансплантаты и мелкие в то же время. По крайней мере, у них нет одинаковых записей, это не сработает.
Если у вас все еще есть старые ссылки (теги, ветки, удаленные главы), которые указывают на более старые коммиты, они не будут очищены, и вы не сохраните больше места на диске.
Ответ 8
Если переформатировать или нажмите на головка/мастер, эта ошибка может возникнуть
remote: GitLab: You are not allowed to access some of the refs!
To [email protected]:main/xyz.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '[email protected]:main/xyz.git'
Чтобы устранить эту проблему в git, панель управления должна удалить главную ветку из "Защищенные ветки"
то вы можете запустить эту команду
git push -f origin master
или
git rebase --onto temp $1 master
Ответ 9
вы можете удалить каталог, файлы, а также всю историю, связанную с файлом или файлом, используя приведенную ниже jar [загрузить] и команды
Файл bfg.jar:
https://rtyley.github.io/bfg-repo-cleaner/
git клон - репозиторий
cd repo_dir
java -jar bfg.jar --delete-folders имя_папки
git reflog expire --expire = now - all && & git gc --prune = now - агрессивный
git push --mirror repo_url
Ответ 10
- удалить git данные, rm.git
- git init
- добавить git remote
- принудительное нажатие