Lars Tackmann
Lars Tackmann

Reputation: 20865

Rename a git submodule

Is there some easy way to rename a git submodule directory (other than going through the entire motion of deleting it and re-adding it with a new destination name).

And while we are at it, why is it that I simply cannot do the following in the parent directory: git mv old-submodule-name new-submodule-name

Upvotes: 243

Views: 121804

Answers (8)

CristiFati
CristiFati

Reputation: 41116

Many great answers, I recently ran into this issue (had a bit of struggle) and I want to share a complete (yet minimal) list of steps that I took.

Working on a concrete example:

Repository PyShallow ([GitHub]: CristiFati/pyshallow - PyShallow):

  • Depends on PyCFUtils ([GitHub]: CristiFati/pycfutils - PyCFUtils) and has it as a (Git) submodule:

    • I recently renamed it (on GitHub) from CFPyUtils

    • One thing that threw me me a bit off course is that the old URL (with the old name) still works - GitHub is smart enough to redirect to the new one (which makes sense)

  • I might be considered too pedantic, but I wanted all references to CFPyUtils removed (even if some of them are just internal (no visibility to the user) and they work)

Steps (if one wants to replace old by new - each term refers to both: path and (part of) URL):

  1. Rename submodule folder in the Git repository (git mv old new)

  2. .gitmodules: Edit and replace all old occurrences by new

  3. .git/config: Edit and replace all old occurrences by new

  4. Rename (manually) submodule reference folder (mv .git/modules/old .git/modules/new)

  5. new/.git (!!! it's a file !!!): Update the new reference folder

  6. Synchronize submodule (git submodule sync)

  7. Modify any (non Git related) file that references the old submodule path

Everything works fine afterwards on the test clone, and also on a fresh one.

The actual steps:

(py_pc064_03.10_test0) [cfati@cfati-5510-0:/mnt/e/Work/Dev/Repos/GitHub/CristiFati/pyshallow/src]> ~/sopr.sh
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[064bit prompt]> # ---------- Start from scratch ----------
[064bit prompt]> ls
[064bit prompt]>
[064bit prompt]> git clone [email protected]:CristiFati/pyshallow.git .
Cloning into '.'...
remote: Enumerating objects: 123, done.
remote: Counting objects: 100% (123/123), done.
remote: Compressing objects: 100% (83/83), done.
remote: Total 123 (delta 57), reused 92 (delta 30), pack-reused 0
Receiving objects: 100% (123/123), 18.97 KiB | 626.00 KiB/s, done.
Resolving deltas: 100% (57/57), done.
[064bit prompt]>
[064bit prompt]> ls
Contents  LICENSE  README.md  _extra  cfpyutils  gen_evt  mue_idle.py  nix_run.sh  win_run.bat
[064bit prompt]>
[064bit prompt]> ls cfpyutils/
[064bit prompt]>
[064bit prompt]> git submodule update --init
Submodule 'cfpyutils' ([email protected]:CristiFati/cfpyutils.git) registered for path 'cfpyutils'
Cloning into '/mnt/e/Work/Dev/Repos/GitHub/CristiFati/pyshallow/src/cfpyutils'...
Submodule path 'cfpyutils': checked out '46ba9528d3aaed29eeaee5f09ac50c0f28e5836d'
[064bit prompt]>
[064bit prompt]> # ---------- Step #1. ----------
[064bit prompt]> git mv cfpyutils pycfutils
[064bit prompt]>
[064bit prompt]> ls
Contents  LICENSE  README.md  _extra  gen_evt  mue_idle.py  nix_run.sh  pycfutils  win_run.bat
[064bit prompt]>
[064bit prompt]> git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   .gitmodules
        renamed:    cfpyutils -> pycfutils

[064bit prompt]>
[064bit prompt]> git diff --cached .gitmodules
diff --git a/.gitmodules b/.gitmodules
index a4caf8a..8c841d4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,5 +1,5 @@
 [submodule "cfpyutils"]
-       path = cfpyutils
+       path = pycfutils
        url = [email protected]:CristiFati/cfpyutils.git
        #url = https://github.com/CristiFati/cfpyutils.git
        branch = master
[064bit prompt]>
[064bit prompt]> # ---------- Step #2. ----------
[064bit prompt]> vi .gitmodules
[064bit prompt]>
[064bit prompt]> # ---------- Step #3. ----------
[064bit prompt]> vi .git/config
[064bit prompt]>
[064bit prompt]> # ---------- Step #4. ----------
[064bit prompt]> mv .git/modules/cfpyutils .git/modules/pycfutils
[064bit prompt]>
[064bit prompt]> git status
fatal: not a git repository: pycfutils/../.git/modules/cfpyutils
[064bit prompt]>
[064bit prompt]> # ---------- Step #5. ----------
[064bit prompt]> vi pycfutils/.git
[064bit prompt]>
[064bit prompt]> # ---------- Step #6. ----------
[064bit prompt]> git submodule sync
Synchronizing submodule url for 'pycfutils'
[064bit prompt]>
[064bit prompt]> # ---------- Step #7. ----------
[064bit prompt]> vi mue_idle.py
[064bit prompt]>
[064bit prompt]> # ---------- All done (review changes, commit and push) ----------
[064bit prompt]>
[064bit prompt]> git diff
diff --git a/.gitmodules b/.gitmodules
index 8c841d4..c9be742 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,5 +1,5 @@
-[submodule "cfpyutils"]
+[submodule "pycfutils"]
        path = pycfutils
-       url = [email protected]:CristiFati/cfpyutils.git
-       #url = https://github.com/CristiFati/cfpyutils.git
-       branch = master
+       url = [email protected]:CristiFati/pycfutils.git
+       #url = https://github.com/CristiFati/pycfutils.git
+       branch = main
diff --git a/mue_idle.py b/mue_idle.py
index 60813f9..dc48dc8 100755
--- a/mue_idle.py
+++ b/mue_idle.py
@@ -12,8 +12,8 @@ if cur_dir not in sys.path:
     sys.path.append(cur_dir)
 \"\"\"
 import gen_evt as ge
-from cfpyutils.common import ts_str
-from cfpyutils.keyboard import read_key
+from pycfutils.common import ts_str
+from pycfutils.keyboard import read_key


 __version_info__ = (0, 2, 2)
[064bit prompt]>
[064bit prompt]> git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   .gitmodules
        renamed:    cfpyutils -> pycfutils

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   .gitmodules
        modified:   mue_idle.py

[064bit prompt]> git add .gitmodules mue_idle.py
[064bit prompt]>
[064bit prompt]> git commit -m "fix: update submodule (path && url)"
[master 15d21e9] fix: update submodule (path && url)
 3 files changed, 8 insertions(+), 8 deletions(-)
 rename cfpyutils => pycfutils (100%)
[064bit prompt]> git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 544 bytes | 24.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:CristiFati/pyshallow.git
   7fcf9f3..52b148e  master -> master

Upvotes: 0

Mahmoud Adam
Mahmoud Adam

Reputation: 5852

The correct solution is:

mv oldpath ~/another-location
git rm oldpath
git submodule add submodule-repository-URL newpath

Upvotes: 19

Mariusz Nowak
Mariusz Nowak

Reputation: 32848

I found following workflow working:

  • Update .gitmodules
  • mv oldpath newpath
  • git rm oldpath
  • git add newpath
  • git submodule sync

Note: this approach does not update the index and .gitmodules properly in 2018 versions of GIT.

Note: You may be able to just do git mv oldpath newpath now, as pointed out in VonC's answer. (Ensure you are using the latest version of git)

Upvotes: 124

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92377

MacOs: When I wanna use VonC solution to change submodule folder Common to lowercase:

git mv Common common

I get

fatal: renaming 'Common' failed: Invalid argument

Solution - use some temporary folder name and move twice:

git mv Common commontemp
git mv commontemp common

That's all :)

Upvotes: 5

VonC
VonC

Reputation: 1324218

Git1.8.5 (October 2013) should simplify the process. Simply do a:

git mv A B

"git mv A B", when moving a submodule A has been taught to relocate its working tree and to adjust the paths in the .gitmodules file.


See more in commit 0656781fadca1:

Currently using "git mv" on a submodule moves the submodule's work tree in that of the superproject. But the submodule's path setting in .gitmodules is left untouched, which is now inconsistent with the work tree and makes git commands that rely on the proper path -> name mapping (like status and diff) behave strangely.

Let "git mv" help here by not only moving the submodule's work tree but also updating the "submodule.<submodule name>.path" setting from the .gitmodules file and stage both.
This doesn't happen when no .gitmodules file is found and only issues a warning when it doesn't have a section for this submodule. This is because the user might just use plain gitlinks without the .gitmodules file or has already updated the path setting by hand before issuing the "git mv" command (in which case the warning reminds him that mv would have done that for him).
Only when .gitmodules is found and contains merge conflicts the mv command will fail and tell the user to resolve the conflict before trying again.


git 2.9 (June 2016) will improve git mv for submodule:

See commit a127331 (19 Apr 2016) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster -- in commit 9cb50a3, 29 Apr 2016)

mv: allow moving nested submodules

"git mv old new" did not adjust the path for a submodule that lives as a subdirectory inside old/ directory correctly.

submodules however need to update their link to the git directory as well as updates to the .gitmodules file.

Upvotes: 341

kenorb
kenorb

Reputation: 166399

It's not possible to rename it, so you've to remove it first (deinit) and add it again.

So after removing it:

git submodule deinit <path>
git rm --cached <path>

you may also double check and remove the references to it in:

  • .gitmodules
  • .git/config
  • remove reference folder from .git/modules/<name> (best to make a backup), as each folder has config file where it keeps the reference to its worktree

then stage your changes by committing any changes to your repo by:

git commit -am 'Removing submodule.'

and double check if you don't have any outstanding issues by:

git submodule update
git submodule sync
git submodule status

so now you can add the git submodule again:

git submodule add --name <custom_name> [email protected]:foo/bar.git <my/path>

Upvotes: 16

jaredwolff
jaredwolff

Reputation: 807

I just tried a few of the suggested above. I'm running:

$ git --version
git version 1.8.4

I found it was best to de-init the submodule, remove the directory and create a new submodule.

git submodule deinit <submodule name>

git rm <submodule folder name>

git submodule add <address to remote git repo> <new folder name>

At least that is what worked for me best. YMMV!

Upvotes: 12

Abizern
Abizern

Reputation: 150615

Edit the .gitmodules file to rename the submodule and then rename the submodule directory.

I think you might need to do a git submodule sync afterwards, but I'm not in a position to check right now.

Upvotes: 4

Related Questions