Как удалить ранее добавленное поддерево git и его историю

Многие луны назад я добавил поддерево в мой репозиторий git. Это поддерево содержало несколько папок и файлов. Я добавил поддерево вместо создания подмодуля (как рекомендовано). Теперь я понимаю, что мне нужен только один из файлов в поддереве и ни один из остальных. Хуже того, когда другие clone мои репозитории, то, что они получают, не то, что ожидается - есть некоторый конфликт с поддеревом и другим кодом, который я создал.

Я могу кататься с файлами/папками с помощью

git rm subtree–folder1 subtree_folder2 subtree_files.*

однако, я все еще остаюсь с длинной историей фиксации из поддерева.

Я потратил много времени на разработку, так как я изначально добавил поддерево и не могу потерять историю фиксации, которую я создал.

Короче говоря, это то, что мне хотелось бы:

  • Удалите все файлы/папки поддерева.
  • Забудьте об истории всех поддеревьев.
  • Остался только мой код и моя история.

Возможно ли это?

PS. Одно из возможных осложнений заключается в том, что я переместил единственный файл заголовка, который я хотел сохранить от поддерева, в какую-то папку в моем коде. Надеюсь, это не то, что мешает мне забыть историю подделок.

Попытка

После новой проверки с удаленного сервера у меня есть следующее:

$ ls
.git             CMakeLists.txt   Read.cpp         logging.conf
.gitignore       ENDF6            TestData         src
.sparse-checkout LICENCE          doc              test
.travis.yml      README.md        include          tools

Где .gitignore имеет только:   строить /   отладки /

Когда я пытаюсь выполнить команду как предложено, я не получаю очень счастливый ответ:

$ git filter-branch --index-filter 'git rm --cached -rf test tools src doc LICENCE README.md .travis.yml' HEAD
Rewrite 2fec85e41e40ae18efd1b130f55b14166a422c7f (1/1701)fatal: pathspec 'test' did not match any files
index filter failed: git rm --cached -rf test tools src doc LICENCE README.md .travis.yml

Я не уверен, почему он говорит, что у него есть проблема с test, когда он явно там. Я озадачен.

Ответ 1

Вам нужно использовать ветвь filter вместе с параметром --prune-empty для удаления любых коммитов, которые больше не вносят новые изменения.

git filter-branch --index-filter 'git rm --cached --ignore-unmatch -rf dir1 dir2 dirN file1 file2 fileN' --prune-empty -f HEAD

После этого, если вы хотите восстановить дисковое пространство, вам нужно будет удалить все исходные ссылки, которые сохраняются в ветки фильтра, истечь reflog и собирать мусор.

Ответ 2

Вы можете использовать git filter-branch для применения операции ко всем фиксациям, сделанным вами в ветке. Это включает удаление файлов из каждой фиксации при перезаписи всей истории. Хорошее описание и инструкции доступны здесь: http://gitready.com/beginner/2009/03/06/ignoring-doesnt-remove-a-file.html. Вы можете найти следующий полезный вопрос: Полностью удалить файлы из Git repo и remote на GitHub (там я нашел ссылку). Фактическая команда, которую вы будете запускать с этим решением, будет похожа на git filter-branch --index-filter 'git rm --cached -rf subtree–folder1 subtree_folder2' HEAD.

Другим способом, который, вероятно, является излишним для того, что вы делаете, является выбор вишни. Черри-выбор позволяет вам переписать любую часть вашей истории, которая вам нравится, с любым уровнем детализации, который вам нравится: http://git-scm.com/docs/git-cherry-pick. Вы захотите сделать что-то вроде git reset --hard <HASH of commit that introduced the subtree>, а затем серию

git cherry-pick -n <following commit hashes>
git reset
git add -p
git commit

для каждого последующего совершенного вами совершения. Это позволит вам удалить поддерево из каждой фиксации, сделанной вами в прошлом. Вы можете обратиться к частично вишневому захвату фиксации с помощью git для получения дополнительной информации об эффективном наборе вишни. Когда вы закончите с этой версией удаления, вы захотите удалить старые коммиты, которые больше не являются частью вашей ветки:

git reflog expire --expire-unreachable=now --all
git gc --prune=now

Другие связанные вопросы: Как переместить ветку назад в git? Список и удаление Git коммитов, которые не имеют ветки (оборван?)