174

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

Community
  • 1
  • 1
Lars Tackmann
  • 18,135
  • 13
  • 60
  • 80
  • 7
    You will no longer need to update `.gitmodules` manually when moving a submodule. see [my answer below](http://stackoverflow.com/a/18712756/6309) – VonC Sep 10 '13 at 07:17
  • @VonC's answer worked like a charm for me – laconbass May 23 '15 at 03:31
  • Git modules are too complicated. `npm` shows how simple works. One day... maybe... someone... will rewrite it... in the meantime... – Rolf Mar 18 '18 at 15:00
  • @VonC's answer is not the full story as of today: it will indeed change .gitmodules, but will just rename the path, not the module name. You need an additional edit to .gitmodules to correct that and a 'git submodule sync' to complete the full process – zertyz Dec 07 '18 at 22:06
  • @zertyz: The property [submodule "name_of_submodule"] is a Git internal name, you can rename it for not confusing yourself but it's just a label. – MKesper May 16 '19 at 07:59
  • The title is misleadiing. It should be "Change a git submodule path" Renaming of a submodule is not possilbe AFAIK. ie the "path" and "url" parts of .gitmodules can be manipulated but not submoudle declaration. If you want the module name to be aligned with the path, you have to delete and reCreate. – Max Robbertze Apr 06 '20 at 12:31

7 Answers7

256

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.

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
  • Note to self: Try this on 1.8.4 and you will have `fatal: source directory is empty, source=my_source, destination=my_destination`. Will try this again when 1.8.5 has stable release. – checksum Nov 29 '13 at 02:22
  • @checksum But 1.8.5 has a stable release, for at least some... hours ;) https://github.com/git/git/releases/tag/v1.8.5 – VonC Nov 29 '13 at 06:16
  • I had to build Git version 1.8.5.GIT from the source code because there is Git v.1.7.5 in Ubuntu repositories. [How to build Git from the source code](http://git-scm.com/book/en/Getting-Started-Installing-Git) – Maksim Dmitriev Jan 17 '14 at 20:24
  • 2
    @MaksimDmitriev but what about a ppa (Personal Package Archive) that I mentioned in http://stackoverflow.com/a/20918469/6309? – VonC Jan 17 '14 at 20:32
  • @VonC, thanks a lot. When I built Git from the source code, there were no man pages. Git from the PPA is installed with the mans. – Maksim Dmitriev Jan 20 '14 at 05:33
  • This breaks your repository when nested submodules exist within the renamed submodule. I had to manually rename .git/module/oldmodule to .git/module/newmodule, rename the module in each submodule's .git file (gitdir path), and modify the worktree path for each nested config file (.git/config, .git/modules//config, .git/modules///config, etc.). Not simple, but works fine. – James Wald Feb 02 '14 at 03:13
  • @JamesWald ok. I don't see yet a patch in preparation in https://github.com/gitster/git/branches. I'll keep looking. – VonC Feb 02 '14 at 06:55
  • This is totally news to me and totally something I shall use in the future. Thanks for posting! – aendrew Feb 24 '14 at 11:42
  • Here's my version of moving/renaming a git submodule. This could be scripted, by somebody ;) http://stackoverflow.com/a/23087640/8047 – Dan Rosenstark Apr 15 '14 at 15:06
  • This does not seem to work with recursive submodules. You need to do this: http://stackoverflow.com/a/13893585/586086. – Andrew Mao Aug 08 '14 at 22:48
  • @AndrewMao with which version of Git did you see that issue? – VonC Aug 09 '14 at 03:12
  • @VonC 2.0.4. Is it fixed in a later version? – Andrew Mao Aug 09 '14 at 03:47
  • @AndrewMao it depends on the issue: are you saying that the .gitmodules within the submodule moved isn't properly changed? (while the .gitmodules of the main repo is) – VonC Aug 09 '14 at 03:48
  • @VonC `.gitmodules` contains no absolute path information. However `{submodule}/.git` and `.git/modules/submodules/{submodule}/config` does, and this is updated correctly for the first-level submodules but not the second-level submodules, when a first-level submodule is moved within the parent repo. I had to update both of the second-level submodule files manually for `git status` and other commands to work again. `git submodule sync` doesn't fix it, although `--recursive` might (although I forgot to try.) – Andrew Mao Aug 09 '14 at 06:03
  • @AndrewMao second level information are in the main parent repo? Not in the moved submodule? – VonC Aug 09 '14 at 06:07
  • @VonC one bit is in the first level submodule and another is in the second, neither are in the parent, both have absolute paths. – Andrew Mao Aug 09 '14 at 06:28
  • @AndrewMao ok, and would a `git submodule update --recursive --init` done from the main parent repo fix those automatically after the `git mv`? – VonC Aug 09 '14 at 06:29
  • Will check and get back to you. – Andrew Mao Aug 09 '14 at 06:30
  • This answer is not the full story: only the path is renamed. Inspecting the .gitmodules file, only the 'path = ....' line is updated. The module definition '[submodule "...."]' isn't touched. – zertyz Dec 07 '18 at 21:49
  • 2
    git mv just does not work for this purpose on my machine. – Alexander Dyagilev Jan 30 '19 at 07:22
  • @AlexanderDyagilev OK. What version of git were you using, on which OS? Also do you git mv the submodule folder with or without a trailing slash? (`git mv folder newpath`or `git mv folder/ newpath/`?) – VonC Jan 30 '19 at 07:45
  • @VonC, 2.9.2.windows.1. I did "git mv currentname newname". – Alexander Dyagilev Jan 30 '19 at 18:55
  • @AlexanderDyagilev Any chance to try that with a Gti 2.21.1? – VonC Jan 30 '19 at 21:49
  • @VonC Sorry, I've resolved the issue already... Btw, I've updated Git too, and it shows me 2.20.1 only... – Alexander Dyagilev Jan 31 '19 at 04:37
  • @VonC Using "git mv currentname newname" - I get the error "fatal: cannot move directory over file source=currentname , destination=newname/currentname"... git version 2.23.0.windows.1 in windows 10, running from git bash. The currentname and newname only differ by the case of the first letter (e.g. Code -> code). – feature_engineer Jul 26 '20 at 13:01
  • @feature_engineer Does the issue persists with Git 2.27? If yes, can you open a new question? – VonC Jul 26 '20 at 16:59
  • @VonC I've solved it by renaming it to a temp name and then to the correct name - I suspect it was due to the fact that the names differ only in their case, and windows' paths are case insensitive. Although the error message could have been more helpful. – feature_engineer Jul 27 '20 at 05:54
107

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 now just do git mv oldpath newpath now, as pointed out in VonC's answer. (Ensure you are using the latest version of git)

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
Mariusz Nowak
  • 28,556
  • 4
  • 32
  • 37
  • 22
    note to self: for `git add newpath` don't use a trailing slash – atomicules Jul 28 '11 at 15:17
  • Anyone successfully rename a submodule in this way? – Drake Guan Oct 17 '11 at 14:39
  • 1
    this works for me and the submodule appears as renamed in the status output (git status) after the move. – Lars Tackmann Nov 09 '11 at 10:03
  • 10
    With such a workflow, you will only create a symlink to the sub-directory you use as a submodule. Symlink is just a part of the global submodule functionality. This mean that when you clone the repo that use the renamed submodules, you may end with the following error: *No submodule mapping found in .gitmodules for path 'your-oldpath' After you remove the oldpath (*git rm oldpath*), you should use *git submodule add REPO-URL newpath* instead of "git add newpath*. When done, git status will display something like this: renamed: oldpath -> newpath – Bertrand Jan 26 '12 at 09:45
  • 1
    @Bertrand's advice worked for me. i also found that i had to delete the oldpath sections from .gitmodules and .git/config. – ryan Feb 02 '13 at 23:44
  • 5
    This solutions doesn’t work for me because when using git add command, the submodule was included into the project as a simple directory and not as a submodule. try $ mv submodule-oldpath ~/another-location $ git rm submodule-oldpath $ git submodule add submodule-repository-URL submodule-newpath http://bcachet.github.io/development/2012/05/25/rename-git-submodule/ – Mahmoud Adam May 06 '13 at 15:07
  • 1
    My output was `fatal: This operation must be run in a work tree fatal: 'git status --porcelain' failed in submodule newpath.` I used `git submodule add SUB_URL new_path` instead of `git add new_path`, and it worked. – Maksim Dmitriev Feb 26 '14 at 08:46
  • 3
    If you do have the problem with the working tree, you can also edit the `.git/modules/SUBMODULE/config` file, such that the `worktree` points to the the right directory again. – Vincent Ketelaars Apr 10 '14 at 14:24
  • This did not work for me, as I am using eclipse that probably has a bug in that case. So I had to remove and add again the submodule. This is probably due to the fact that in this way the module points to a work tree placed in a directory with the same name of the actual submodule path. – alexmogavero Jan 12 '15 at 14:32
  • 4
    This did not worked for me with git `2.13.1`. But simply doing `git mv old new` works like a charm. I only need to do git commit to complete the changes. – user Jul 20 '17 at 23:17
  • Yeah that deleted the submodule from `.gitmodules` so it doesn't really work. – Rolf Mar 18 '18 at 15:02
  • Saying "the latest version of git" does not age well. A specific version number would be better. – Craig McQueen Sep 25 '20 at 01:40
14

The correct solution is:

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

Source: Rename git submodule

BMW
  • 34,279
  • 9
  • 81
  • 95
Mahmoud Adam
  • 5,422
  • 5
  • 35
  • 61
  • 3
    Did you pull this word for word from this location? http://bcachet.github.io/development/2012/05/25/rename-git-submodule/ If so, please make sure to give attribution to that site in your answer. – George Stocker May 06 '13 at 16:17
11

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!

jaredwolff
  • 697
  • 8
  • 12
9

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> git@github.com:foo/bar.git <my/path>
kenorb
  • 118,428
  • 63
  • 588
  • 624
4

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.

Abizern
  • 129,329
  • 36
  • 198
  • 252
3

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

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241