Как удалить старую историю из репозитория 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
  • принудительное нажатие