Easy Way ™
Виявляється, це настільки поширена і корисна практика, що владарі Git зробили це дуже просто, але ви повинні мати більш нову версію Git (> = 1.7.11 травня 2012). Дивіться додаток, як встановити останній Git. Крім того , є реальний приклад в покроковому нижче.
Підготуйте старе репо
cd <big-repo>
git subtree split -P <name-of-folder> -b <name-of-new-branch>
Примітка: <name-of-folder>
НЕ повинен містити провідних або кінцевих символів. Наприклад, папку з іменем subproject
ОБОВ'ЯЗКОВО передавати як subproject
, НЕ./subproject/
Примітка для користувачів Windows: Коли глибина вашої папки становить> 1, <name-of-folder>
має бути роздільник папок стилю * nix (/). Наприклад, папку з іменем path1\path2\subproject
ОБОВ'ЯЗКОВО передавати якpath1/path2/subproject
Створіть нове репо
mkdir ~/<new-repo> && cd ~/<new-repo>
git init
git pull </path/to/big-repo> <name-of-new-branch>
Пов’яжіть нове репо в GitHub або куди завгодно
git remote add origin <git@github.com:user/new-repo.git>
git push -u origin master
Очищення всередині <big-repo>
, якщо бажано
git rm -rf <name-of-folder>
Примітка . Це залишає всі історичні посилання у сховищі. Перегляньте Додаток нижче, якщо ви насправді занепокоєні тим, що ввели пароль або вам потрібно зменшити розмір файлу вашої .git
папки.
...
Покрокова інструкція
Це ті ж кроки, що і вище , але слідуючи моїм точним крокам для мого сховища, а не використовувати <meta-named-things>
.
Ось проект, з якого я реалізую модулі браузера JavaScript у вузлі:
tree ~/node-browser-compat
node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator
Я хочу розділити одну папку btoa
в окремий сховище Git
cd ~/node-browser-compat/
git subtree split -P btoa -b btoa-only
Тепер у мене є нова гілка, у btoa-only
якій є лише коміти, btoa
і я хочу створити нове сховище.
mkdir ~/btoa/ && cd ~/btoa/
git init
git pull ~/node-browser-compat btoa-only
Далі я створюю нове репо на GitHub або Bitbucket або будь-якому іншому і додаю його як origin
git remote add origin git@github.com:node-browser-compat/btoa.git
git push -u origin master
Щасливий день!
Примітка. Якщо ви створили репо з a README.md
, .gitignore
і LICENSE
, вам потрібно буде витягнути спочатку:
git pull origin master
git push origin master
Нарешті, я хочу видалити папку з більшого репо
git rm -rf btoa
...
Додаток
Останній Git на macOS
Щоб отримати останню версію Git за допомогою Homebrew :
brew install git
Останній Git на Ubuntu
sudo apt-get update
sudo apt-get install git
git --version
Якщо це не працює (у вас дуже стара версія Ubuntu), спробуйте
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
Якщо це все-таки не працює, спробуйте
sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree
Дякую rui.araujo з коментарів.
Очищення історії
За замовчуванням видалення файлів з Git насправді не видаляє їх, а лише зобов’язується, що їх більше немає. Якщо ви хочете фактично видалити історичні посилання (тобто ви ввели пароль), вам потрібно зробити це:
git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD
Після цього ви можете перевірити, чи ваш файл або папка більше не відображається в історії Git
git log -- <name-of-folder> # should show nothing
Однак ви не можете "проштовхувати" видалення до GitHub тощо. Якщо ви спробуєте, ви отримаєте помилку, і вам доведеться це зробити git pull
до того, як зможете git push
- і тоді ви повернетесь до того, що все у вашій історії.
Тож якщо ви хочете видалити історію з "походження" - це означає, щоб видалити її з GitHub, Bitbucket тощо - вам потрібно буде видалити репо і повторно натиснути обрізану копію репо. Але зачекайте - є ще більше ! - Якщо ви дійсно стурбовані тим, щоб позбутися пароля чи чогось подібного, вам потрібно буде обрізати резервну копію (див. Нижче).
Зробити .git
менше
Вищезгадана команда історії видалення все ще залишає після себе безліч резервних файлів - адже Git дуже добрий, щоб допомогти вам не зіпсувати репортаж випадково. Врешті-решт вони видаляють осиротілі файли протягом днів і місяців, але залишають їх на деякий час, якщо ви зрозумієте, що випадково видалили щось, чого не хотіли.
Отже, якщо ви дійсно хочете спорожнити сміття, щоб зменшити розмір клону РЕПО, вам доведеться зробити все це дуже дивно:
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
З цього приводу я рекомендую не виконувати ці кроки, якщо ви не знаєте, що вам потрібно - про всяк випадок, якщо ви обрізали неправильний підкаталог, знаєте? Файли резервного копіювання не повинні клонуватися, коли ви натискаєте репо, вони просто будуть у вашій локальній копії.
Кредит
git filter-branch
дивіться мою відповідь нижче.