Как удалить субмодуль?

3540

Как удалить субмодуль Git?

Кстати, есть ли причина, которую я не могу просто сделать git submodule rm whatever?

Р. Мартиньо Фернандес
источник
109
Простой ответ stackoverflow.com/a/21211232/94687 теперь правильный, и должен быть помечен так. Теперь это просто git rm modulenameиrm -rf .git/modules/modulename
imz - Иван Захарящев
10
Это на самом деле не правда. Этот ответ не касается удаления записи субмодуля из .git/config. Принятый ответ показывает современный способ полного удаления субмодуля. Это также объясняется более кратко в этом ответе: stackoverflow.com/a/36593218/1562138
fvgs
Я нашел эту статью очень полезной в удалении подмодулей. Она включает в себя информацию об удалении записи в .gitsubmodules и .git / файлы конфигурации ссылаются
RI_
12
Пожалуйста, сэкономьте немного времени и сразу перейдите к ответу, который работает (в 2017 году): stackoverflow.com/a/36593218/528313
Винченцо
Я боролся с проблемами подмодулей в течение двух дней. Прорыв произошел, когда я нашел это: 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/…
Элиз ван Лоой,

Ответы:

2216

Начиная с версии 1.8.3 (22 апреля 2013 г.) :

Не было никакого Фарфорового способа сказать "Я больше не заинтересован в этом подмодуле", как только вы выразите свою заинтересованность в подмодуле с помощью " submodule init".
« submodule deinit» это способ сделать это.

Процесс удаления также использует git rm(начиная с git1.8.5 Октябрь 2013).

Резюме

Трехэтапный процесс удаления будет:

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» в подмодуле удаляет рабочее дерево подмодуля из суперпроекта и gitlink из индекса.
Но секция подмодуля в .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 больше не является сценарием оболочки.
Это вызов функции C.

См. Коммит 2e61273 , коммит 1342476 (14 января 2018 г.) Пратамеша Чавана ( pratham-pc) .
(Слиты Junio C Hamano - gitster- в фиксации ead8dbe , 13 февраля 2018)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "$@"
VonC
источник
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 Tutorial :

Для удаления подмодуля вам необходимо:

  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

Смотрите также : альтернативные шаги ниже .

John Douthat
источник
410
"И, кстати, есть ли причина, по которой я не могу просто сделать git submodule rm?" ?
Abernier
48
@abernier Краткий ответ может быть «потому что такой команды не существует». Я предполагаю, что они пытаются сделать удаление файлов субмодулей против конфигурации субмодуля явным, чтобы избежать случайной потери данных. Возможно, один человек подумает, что git submodule rmпросто удаляет регистрацию субмодуля, и будет удивлен, если команда также удалит локальный репозиторий. Любые локальные изменения будут безвозвратно утеряны. И, возможно, другой человек подумает, что будут удалены только файлы.
Джон Даутат
119
Честно говоря, я не знаю почему. Я надеюсь, что они добавляют команду, хотя. Эти 4 шага слишком сложны.
Джон Даутат
25
Вот скрипт bash, который удаляет подмодуль, просто создайте псевдоним git для submodule
Capi Etheriel
33
также нужно имя rm -rf .git \ modules \ submodule?
rogerdpack
484

Просто записка. Начиная с git 1.8.5.2, две команды будут делать:

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

Как правильно указал ответ @Mark Cheverton, если вторая строка не используется, даже если вы удалили субмодуль на данный момент, остальная папка .git / modules / 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
tinlyx
источник
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 deinit -f the_submodule
danday74
1
@JarrodSmith Да, это путь. пожалуйста, смотрите обновление.
tinlyx
479

Большинство ответов на этот вопрос устарели, неполны или излишне сложны.

Подмодуль, клонированный с использованием 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
fvgs
источник
39
Почему в этом ответе так мало голосов? Все эти популярные ответы что-то пропускают, это единственный, который действительно удаляет все следы подмодуля, самым простым способом. И обратите внимание: порядок команд имеет значение.
mbdevpl
2
Чтобы ответить на мой собственный вопрос: stackoverflow.com/questions/97875/rm-rf-equivalent-for-windows
Thomas
5
@mbdevpl появился через 3 года после принятого ответа, и я думаю, что никому не удалось убедить ОП принять этот ответ
Энди,
10
ЭТО несложный ответ в 2018 году?
Уоррен П
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
напутано
2
чтобы получить список модулей, в которых не было внесено никаких локальных изменений -git submodule | grep '^+' | cut -d' ' -f2
errordeveloper
обратите внимание, мне пришлось включить submodulenameв двойные кавычки "submodulename".. ссылаясь на .git/configфайл
мюон
Просто. Эффективное. В 2.25.0, после шага 1, вам нужно подготовить изменения .gitmodules до шага 2.
Мишель Донай
83

В дополнение к рекомендациям мне также нужно было rm -Rf .git/modules/path/to/submoduleиметь возможность добавить новый подмодуль с тем же именем (в моем случае я заменял вилку оригиналом)

Марк Чевертон
источник
1
У меня тоже были проблемы с этим. Если вы попытаетесь переустановить субмодуль по тому же пути, он сохранит информацию о ветках в кэше в указанном вами месте, что приведет к путанице.
Jangosteve
Спасибо, мне это тоже нужно. @ Антон, я согласен, и я отредактировал ответ с наибольшим количеством голосов, чтобы добавить эту информацию.
Уильям Деннис
Я использовал --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
Doug
источник
1
+1 действительно. Это единственный правильный ответ начиная с git 1.8.3. Должен быть принят как правильный.
Ксананакс
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/configфайле (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_submoduleпеременную (без косой черты):

    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

luissquall
источник
так что все остальные, кто извлекает мои изменения, должны запустить rm -rf $ path_to_submodule rm -rf .git / modules / $ 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.

Оли Студхолм
источник
точно мой случай
Жекаус
37

Я нашел deinitхорошие работы для меня:

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

Из git docs :

Deinit

Отмените регистрацию данных подмодулей, т.е. удалите весь submodule.$name раздел из .git / config вместе с их рабочим деревом.

Дамжан Павлица
источник
Согласитесь, нашли такое же решение. Это лучший способ сегодня в 2018 году)
woto
1
он не удалил .git / modules / ... Вы должны удалить их, смотрите ответ @fvgs
Vilém Kurz
Не знаю, почему это простое и легкое решение не номер 1
Марк Магон,
AFAICS это кажется наиболее безопасным ответом на новые gitс , которые знают о deinit, а другой ответ удаляет .git/modules/submoduleкаталог слишком рано, что , кажется, делает новый gits потерпеть неудачу сейчас или потом. Кроме того (см. Мой комментарий там) удаление .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)
udondan
источник
Почему вы используете 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 без старой ссылки на подмодуль.

Кайл Клегг
источник
Я должен был сделать это тоже, чтобы обойти ошибку «роковая: не git-репозиторий:» при попытке выполнить этот git rm --cacheшаг.
RickDT
9

Вот 4 шага, которые я нашел необходимыми или полезными (сначала важными):

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 deinit:

Отмените регистрацию указанных подмодулей ... Если вы действительно хотите удалить подмодуль из репозитория и зафиксировать, используя взамен git-rm [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, но (надеюсь) это не имеет отношения.

Заметил, что никто не размещал ручное стирание, поэтому добавил

Стивен Дж
источник
Это.gitmodules
Ариальдо Мартини
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удалите папку. Это предполагает, что добавление субмодуля - единственное, что вы сделали в недавнем репо.

botbot
источник
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.042.17.1 .
  • "$submodule" просто чтобы подчеркнуть, где поставить имя, и что вы должны быть осторожны с пробелами и тому подобное
  • Если в Windows пропустите первую строку и замените "$submodule"на путь 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может быть какая-то виртуальная машина или Ubuntu WSL под Windows, что угодно. Даже a chroot(но я предполагаю, что вы не являетесь пользователем root, потому что если 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 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/наличия двух разных (и, возможно, несовместимых) вышестоящих репозиториев. И самое лучшее: вы храните оба кэшированных локально.

  • Это касается не только вас. Это также верно для всех остальных, использующих ваш репозиторий.
  • И вы не потеряете историю. Если вы забыли загрузить самую последнюю версию старого субмодуля, вы можете ввести локальную копию и сделать это позже. Обратите внимание, что довольно часто кто-то забывает подтолкнуть некоторые подмодули (потому что это PITA для новичков, пока они не привыкли git).

Однако, если вы удалили кэшированный каталог, обе разные проверки наткнуться друг на друга, потому что вы не будете использовать --nameпараметры, верно? Поэтому каждый раз, когда вы делаете заказ, вам, возможно, придется .git/modules/<module>/снова и снова удалять каталог. Это чрезвычайно громоздко и затрудняет использование чего-то подобного git bisect.

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

Еще одна причина показана выше. Посмотрите на ls. Что ты там видишь?

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

Так что не только большинство других ответов попадают в эту опасную ловушку, но даже очень популярные gitрасширения имели эту ошибку ( теперь она исправлена )! Так что лучше держите руки в .git/справочнике, если не совсем точно, что вы делаете!

И с философской точки зрения вытирая историю всегда неправильно! За исключением квантовой механики , как обычно, но это нечто совершенно другое.

К вашему сведению, вы, наверное, догадались: hilbix - это мой аккаунт на GitHub.

Tino
источник
Эту энциклопедию поста следует разбить на более четкие разделы с более крупными / более ясными подзаголовками, чтобы указать фактический ответ, и различные разделы «Устранение неполадок» / и т. Д.
Андрей
2

Подводя итог, вот что вы должны сделать:

Установите path_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 submodule add», но без фиксации? Я предполагаю, что в этом случае не требуется коммит для удаления подмодуля, верно?
Карло Вуд
Я думаю, вам нужно поменять местами 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

TechRadar
источник
0

В последнем git требуется всего 4 операции для удаления подмодуля git.

  • Удалить соответствующую запись в .gitmodules
  • Сценические изменения git add .gitmodules
  • Удалить каталог подмодулей git rm --cached <path_to_submodule>
  • Совершить это git commit -m "Removed submodule xxx"
rashok
источник
0

В случае, если вам нужно сделать это в одной строке с помощью скрипта bash, как показано ниже:

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

Создайте файл сценария bash в каталоге с $HOMEименем ie 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

Chetabahana
источник
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-й этапы не создают никаких изменений, которые необходимо зафиксировать.

rashok
источник
Было бы намного проще, если бы вы использовали git submodule deinit git-scm.com/docs/git-submodule#Documentation/…
Black