submodule: absorb git dir instead of dying on deinit

Currently, running 'git submodule deinit' on repos where the submodule's '.git' is a directory, aborts with a message that is not exactly user friendly. Let's change this to instead warn the user that the .git/ directory has been absorbed into the superproject. The rest of the deinit function can operate as it already does with new-style submodules. In one test, we used to require "git submodule deinit" to fail even with the "--force" option when the submodule's .git/ directory is not absorbed. Adjust it to expect the operation to pass. Suggested-by: Atharva Raykar <raykar.ath@gmail.com> Signed-off-by: Mugdha Pattnaik <mugdhapattnaik@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Mugdha Pattnaik committed Nov 19, 2021 at 10:56 UTC 0adc8ba6ae2b76501f4e0e57cc83d79be5305418
2 files changed +16 -16
builtin/submodule--helper.c
+11 -10
@@ -1503,16 +1503,17 @@ static void deinit_submodule(const char *path, const char *prefix,
1503 struct strbuf sb_rm = STRBUF_INIT;
1504 const char *format;
1505
1506 - /*
1507 - * protect submodules containing a .git directory
1508 - * NEEDSWORK: instead of dying, automatically call
1509 - * absorbgitdirs and (possibly) warn.
1510 - */
1511 - if (is_directory(sub_git_dir))
1512 - die(_("Submodule work tree '%s' contains a .git "
1513 - "directory (use 'rm -rf' if you really want "
1514 - "to remove it including all of its history)"),
1515 - displaypath);
1506 + if (is_directory(sub_git_dir)) {
1507 + if (!(flags & OPT_QUIET))
1508 + warning(_("Submodule work tree '%s' contains a .git "
1509 + "directory. This will be replaced with a "
1510 + ".git file by using absorbgitdirs."),
1511 + displaypath);
1512 +
1513 + absorb_git_dir_into_superproject(path,
1514 + ABSORB_GITDIR_RECURSE_SUBMODULES);
1515 +
1516 + }
1517
1518 if (!(flags & OPT_FORCE)) {
1519 struct child_process cp_rm = CHILD_PROCESS_INIT;
t/t7400-submodule-basic.sh
+5 -6
@@ -1182,18 +1182,17 @@ test_expect_success 'submodule deinit is silent when used on an uninitialized su
1182 rmdir init example2
1183 '
1184
1185 -test_expect_success 'submodule deinit fails when submodule has a .git directory even when forced' '
1185 +test_expect_success 'submodule deinit absorbs .git directory if .git is a directory' '
1186 git submodule update --init &&
1187 (
1188 cd init &&
1189 rm .git &&
1190 - cp -R ../.git/modules/example .git &&
1190 + mv ../.git/modules/example .git &&
1191 GIT_WORK_TREE=. git config --unset core.worktree
1192 ) &&
1193 - test_must_fail git submodule deinit init &&
1194 - test_must_fail git submodule deinit -f init &&
1195 - test -d init/.git &&
1196 - test -n "$(git config --get-regexp "submodule\.example\.")"
1193 + git submodule deinit init &&
1194 + test_path_is_missing init/.git &&
1195 + test -z "$(git config --get-regexp "submodule\.example\.")"
1196 '
1197
1198 test_expect_success 'submodule with UTF-8 name' '