116 lines
3.3 KiB
Markdown
116 lines
3.3 KiB
Markdown
# Removing a Git Submodule (CLI Script – Windows Safe)
|
||
|
||
This repository includes a safe, repeatable **scripted approach** for fully removing a Git submodule.
|
||
It handles Windows-specific issues, including stale `.git/modules` entries and file locks.
|
||
|
||
This version automates cleanup to prevent errors when adding new submodules at the same path or parent paths.
|
||
|
||
> ⚠️ Do **not** delete a submodule by removing the folder manually in Explorer.
|
||
> That leaves broken references in the repository.
|
||
|
||
---
|
||
|
||
## Usage
|
||
|
||
### 1. Run the script in Bash
|
||
|
||
```
|
||
#!/bin/bash
|
||
# Git Bash snippet: Remove a submodule safely on Windows
|
||
# Just assign SUBMODULE_PATH once and paste the whole thing
|
||
|
||
# ---- Assign your submodule path here ----
|
||
SUBMODULE_PATH="Open/Models/Bonsai/references/OD_css"
|
||
|
||
# ---- Begin removal ----
|
||
echo "Removing submodule: $SUBMODULE_PATH"
|
||
|
||
# 1. Deinitialize and remove submodule from index
|
||
git submodule deinit -f "$SUBMODULE_PATH"
|
||
git rm -f "$SUBMODULE_PATH"
|
||
git config -f .gitmodules --remove-section "submodule.$SUBMODULE_PATH" 2>/dev/null || true
|
||
git add .gitmodules 2>/dev/null || true
|
||
git commit -m "Remove submodule $SUBMODULE_PATH"
|
||
|
||
# 2. Attempt to remove local .git/modules metadata (Windows-safe)
|
||
MODULE_DIR=".git/modules/$SUBMODULE_PATH"
|
||
if [ -d "$MODULE_DIR" ]; then
|
||
echo "Cleaning up local gitdir: $MODULE_DIR"
|
||
attempts=0
|
||
while [ -d "$MODULE_DIR" ] && [ $attempts -lt 5 ]; do
|
||
rm -rf "$MODULE_DIR" 2>/dev/null || true
|
||
sleep 1
|
||
attempts=$((attempts+1))
|
||
done
|
||
if [ -d "$MODULE_DIR" ]; then
|
||
echo "WARNING: Could not remove $MODULE_DIR. Close Git Bash, Explorer, or IDEs and retry."
|
||
else
|
||
echo "Local gitdir removed successfully."
|
||
fi
|
||
else
|
||
echo "No leftover gitdir found. Cleanup complete."
|
||
fi
|
||
|
||
# 3. Show current submodule status
|
||
git submodule status
|
||
|
||
```
|
||
|
||
The script will:
|
||
1. Deinitialize the submodule (`git submodule deinit`)
|
||
2. Remove it from the index and working tree (`git rm`)
|
||
3. Remove the entry from `.gitmodules`
|
||
4. Commit the change
|
||
5. Attempt to delete `.git/modules/<submodule>` automatically
|
||
6. Display the current `git submodule status`
|
||
|
||
---
|
||
|
||
## How the script handles Windows-specific issues
|
||
|
||
Windows often holds files open in:
|
||
- Git Bash
|
||
- Explorer
|
||
- TortoiseGit dialogs
|
||
- Antivirus / Defender
|
||
|
||
This can prevent `.git/modules/...` from being fully deleted. The script:
|
||
- Retries deletion up to 5 times
|
||
- Sleeps briefly between retries
|
||
- Warns the user if the directory is still locked
|
||
|
||
> This ensures future submodule adds at the same path or a parent path do not fail.
|
||
|
||
---
|
||
|
||
## Manual fallback (if needed)
|
||
|
||
If the script warns that `.git/modules/...` could not be deleted:
|
||
1. Close all Git Bash windows, TortoiseGit dialogs, IDEs, and Explorer windows.
|
||
2. Delete the folder manually:
|
||
|
||
```
|
||
.git/modules/path/to/submodule
|
||
```
|
||
|
||
---
|
||
|
||
|
||
## Notes
|
||
|
||
- This permanently removes the submodule from the repository.
|
||
- To **convert a submodule into a normal tracked directory**, use a different workflow.
|
||
- Do **not** use `git submodule add --force` unless you know exactly why.
|
||
|
||
---
|
||
|
||
## Recommended best practices
|
||
|
||
- Always run the removal script from the **repo root**
|
||
- Verify `.git/modules` is empty for removed submodules
|
||
- Retry cleanup or delete manually if Windows locks files
|
||
- Use a **single argument** to specify the submodule path
|
||
- Check `git submodule status` to confirm removal
|
||
|
||
---
|
||
|