Як видалити підмодуль?


3539

Як видалити підмодуль Git?

До речі, чи є причина, яку я не можу просто зробити git submodule rm whatever?


109
Проста відповідь stackoverflow.com/a/21211232/94687 тепер правильна, і повинна бути позначена так. Тепер просто git rm modulenameіrm -rf .git/modules/modulename
імз - Іван Захарящев

10
Це насправді не так. Ця відповідь не стосується видалення запису з підмодуля .git/config. Прийнята відповідь показує сучасний спосіб повного видалення підмодуля aa. Це також пояснюється більш стисло в цій відповіді: stackoverflow.com/a/36593218/1562138
fvgs

Я знайшов цю статтю дуже корисною для видалення субмодулів. Вона включає в себе інформацію про видалення запису в .gitsubmodules і .git / файли конфігурації посилаються
RI_

12
Заощадьте собі час і безпосередньо перейдіть до відповіді, яка працює (у 2017 році): stackoverflow.com/a/36593218/528313
Vincenzo Pii

Я боровся з проблемами субмодулю протягом двох днів. Прорив стався, коли я виявив це: forums.developer.apple.com/thread/13102 . В основному, Xcode і, можливо, інші програми намагаються розширити URL-адресу, що містить '~'. Як тільки я змінив ssh: //username@server.remoteHost.com/~/git/MyRepo.git на ssh: //username@server.remoteHost.com/home/username/git/MyRepo.git (шукати фактичний шлях на вашому сервері) вся дивацтво зникла за десять хвилин. Дивіться також stackoverflow.com/questions/32833100 / ...
Elise ван Looij

Відповіді:


2213

З моменту git1.8.3 (22 квітня 2013 року) :

Не було жодного способу порцеляни сказати "Мене вже не цікавить цей підмодуль", як тільки ви висловите свою зацікавленість підмодулем за допомогою " submodule init".
" submodule deinit" це спосіб зробити це.

Також використовується процес видалення git rm(з git1.8.5 жовтня 2013 р.).

Підсумок

Процес видалення в 3 кроки буде таким:

0. mv a/submodule a/submodule_tmp

1. git submodule deinit -f -- a/submodule    
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)

# or, if you want to leave it in your working tree and have done step 0
3.   git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule

Пояснення

rm -rf: Про це йдеться в Деніела Шредера «S відповідь , і підсумовані Eonil в коментарі :

Це залишається .git/modules/<path-to-submodule>/незмінним.
Тож якщо ви один раз видалите підмодуль за допомогою цього методу та повторно додасте їх знову, це буде неможливо, оскільки сховище вже було пошкоджено.


git rm: Див. Запис 95c16418 :

В даний час використання git rmпідмодуля " " видаляє робоче дерево субмодуля з дерева надпроекту та посилання з індексу.
Але розділ підмодулю в .gitmodulesзалишився недоторканим, що є залишком вже видаленого підмодуля і може дратувати користувачів (на відміну від налаштування в .git/configцьому, це повинно залишатися нагадуванням про те, що користувач виявив інтерес до цього підмодулю, тому він буде переповнений пізніше коли перевіряється старіша комісія).

Дозвольте " git rm" допомогти користувачеві, не тільки видаливши підмодуль з робочого дерева, але також видаливши submodule.<submodule name>розділ з " " .gitmodulesфайлу та поставивши обидва.


git submodule deinit: Це походить від цього виправлення :

З " git submodule init" користувач може сказати git, що вони піклуються про один або декілька підмодулів і хоче, щоб він був заповнений під час наступного дзвінка до " git submodule update".
Але в даний час не існує простого способу, щоб вони могли сказати git, що вони вже не піклуються про підмодуль і хочуть позбутися місцевого робочого дерева (якщо користувач не знає багато про внутрішні підмодулі та не видаляє налаштування " submodule.$name.url" .git/configразом із роботою саме дерево).

Допоможіть цим користувачам, надавши deinitкоманду " ".
Це видаляє весь submodule.<name>розділ .git/configабо для заданого підмодуля (або) для всіх, які були ініціалізовані, якщо ' .' задано).
Збій, якщо поточне робоче дерево містить зміни, якщо їх не вимушено.
Поскаржись, коли для підмодуля, вказаного в командному рядку, параметр URL не може бути знайдений .git/config, але, тим не менш, не виходить з ладу.

Це враховує, якщо кроки ( .git/configі .git/modules/xxx) ініціалізації ( і )

З git1.8.5 року git rmзаймає також турбота про:

  • « add» Крок , який записує URL в подмодуль в .gitmodulesфайлі: воно необхідне зняти для вас.
  • спеціальний запис підмодуля (як проілюстровано цим запитанням ): git rm видаляє його з індексу:
    git rm --cached path_to_submodule(відсутній кінець косої риси),
    що видалить цей каталог, що зберігається в індексі, у спеціальному режимі "160000", позначивши його як кореневий каталог підмодуля .

Якщо ви забудете цей останній крок і спробуйте додати те, що було підмодулем як звичайний каталог, ви отримаєте повідомлення про помилку на зразок:

git add mysubmodule/file.txt 
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'

Примітка: оскільки Git 2.17 (Q2 2018), git субмодуль deinit вже не є сценарієм оболонки.
Це дзвінок до функції С.

Див. Команду 2e61273 , фіксуйте 1342476 (14 січня 2018 р.) Пратхамеш Чаван ( pratham-pc) .
(Об’єднав Хуніо С Хамано - gitster- в комітеті ead8dbe , 13 лютого 2018 р.)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "$@"

18
Чи можете ви навести приклад використання submodule deinit?
zakdances

5
@yourfriendzak ось один із прикладів успішного використання ним: stackoverflow.com/a/16161950/6309 . Але майте на увазі, що всупереч тому, що я спочатку вважав, 1.8.3 ще не випущено! У Unix ви можете зібрати його з джерел.
VonC

2
@HamishDowner спеціального запису не повинно бути (каталог більше не є підмодулем), і це .gitmodulesповинно бути нормально, але я все одно ще раз перевірте що-небудь із .gitкаталогом (тобто локальним конфігуратором, у вашому локальному репо: це не так змінено а git pull)
VonC

2
@Jayen так, якщо ви скористаєтеся видаленням .gitmodulesзапису та видаленням спеціального запису в індексі та натисніть це репо, інші можуть витягнути його, і цей підмодуль вже не буде.
VonC

3
У поточному git (v1.9 +) звичайний старий git rm submoduleробить саме те, що ви хочете, як уже говорили інші.
Піт Петерсон

3445

Через сторінку Підручник Git Submodule :

Щоб видалити підмодуль, потрібно:

  1. Видаліть відповідний розділ з .gitmodulesфайлу.
  2. Етап .gitmodulesзмін:
    git add .gitmodules
  3. Видаліть відповідний розділ із .git/config.
  4. Видаліть файли підмодулю з робочого дерева та індексу:
    git rm --cached path_to_submodule(відсутній кінець косої риски)
  5. Видаліть .gitкаталог підмодуля :
    rm -rf .git/modules/path_to_submodule
  6. Внести зміни:
    git commit -m "Removed submodule <name>"
  7. Видаліть не відстежені файли підмодулю:
    rm -rf path_to_submodule

Дивіться також : альтернативні кроки нижче .


410
"І, до речі, чи є причина, що я не можу просто зібрати підмодуль rm?" ?
аберньє

48
@abernier Справжня відповідь могла бути "тому що такої команди не існує". Я здогадуюсь, що вони намагаються зробити видалення файлів субмодулів та конфігурації субмодулів явними, щоб уникнути випадкової втрати даних. Можливо, одна людина подумає, що git submodule rmпросто видаляє реєстрацію підмодуля, і здивується, якщо команда також видалить локальний сховище. Будь-які локальні зміни будуть безповоротно втрачені. І, можливо, інша людина подумає, що видаляються лише файли.
Джон Даут,

119
Чесно кажучи, я не знаю чому. Я сподіваюся, що вони додають команду. Ці 4 кроки занадто складні.
Джон Даут,

25
Ось bash-скрипт, який видаляє підмодуль, просто створіть псевдонім git для підмодуля-rm;) gist.github.com/2491147
Capi Etheriel

33
також потрібні rm -rf .git \ module \ ім'я підмодуля?
rogerdpack

484

Просто записка. Оскільки git 1.8.5.2, дві команди будуть виконувати:

git rm the_submodule
rm -rf .git/modules/the_submodule

Як правильно вказала відповідь @Mark Cheverton, якщо другий рядок не використовується, навіть якщо ви зараз видалили підмодуль, залишок .git / module / the_submodule папка запобіжить тому, щоб той самий підмодуль не був доданий назад або замінений у майбутньому . Також, як згадував @VonC, git rmбільшу частину роботи буде виконано в підмодулі.

--Оновлення (05.07.2017) -

Просто для уточнення, the_submoduleчи відносний шлях підмодулю всередині проекту. Наприклад, це subdir/my_submoduleякщо підмодуль знаходиться всередині підкаталогу subdir.

Як правильно вказано в коментарях та інших відповідях , дві команди (хоча функціонально достатньо для видалення підмодуля) залишають слід у [submodule "the_submodule"]розділі .git/config(станом на липень 2017 року), який можна видалити за допомогою третьої команди:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null

5
Я перебуваю на git версії 2.4.9 (Apple Git-60), і все, що мені потрібно було зробити, це rm the_submodule. Я натиснув, що потім повторно додав папку, названу так само, як підмодуль, і вона працювала без проблем.
Девід Сільва Сміт

19
Це не видаляє запис субмодулю з .git/config. Дивіться stackoverflow.com/a/36593218/1562138 про повний спосіб видалення підмодуля.
fvgs

2
@drevicko Я щойно перевірив це за допомогою Git 2.11.1 і спостерігаю ту ж поведінку, що і раніше. git init && git submodule add <repository> && git rm <name>залишає після себе .git/configзапис і .git/modules/<name>каталог та його вміст. Можливо, ви не ініціалізували підмодуль перед його видаленням?
fvgs

2
я відчуваю себе безпечнішим запускати цей перший .. git submodule deinit -f the_submodule
danday74

1
@JarrodSmith Так, це шлях. будь ласка, дивіться оновлення.
тинлікс

478

Більшість відповідей на це питання є застарілими, неповними або надмірно складними.

Підмодуль, клонований за допомогою git 1.7.8 або новіших, залишить не більше чотирьох слідів у вашому місцевому репо. Процес видалення цих чотирьох слідів задано трьома командами нижче:

# Remove the submodule entry from .git/config
git submodule deinit -f path/to/submodule

# Remove the submodule directory from the superproject's .git/modules directory
rm -rf .git/modules/path/to/submodule

# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule
git rm -f path/to/submodule

39
Чому ця відповідь має так мало відгуків? Усі ці популярні відповіді щось пропускають, це єдиний, який справді видаляє всі сліди підмодуля найпростішим можливим способом. І зверніть увагу: порядок команд має значення.
mbdevpl

2
Щоб відповісти на моє власне запитання: stackoverflow.com/questions/97875/rm-rf-equivalent-for-windows
Томас

5
@mbdevpl прийшов через 3 роки після прийнятої відповіді, і я думаю, нікому не вдалося переконати ОП прийняти цю
Енді

10
ЦЕ не найскладніша відповідь у 2018 році?
Warren P

9
.gitmodules файл по- , як і раніше здається , не впливає виконання цих команд
Fractalf

206

Прості кроки

  1. Видалити записи конфігурації:
    git config -f .git/config --remove-section submodule.$submodulename
    git config -f .gitmodules --remove-section submodule.$submodulename
  2. Видалити каталог з індексу:
    git rm --cached $submodulepath
  3. Здійснити
  4. Видаліть невикористані файли:
    rm -rf $submodulepath
    rm -rf .git/modules/$submodulename

Зверніть увагу: $submodulepath не містить провідної чи зворотної косої риски.

Фон

Коли ви це робите git submodule add, він додає його лише до цього .gitmodules, але колись ви це зробили git submodule init, додавали до .git/config.

Тож якщо ви хочете видалити модулі, але зможете швидко відновити їх, зробіть саме це:

git rm --cached $submodulepath
git config -f .git/config --remove-section submodule.$submodulepath

Це добре зробити git rebase HEADспочатку і git commit в кінці, якщо ви це помістите в сценарій.

Подивіться також відповідь на те, чи можу я розселити підмодуль Git? .


1
У мене було багато підмодулів (і більший безлад), тому мені довелося пропустити їх через цикл for. Оскільки більшість з них, де під певним каталогом та ls-виведенням міститься кінці косої риски. Я щось подібне зробив for dir in directory/*; do git rm --cached $dir; done.
Пабло Олмос де Агілера C.

Щоб отримати це, список, який може бути використаний у скрипті для рекурсивного видалення - git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'- - виглядає так, що вам потрібно це зробити дійсно в тому випадку, якщо щось зіпсовано, інакше простоgit submodule | grep -v '^+' | cut -d' ' -f3
errordeveloper

2
щоб отримати список модулів, де не було внесено локальних змін -git submodule | grep '^+' | cut -d' ' -f2
errordeveloper

Зауважте, мені довелося включити submodulenameв подвійні лапки "submodulename".. з посиланням на .git/configфайл
muon

Простий. Ефективний. У 2.25.0, після кроку 1, вам потрібно поетапно змінити .gitmodules перед етапом 2.
Мішель Донай

83

Окрім рекомендацій, мені також довелося rm -Rf .git/modules/path/to/submoduleдодати новий підмодуль з такою ж назвою (у моєму випадку я замінював виделку на оригінал)


1
У мене також були проблеми з цим. Якщо ви спробуєте перевстановити підмодуль на той самий шлях, він зберігає кешовану інформацію про гілку у вказаному вами місці, яке змінює речі.
jangosteve

Спасибі, мені це теж було потрібно. @Anton, я згоден, і я відредагував відповідну відповідь, щоб додати цю інформацію.
Вільям Денніс

Я використовував --name можливість зробити заміну роботи ... см stackoverflow.com/questions/14404704 / ...
joseph.hainline

60

Щоб видалити доданий підмодуль за допомогою:

git submodule add blah@blah.com:repos/blah.git lib/blah

Виконати:

git rm lib/blah

Це воно.

Для старих версій git (приблизно ~ 1.8.5) використовуйте:

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah

1
+1 дійсно. Це єдина правильна відповідь від git 1.8.3 і далі. Слід визнати правильним.
Xananax

6
git rmяк і раніше залишає речі .git/modules/. (2.5.4)
Рудольф Адамкович

1
@RudolfAdamkovic це працює для мене? Зауважте, що він видаляє запис субмодулю лише у тому випадку, якщо відповідає точний шлях; якщо ви перемістили підмодуль, а потім не використовуєте git rmйого; Швидкий тест з 2.5.4 на моєму mac оновлює файл .gitmodules, як описано в документації тут: git-scm.com/docs/git-rm#_submodules ... але якщо ви знайшли якусь комбінацію платформи / версія, де цього не відбувається, ви, ймовірно, мусите про це помилку.
Даг

2
Ця відповідь не зовсім правильна. git rmзалишає матеріал у .git/modules/dir та .git/configfile (ubuntu, git 2.7.4). Інший відповідь працює на 100%: stackoverflow.com/a/36593218/4973698
mbdevpl

50

Ви повинні видалити запис в .gitmodulesі .git/configта вилучити каталог модуля з історії:

git rm --cached path/to/submodule

Якщо ви напишете у списку розсилки git, можливо, хтось зробить сценарій оболонки для вас.


Там немає необхідності для будь-якого сценарію оболонки, інший відповіді є команди для видалення всіх слідів підмодуля: stackoverflow.com/a/36593218/4973698
mbdevpl

42

Ви можете використовувати псевдонім для автоматизації рішень, наданих іншими:

[alias]
  rms = "!f(){ git rm --cached \"$1\";rm -r \"$1\";git config -f .gitmodules --remove-section \"submodule.$1\";git config -f .git/config --remove-section \"submodule.$1\";git add .gitmodules; }; f"

Помістіть це у свій git config, і тоді ви можете зробити: git rms path/to/submodule


-1 оскільки це очевидно занадто неправильно. ПЕРШЕ: Це передбачає, що ім'я та шлях підмодуля однакові, що найчастіше не так . IE git clone https://github.com/hilbix/empty.git; cd empty; git submodule add https://github.com/hilbix/empty.git one; git mv one two; git rms two. ДРУГО: Ви повинні виконати це з правильного шляху. gitпсевдоніми повинні працювати в будь-якому місці робочого дерева (або виходити витончено). ТРЕТИЙ: git config -f .git/configне працює в підмодулях, як .gitзазвичай це файл.
Тіно

42

Підсумовуючи це, ви повинні зробити:

  1. Встановити path_to_submodulevar (без останньої косої риски):

    path_to_submodule=path/to/submodule

  2. Видаліть відповідний рядок із файлу .gitmodules:

    git config -f .gitmodules --remove-section submodule.$path_to_submodule

  3. Видаліть відповідний розділ із .git / config

    git config -f .git/config --remove-section submodule.$path_to_submodule

  4. Видаліть та видаліть $ path_to_submodule лише з індексу (щоб запобігти втраті інформації)

    git rm --cached $path_to_submodule

  5. Відстежуйте зміни, внесені до .gitmodules

    git add .gitmodules

  6. Здійсніть суперпроект

    git commit -m "Remove submodule submodule_name"

  7. Видаліть не відстежені файли підмодуля

    rm -rf $path_to_submodule

    rm -rf .git/modules/$path_to_submodule


тому всі інші, хто зніме мою зміну, повинні буде запустити rm -rf $ path_to_submodule rm -rf .git / module / $ path_to_submodule, щоб видалити кеш підмодуля?
j2emanue

Рекомендую оновити, git submodule update . І якщо шляхи субмодулів не були оновлені правильно (git кидає помилку), видаліть їх:rm -rf .git/modules/<submodule> && rm -rf <submodule> && git submodule update
luissquall

40

Якщо підмодуль був випадково доданий через те, що ви додали, зробили та натиснули папку, яка вже була сховищем Git (містилася .git), у вас не буде .gitmodulesфайлу для редагування чи нічого в цьому .git/config. У цьому випадку все, що вам потрібно, це:

git rm --cached subfolder
git add subfolder
git commit -m "Enter message here"
git push

FWIW , я також видалив .gitпапку перед тим, як робити git add.


саме мій випадок
zhekaus

37

Я виявив, що deinitдля мене це добре:

git submodule deinit <submodule-name>    
git rm <submodule-name>

З git docs :

deinit

Скасуйте дані підмодулі, тобто видаліть з submodule.$name розділу .git / config весь розділ разом із їх робочим деревом.


Погодьтеся, знайшли таке саме рішення. Це найкращий спосіб сьогодні в 2018 році)
woto

1
він не видалив .git / модулі / .. Ви повинні їх видалити, дивіться відповідь @fvgs
Vilém Kurz

Не знаєте, чому це просте та легке рішення - не номер 1
Марк Магон

AFAICS, здається, це найбезпечніша відповідь для новіших git, хто знає про це deinit, оскільки інша відповідь видаляє .git/modules/submoduleкаталог занадто рано, що, здається, змушує нові gitчи інші ламати зараз чи потім. Також (див. Мій коментар там) видалення .git/modules/submoduleможе бути неправильним шляхом, тому це небезпечний крок, найкраще вжити пізніше лише тоді, коли gitскаржиться (або якщо ви на 299% впевнені, що це те, що ви хочете, це правильний шлях і справді потрібен).
Тіно

Мені також потрібно git commitбуло здійснити поетапні зміни в робочому режимі: modified .gitmodulesі deleted <submodule-path>.
Юрій Позняк

20

Після експерименту з усіма різними відповідями на цьому веб-сайті я закінчив це рішення:

#!/bin/sh
path="$1"
if [ ! -f "$path/.git" ]; then
  echo "$path is no valid git submodule"
  exit 1
fi
git submodule deinit -f $path &&
git rm --cached $path &&
rm -rf .git/modules/$path &&
rm -rf $path &&
git reset HEAD .gitmodules &&
git config -f .gitmodules --remove-section submodule.$path

Це відновлює той самий стан, що і до того, як ви додали підмодуль. Ви можете одразу додати підмодуль ще раз, що було неможливим із більшості відповідей тут.

git submodule add $giturl test
aboveScript test

Це дозволяє вам отримати чистий замовлення без змін.

Це було протестовано за допомогою:

$ git --version
git version 1.9.3 (Apple Git-50)

Чому ви використовуєте git rm --cached $pathтоді rm -rf $pathзамість git rm -r $path?
bfontaine

-1 Не працює, якщо ви намагаєтесь видалити підмодуль в межах підмодуля (підмодуль може утворювати дерева!). Також це небезпечно баггі через відсутність котирування! Приклад git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'-> коли ви намагаєтесь видалити "небезпечний .. підмодуль" зі своїм сценарієм, це, rm -rf ..швидше за все, не те, що ви хочете ..
Tino

17

Що я зараз роблю в грудні 2012 року (поєднує більшість цих відповідей):

oldPath="vendor/example"
git config -f .git/config --remove-section "submodule.${oldPath}"
git config -f .gitmodules --remove-section "submodule.${oldPath}"
git rm --cached "${oldPath}"
rm -rf "${oldPath}"              ## remove src (optional)
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (optional housekeeping)
git add .gitmodules
git commit -m "Removed ${oldPath}"

15

Ось що я зробив:

1.) Видаліть відповідний розділ з файлу .gitmodules. Ви можете використовувати команду нижче:

git config -f .gitmodules --remove-section "submodule.submodule_name"

2.) Постановка .gitmodulesзмін

git add .gitmodules

3.) Видаліть відповідний розділ із .git/config. Ви можете використовувати команду нижче:

git submodule deinit -f "submodule_name"

4.) Видаліть посилання (без кінцевої косої риски):

git rm --cached path_to_submodule

5.) Очищення .git/modules:

rm -rf .git/modules/path_to_submodule

6.) Здійснити:

git commit -m "Removed submodule <name>"

7.) Видаліть не відстежені файли підмодуля

rm -rf path_to_submodule

Дякую за це Для мене мені довелося переставити наказ перших трьох кроків на 3), 1), 2). Робити 1) спочатку дали fatal: no submodule mapping found in .gitmodules for path 'submodule_name'на кроці 3. Хоча обидва кроки були необхідні. (git v2.8.2)
U007D

13

Нещодавно я з’ясував проект git, який включає багато корисних команд, пов'язаних з git: https://github.com/visionmedia/git-extras

Встановіть його та введіть:

git-delete-submodule submodule

Потім справи робляться. Каталог субмодулів буде видалений з репо-файлу та все ще буде існувати у вашій файловій системі. Ви можете зафіксувати зміни , як: git commit -am "Remove the submodule".


Ви можете назвати це так git delete-submodule, як git-extrasпотрібно, щоб стати на шляху до роботи. Також зауважте, що я рекомендую не використовуватиgit-extras , оскільки багато його частин надзвичайно глючно і небезпечно . IE, git-delete-submoduleможливо, видаляє неправильний шлях внизу .git/modules/*, оскільки передбачає, що модуль і шлях однакові (що часто не буває), і він не працює правильно, якщо ви намагаєтесь видалити підмодуль з підмодуля. git-extrasможе бути на 99% корисним, але, будь ласка, не скаржтеся, якщо в ньому все буде зовсім не так. ВАМ ПЕРЕДБАГАЛИ!
Тіно

10

Мені довелося зробити кроки Джона Дауата на крок далі та cdдо каталогу підмодулю, а потім видалити сховище Git:

cd submodule
rm -fr .git

Тоді я міг би записати файли як частину батьківського сховища Git без старої посилання на підмодуль.


Мені довелося це робити і для того, щоб пройти помилку "fatal: Not git repository:" при спробі зробити git rm --cacheкрок.
RickDT

9

Ось чотири кроки, які мені здаються потрібними чи корисними (важливі спочатку):

git rm -f the_submodule
rm -rf .git/modules/the_submodule
git config -f .git/config --remove-section submodule.the_submodule
git commit -m "..."

Теоретично , git rmв кроці 1 повинен подбати про це. Сподіваємось, на другу частину питання ОП можна відповісти позитивно за один день (що це можна зробити за одну команду).

Але станом на липень 2017 року, крок 2 необхідний для видалення даних, .git/modules/оскільки в іншому випадку ви не можете, наприклад, додавати підмодуль у майбутньому.

Ви, ймовірно, можете піти з вищевказаних кроків для git 1.8.5+ як зазначено у відповіді tinlyx , оскільки всі git submoduleкоманди, здається, працюють.

Крок 3 видаляє розділ для the_submodule файлу .git/config. Це слід зробити для повноти. (Запис може спричинити проблеми для старих версій git, але я не маю тестувати).

Для цього більшість відповідей пропонують використовувати git submodule deinit. Я вважаю це більш явним і менш заплутаним у використанні git config -f .git/config --remove-section. Відповідно до git-підмодульної документації , git deinit:

Разрегістріровать дані подмодулей ... Якщо ви дійсно хочете видалити подмодуль зі сховища і фіксація , що використання ГІТ-ет [1] замість .

І останнє, але не менш важливе, якщо ви цього не зробите git commit, ви можете / може отримати помилку під час виконання git submodule summary(з git 2.7):

fatal: Not a git repository: 'the_submodule/.git'
* the_submodule 73f0d1d...0000000:

Це не залежно від того, чи виконуєте ви кроки 2 чи 3.


7
project dir:     ~/foo_project/
submodule:       ~/foo_project/lib/asubmodule
- - - - - - - - - - - - - - - - - - - - - - - - -
run:
  1.   cd ~/foo_project
  2.   git rm lib/asubmodule && 
          rm .git/modules/lib/asubmodule && 
            git submodule lib/asubmodule deinit --recursive --force

7

Я щойно знайшов прихований файл .submodule (забув точне ім’я), у ньому є список ... Ви можете видалити їх окремо таким чином. У мене просто був такий, тому я його видалив. Простий, але це може зіпсувати Git, оскільки я не знаю, чи щось додано до підмодуля. Поки здається нормальним, окрім звичного питання оновлення libetpan, але це (сподіваємось) не пов'язане.

Помітив, що ніхто не публікував стирання вручну, тому додано



7

З git 2.17 і вище це просто:

git submodule deinit -f {module_name}
git add {module_name}
git commit

Чи не працює, ні за git 2.17.1ні git 2.20.1. Однак використання git rmзамість git addпрацювали для обох. Примітки: -fне потрібно, якщо речі чисті. Будьте впевнені , щоб не використовувати варіанти з , gitякщо ви хочете захистити від ненавмисних втрат даних. Також зауважте, що це залишає .git/modules/{module_name}на місці. Найкраще зберігати його там, оскільки gitдрукується правильна (!) Допомога, як діяти, якщо щось заблоковано через це.
Тіно

4

Якщо ви щойно додали підмодуль, і, наприклад, ви просто додали неправильний підмодуль або додали його в неправильному місці, просто зробіть, git stashа потім видаліть папку. Це припущення, що додавання підмодуля - це єдине, що ви зробили в недавньому репо.


3

На користь читача, це тут намагається підсумувати його та дати покрокове керівництво щодо того, як це зробити, якщо все не працює так, як очікувалося. Далі йде перевірений і безпечний спосіб для gitверсії 2.17та вище для позбавлення від підмодуля :

submodule="path/to/sub"              # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
  • Якщо це не допоможе вам, дивіться нижче.
  • Немає варіантів. Нічого небезпечного. І навіть не думайте робити більше!
  • Тестовано з Debian Buster 2.20.1та Ubuntu 18.04 2.17.1.
  • "$submodule" це лише підкреслити, де слід вказати ім’я, і що вам слід бути обережними з пробілами тощо
  • Якщо в Windows ігноруйте перший рядок і замініть "$submodule"Windows способом правильно вказаного шляху до підмодуля. (Я не Windows)

Увага!

Ніколи не торкайтеся нутрощів .gitкаталогу самостійно! Редагування всередині.git переходить у темну сторону. Тримайтеся подалі за будь-яку ціну!

І так, ви можете звинуватити gitв цьому, оскільки багато корисних речей не вистачалоgit минулому. Як правильний спосіб знову видалити підмодулі.

Я думаю, що в документації Росії є дуже небезпечна частина git submodule. Рекомендує зняти $GIT_DIR/modules/<name>/себе. На моє розуміння, це не просто невірно, це надзвичайно небезпечно і провокує великі головні болі в майбутньому! Дивись нижче.

Зауважте, що

git module deinit

є прямою оберненою до

git module init

але

git submodule deinit -- module
git rm -- module

також є досить зворотним

git submodule add -- URL module
git submodule update --init --recursive -- module

тому що деяким командам в основному потрібно зробити більше, ніж просто одну річ:

  • git submodule deinit -- module
    • (1) оновлення .git/config
  • git rm
    • (2) видаляє файли модуля
    • (3) тим самим рекурсивно видаляє підмодулі підмодуля
    • (4) оновлення .gitmodules
  • git submodule add
    • тягне дані до .git/modules/NAME/
    • (1) робить git submodule init, тому оновлення.git/config
    • (2) робить git submodule update, таким чином, нерекурсивно перевіряє модуль
    • (4) оновлення .gitmodules
  • git submodule update --init --recursive -- module
    • за потреби подає додаткові дані
    • (3) рекурсивно перевіряє підмодулі підмодуля

Це не може бути повністю симетричним, оскільки зберігати його строго симетрично не має особливого сенсу. Просто не потрібно більше двох команд. Також "втягування даних" є неявним, оскільки вам це потрібно, але видалення кешованої інформації не робиться, оскільки це зовсім не потрібно і може стерти дорогоцінні дані.

Це справді дивовижне для новачків, але в основному це добре: gitпросто робить очевидно і робить це правильно, і навіть не намагається робити більше. gitце інструмент, який повинен зробити надійну роботу, а не бути лише черговим "Eierlegende Wollmilchsau" ("Eierlegende Wollmilchsau" перекладається для мене "якоюсь злою версією ножа швейцарської армії").

Тож я розумію скарги людей, кажучи: "Чому я не робиш gitочевидного для мене". Це тому, що "очевидне" тут залежить від точки зору. Надійність у кожній ситуації набагато важливіша. Отже, те, що для вас очевидно, часто не є правильним у всіх можливих технічних ситуаціях. Пам'ятайте про це: AFAICS gitслідує технічному шляху, а не соціальному. (Звідси розумна назва: git)

Якщо це не вдасться

Команди, наведені вище, можуть не працювати через:

  • Ваш gitзанадто старий. Потім використовуйте новіший git. (Дивіться нижче, як це зробити.)
  • Ви не передали дані і можете втратити дані. Тоді краще спочатку скопіюйте їх.
  • Ваш підмодуль у певному git cleanсенсі не чистий . Потім спочатку очистіть підмодуль за допомогою цієї команди. (Дивись нижче.)
  • Ви раніше робили щось, що не підтримується git . Тоді ви на темній стороні, і справи стають потворними і складними. (Можливо, використання іншої машини виправляє це.)
  • Можливо, є більше способів невдачі, про які я не знаю (я просто якийсь gitвладний користувач.)

Наступні можливі виправлення.

Використовуйте новіший git

Якщо Ваш апарат занадто старий , немає submodule deinitв вашому git. Якщо ви не хочете (або можете) оновити свою git, тоді просто використовуйте іншу машину з новішою git! gitпризначений для повного розповсюдження, тому ви можете використовувати іншу, gitщоб виконати роботу:

  • workhorse:~/path/to/worktree$ git status --porcelain не повинен нічого виводити! Якщо це так, спочатку почистіть речі!
  • workhorse:~/path/to/worktree$ ssh account@othermachine
  • othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
  • Тепер робимо підмодуль
  • othermachine:~/TMPWORK$ git commit . -m . && exit
  • workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
  • workhorse:~/path/to/worktree$ git merge --ff-only FETCH_HEAD. Якщо це не працює, використовуйтеgit reset --soft FETCH_HEAD
  • Тепер прибирайте речі, поки git statusзнову не буде чисто. Ви можете це зробити, тому що ви очистили це раніше, завдяки першому кроку.

Це othermachineможе бути якийсь VM або якийсь Ubuntu WSL під Windows. Навіть chroot(але я припускаю, що ви не кореневий, тому що, якщо ви є, rootйого слід легше оновити на новіші git).

Зауважте, що якщо ви не можете sshввійти, існує набір шляхів транспортування gitсховищ. Ви можете скопіювати своє робоче дерево на якийсь USB-накопичувач (включаючи .gitкаталог) та клонувати його з флешки. Клонуйте копію, просто щоб знову зробити речі в чистому вигляді. Це може бути PITA, якщо ваші підмодулі не доступні безпосередньо з інших машин. Але і для цього є рішення:

git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX

Ви можете використовувати це множення, і це зберігається в $HOME/.gitconfig. Щось на зразок

git config --add 'url./mnt/usb/repo/.insteadof' https://github.com/

переписує такі URL-адреси, як

https://github.com/XXX/YYY.git

в

/mnt/usb/repo/XXX/YYY.git

Це легко, якщо ви почнете звикати до таких потужних gitфункцій.

Спочатку почистіть речі

Чистка вручну - це добре, тому що ви, можливо, виявляєте деякі речі, про які ви забули.

  • Якщо git поскаржиться на незбережені речі, зробіть їх і кудись надійніше.
  • Якщо git скаржиться на деякі залишки, git statusіgit clean -ixfd це ваш друг
  • Постарайтеся утриматися від варіантів rmі до deinitтих пір, поки зможете. Параметри (як -f) для gitхороших, якщо ви професіонал. Але, як ви приїхали сюди, ви, мабуть, не так досвідчені в цьому submoduleрайоні. Тож краще бути в безпеці, ніж шкодувати.

Приклад:

$ git status --porcelain
 M two
$ git submodule deinit two
error: the following file has local modifications:
    two
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'two' contains local modifications; use '-f' to discard them
$ cd two
$ git submodule deinit --all
error: the following file has local modifications:
    md5chk
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'md5chk' contains local modifications; use '-f' to discard them
$ cd md5chk
$ git submodule deinit --all
error: the following file has local modifications:
    tino
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'tino' contains local modifications; use '-f' to discard them
$ cd tino
$ git status --porcelain
?? NEW
$ git clean -i -f -d
Would remove the following item:
  NEW
*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers    4: ask each
    5: quit                 6: help
What now> 1
Removing NEW
$ cd ../../..
$ git status --porcelain
$ git submodule deinit two
Cleared directory 'two'
Submodule 'someunusedname' (https://github.com/hilbix/src.git) unregistered for path 'two'

Розумієте, немає -fнеобхідності на submodule deinit. Якщо речі чисті, в певному git cleanсенсі. Також зауважте, що git clean -xце не потрібно. Це означає, що git submodule deinitбезумовно видаляються незатребувані файли, які ігноруються. Зазвичай це те, що ви хочете, але не забувайте про це. Іноді ігноровані файли можуть бути дорогоцінними, як кешовані дані, на які потрібно заново обчислювати години.

Чому ніколи не видаляють $GIT_DIR/modules/<name>/?

Можливо, люди хочуть видалити кешований сховище, оскільки вони бояться зіткнутися з проблемою пізніше. Це правда, але наткнутися на цю "проблему" - це правильний спосіб її вирішити! Оскільки виправити це легко, і правильно зробити, ви зможете жити щасливо до цього часу. Це дозволяє уникнути більш громіздких проблем, ніж при видаленні даних самостійно.

Приклад:

mkdir tmptest &&
cd tmptest &&
git init &&
git submodule add https://github.com/hilbix/empty.git two &&
git commit -m . &&
git submodule deinit two &&
git rm two &&
git commit -m . &&
git submodule add https://github.com/hilbix/src.git two

Останній рядок видає наступну помилку:

A git directory for 'two' is found locally with remote(s):
  origin    https://github.com/hilbix/empty.git
If you want to reuse this local git directory instead of cloning again from
  https://github.com/hilbix/src.git
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.

Чому ця помилка? Оскільки .git/modules/two/раніше було заповнено з https://github.com/hilbix/empty.git, а тепер буде повторно заселене чимось іншим, а саме https://github.com/hilbix/src.git . Ви не побачите цього, якщо повторно заселите його з https://github.com/hilbix/empty.git

Що ж тепер робити? Ну просто роби точно так, як сказано! Використовуйте--name someunusedname

git submodule add --name someunusedname https://github.com/hilbix/src.git two

.gitmodules то схожий

[submodule "someunusedname"]
    path = two
    url = https://github.com/hilbix/src.git

ls -1p .git/modules/ дає

someunusedname/
two/

Таким чином, у майбутньому ви можете перемикати гілки / здійснювати вперед та назад і більше ніколи не потраплятимете в будь-які проблеми через two/наявність двох різних (і, можливо, несумісних) сховищ вище. А найкраще: Ви обидва зберігаєте кешований локально.

  • Це стосується не тільки вас. Це також справедливо для всіх інших, що використовують ваше сховище.
  • І ви не втрачаєте історію. Якщо ви забули натиснути саму останню версію старого підмодуля, ви можете ввести локальну копію і зробити це пізніше. Зауважте, що досить часто хтось забуває натиснути на якісь підмодулі (адже це ПДФА для новачків, поки вони не звикли git).

Однак якщо ви видалили кешований каталог, обидві різні каси натикатимуться один на одного, тому що ви не будете використовувати --nameваріанти, правда? Тому щоразу, коли ви здійснюєте оформлення замовлення, вам, можливо, доведеться видаляти .git/modules/<module>/каталог знову і знову. Це надзвичайно громіздко і ускладнює використання чогось подібного git bisect.

Тому є дуже технічна причина зберегти цей каталог модулів як заповнювач. Люди, які рекомендують видалити щось нижче, .git/modules/або не знають краще, або забувають сказати вам, що це робить такі потужні функції, якgit bisect майже неможливо використовувати, якщо це перетинає таку несумісність підмодуля.

Наступна причина показана вище. Подивись наls . Що ти там бачиш?

Ну, 2-й варіант модуля two/не під .git/modules/two/, він під .git/modules/someunusedname/! Тож такі речі git rm $module; rm -f .git/module/$moduleабсолютно неправильні! Ви повинні або проконсультуватися, module/.gitабо.gitmodules знайти потрібну річ, яку потрібно видалити!

Тож не лише більшість інших відповідей потрапляють у цю небезпечну пастку, навіть дуже популярні gitрозширення мали цю помилку ( вона зараз виправлена )! Тож краще тримати свої .git/довідники, якщо ви точно не робите, що робите!

І з філософського погляду витирання історії завжди неправильне! За винятком квантової механіки , як завжди, але це щось зовсім інше.

FYI ви, напевно, здогадалися: hilbix - це мій обліковий запис GitHub.


Ця енциклопедія допису повинна бути розбита на чіткіші розділи з більшими / чіткішими підзаголовками, щоб вказати на реальну відповідь та різні розділи "усунення несправностей" / тощо.
Андрій

2

Підсумовуючи це, ви повинні зробити:

Встановити var_to_submodule var (відсутній косою косою рисою):

path_to_submodule=path/to/submodule

Видаліть відповідний рядок із файлу .gitmodules:

git config -f .gitmodules --remove-section submodule.$path_to_submodule

Видаліть відповідний розділ із .git / config

git config -f .git/config --remove-section submodule.$path_to_submodule

Видаліть та видаліть $ path_to_submodule лише з індексу (щоб запобігти втраті інформації)

git rm --cached $path_to_submodule

Відстежуйте зміни, внесені до .gitmodules

git add .gitmodules

Здійсніть суперпроект

git commit -m "Remove submodule submodule_name"

Видаліть не відстежені файли підмодуля

rm -rf $path_to_submodule

rm -rf .git/modules/$path_to_submodule

Дивіться також: Альтернативні напрямні лінії


Чи можете ви, будь ласка, розширити це тим, як видалити підмодуль після "додавання підмодуля git", але не вчиняючи його ніколи? Я припускаю, що в такому випадку для видалення підмодуля не потрібне жодне зобов'язання, правда?
Карло Вуд

Я думаю, вам потрібно поміняти місцями git rm --cached $path_to_submoduleі git add .gitmodulesні? Я отримав помилку в першій команді: fatal: Please stage your changes to .gitmodules or stash them to proceedтому що в мене були нестандартні зміни .gitmodules. Виконання git add .gitmodulesпершого вирішує це.
Карло Вуд

2

Це легко:

  1. Видаліть розділ з .gitmodules
  2. Виклик: git add .gitmodules
  3. Виклик: git submodule deinit <path to submodule>
  4. Виклик: git rm <path to submodule>
  5. Звернутись і натиснути

Файли модулів з вашого проекту доведеться видалити вручну.


2
Для мене було достатньо дзвонити git submodule deinit <submodule_name>і git rm <path_to_submodule>. Остання команда автоматично видаляє запис всередині .gitmodules. Git 2.17
Дмитро Овдієнко

1

Я створив сценарій bash, щоб полегшити процес видалення. Він також перевіряє, чи є зміни в репо, залишеному без збереження, і просить підтвердити. Це тестування os xбуло б цікаво дізнатися, чи працює він, як і у звичайних дистрибутивах Linux:

https://gist.github.com/fabifrank/cdc7e67fd194333760b060835ac0172f


0

Останнім git потрібно лише 4 операції для видалення підмодуля git.

  • Видаліть відповідний запис у .gitmodules
  • Зміни стадії git add .gitmodules
  • Видаліть каталог підмодулів git rm --cached <path_to_submodule>
  • Здійсни це git commit -m "Removed submodule xxx"

0

У випадку, якщо вам потрібно зробити це в одній рядковій команді із скриптом bash, як показано нижче:

$ cd /path/to/your/repo && /bin/bash $HOME/remove_submodule.sh /path/to/the/submodule

Створіть файл bash script у режимі з $HOMEім'ям, тобто remove_submodule.sh:

#!/bin/bash

git config -f .gitmodules --remove-section submodule.$1
git config -f .git/config --remove-section submodule.$1
git rm --cached $1
git add .gitmodules
git commit -m "Remove submodule in $1"
rm -rf $1
rm -rf .git/modules/$1
git push origin $(git rev-parse --abbrev-ref HEAD) --force --quiet


0
  • Підмодуль можна видалити запуском git rm <submodule path> && git commit. Це можна скасувати за допомогою git revert.
    • Видалення видаляє дані відстеження суперпроекту, які є як записом gitlink, так і розділом у .gitmodulesфайлі.
    • Робочий каталог підмодуля видалено з файлової системи, але каталог Git зберігається навколо, щоб зробити можливість перевірки минулих комісій, не вимагаючи отримання з іншого сховища.
  • Щоб повністю видалити підмодуль, додатково видаліть його вручну$GIT_DIR/modules/<name>/ .

Джерело: git help submodules


-1

Видалення підмодуля git

Для видалення gitпідмодуля потрібно 4 кроки.

  1. Видаліть відповідний запис у .gitmodulesфайлі. Запис може бути як зазначено нижче
[submodule "path_to_submodule"]
    path = path_to_submodule
    url = url_path_to_submodule
  1. Зміни стадії git add .gitmodules
  2. Видаліть каталог підмодулів git rm --cached <path_to_submodule>.
  3. Зробіть це git commit -m "Removed submodule xxx"і натисніть.

Додаткові ще 2 етапи, згадані нижче, необхідні для повного очищення підмодуля в локальній клонованій копії.

  1. Видаліть відповідний запис у .git/configфайлі. Запис може бути як зазначено нижче
[submodule "path_to_submodule"]
    url = url_path_to_submodule
  1. Зробіть rm -rf .git/modules/path_to_submodule

Ці 5-й та 6-й кроки не створюють жодних змін, які потребують внесення змін.


Було б набагато простіше, якби ви використовували git submodule deinit git-scm.com/docs/git-submodule#Documentation/…
Чорний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.