Search code examples
gitgit-submodules

Change "logical name" of a Git submodule


The git submodule add command accepts the --name option, which lets you specify a logical name for the submodule. Otherwise, the submodule is named after the path where it is created.

Is there a way to change this logical name after the submodule has been created?


Solution

  • As of Git version 2.30.1, I have not found a way to do this using the Git command line, other than removing the submodule entirely and re-creating it from scratch.

    There are 4 things that need to change in order to rename a Git submodule:

    1. The name of the submodule heading in the .gitmodules file.
    2. The location of the submodule under the .git/modules tree.
    3. The contents of the .git file in the submodule.
    4. The location of the work tree specified in the submodule under the .git/modules tree.

    It's doable, but potentially messy. Proceed if you are brave, reckless, and/or desperate.


    Suppose you have a submodule saved in vendor/libfoo, and now you want to give it the logical name of vendor-libfoo without changing its physical location in the work tree.

    Here is the corresponding .gitmodules file:

    [submodule "vendor/libfoo"]
      path = vendor/libfoo
      url = https://git.example.net/libfoo
    

    And vendor/libfoo/.git will be a text file (not a directory, as with a top-level git repo), containing:

    gitdir: ../../.git/modules/vendor/libfoo
    

    This file points to where the Git data files are stored, which will be the directory .git/modules/vendor/libfoo.

    The file .git/modules/vendor/libfoo/config will contain (among other things):

    [core]
      worktree = ../../../../vendor/libfoo
    

    All of these must be adjusted in order to make the change!

    1. Change the logical name of the submodule without changing its path.l: change [submodule "vendor/libfoo"] to [submodule "vendor-libfoo"], but do not change the path = option under that section heading.
    2. Git will now attempt to look for this module in .git/modules/vendor-libfoo instead of .git/modules/vendor/libfoo. Therefore we must rename the latter to the former, to reflect the change in step 1.
    3. The contents of vendor/libfoo/.git will then be wrong, as the relative path will no longer point to the right place. We must change ../../.git/modules/vendor/libfoo to ../../.git/modules/vendor-libfoo, to reflect the change in step 2.
    4. In addition, the worktree = ../../../../vendor/libfoo option in .git/modules/vendor-libfoo will also be wrong. Change it to ../../../vendor/libfoo to reflect the fact that we have moved this directory upward within .git/modules by 1 level.

    Obviously, these steps need to be adapted to your particular case. I make no guarantees about the correctness or validity of this procedure in any situation.

    Theoretically this process can be scripted/automated, but there could be difficulties in correctly parsing the Git config format. You can probably get away with regex substitution in most cases.

    Good luck! And maybe hope that this feature gets more attention in later versions of git.