365Git

  1. Search
  2. About
  3. Subscribe
  4. Archive
  5. Random

365Git

Regular small snippets and workflows for Git

My original plan of a post everyday turned out to be unrealistic, but I'll carry on posting as regularly as I can.

Find me @abizern on twitter if you have anything you'd like me to cover.

Newer
Older
  • Set Up a Submodule Where Only You Have Write Access.

    Say you want to add a submodule to your repository, and this submodule is a one to which you have push access. It is frequently useful to be able to publish a repository with the submodule URL as pull-only, while keeping the push-pull URL in your own repository. This way, you can make changes to the submodule repository from within the enclosing repository. This is a simple thing to do in Git once you know how submodules are arranged.

    Example

    For convenience, let’s use a a couple of GitHub repositories as an example. Let’s start with the Hello repository, and say I want to add the Just Testing repository as a submodule. That’s simple enough; I check out the Hello repository to my local drive:

    cd tmp
    git clone -o github git@github.com:Abizern/Hello.git
    cd Hello
    

    (You may notice the unfamiliar -o github in the clone command. This names the remote for this clone “github” instead of the default “origin”. Git is distributed, and I often have more than one remote for repositories, so I like to name my remotes semantically. Another name I use is “dropbox” for obvious reasons).

    Now I’m in the repository I add the remote. This is where I have to make a choice. GitHub gives you a choice of clone URLs:

    SSH Read+WriteHTTP Read+WriteGit Read Only

    If I use the Read+Write URLs, for the submodules, and someone else clones my repository, they will be using URLs to which they do not have access. So, cloning the repository will work, but when they go to initialise the submodule, the command will fail because they can’t access the repository through that URL. But, If I use the Read-Only URL, I won’t be able to push to my submodule repository. That’s okay, because I can add the repository with Read+Write access for me but change it for the shared repository. Let’s start by adding the submodule to the repository using the Read+Write URL:

    git submodule add git@github.com:Abizern/JustTesting.git
    

    This will add a directory called “JustTesting” to my repository and check out the files. You can check the submodule with git submodule status which, in my case, shows this:

     a73686133fc66884faac1f8c1d9603b9ffcf09b1 JustTesting (heads/master)
    

    Which shows the sha of the checked out commit of the submodule (there are no - or + adornments so there are no issues) the directory which contains it (JustTesting) and the current description (in this case it just shows the head of the master branch. If there were any tags in the repository it would show the output of git describe).

    Checking the status of the repository with git status shows that we have two new files:

    Result of git status

    JustTesting isn’t a new file, it’s just the way that Git sees a submodule. What we are interested in is the “.gitmodules” file. You can see that this shows where the the submodule is kept and what it’s URL is. Now let’s look at the way the submodule is configured:

    Remote information

    First I find out what the name of the remote is (yes, I know it’s origin) and then I get information about the remote. This shows that it is configured to the Read+Write URL

    Let’s take a look at the “.git/config” file. This is where the configuration for the local repository is kept:

    Git config file

    The interesting section is at the bottom, which has information about the submodule. This looks a lot like the entry in the “.gitmodules” file, except that it doesn’t reference the path to the submodule.

    Now let’s change the URL in the “.gitmodules” file so that it points to the Read-only URL.

    Git config after changed section

    So there are two URLs for this submodule. The repository itself contains the Read-Only URL in “.gitmodules” and this is the configuration that is shared among all repositories that clone it. And the private Read+Write module is configured in the “.git/config” file which applies only to this particular repository. Now I just need to commit the changes and I can push this back up to GitHub.

    Go and look at the Hello repository for yourself. You can see that JustTesting is a submodule. And if you clone this and update the submodule, it will be configured to point to the Read-Only version of JustTesting:

    cd tmp
    git clone -o github git@github.com:Abizern/Hello.git Hello2
    cd Hello2
    git submodule update --init
    

    And you can see for yourself that “.gitmodules”, “.git/config” are configured for the Read-only URL. I’m not going to show you the output of those because I want to show you something more interesting.

    Imagine I am at my other machine and I want to clone this repository but still have Read+Write Access to the submodule. This is how I go about that. I clone the repository as normal but I don’t update the submodule in the same way as I just did above

    cd tmp
    git clone -o github git@github.com:Abizern/Hello.git Hello3
    cd Hello3
    

    Then – I init the submodule:

    git submodule init
    

    And you can see that all this does is register the submodule, but does not actually check out the repository:

    Submodule init

    Now - I can change my local configuration in “.git/config” so that the submodule URL is the Read+Write one:

    config changed

    And now I update the submodule repository:

    git submodule update
    

    And I have Read+Write access from my local submodule:

    Submodule status

    Explanation

    That seems like a lot of steps - but only because I went through it in detail. This is why it works:

    URLs for submodules are kept in the “.gitmodules” file. As this is in the top level of the repository, it is shared amongst all repositories that clone from it. When you initially add a submodule to your repository, an entry is added to the “.gitmodules” file and to the local “.git/config” file and the repository is checked out. All in one step (although the changes to the repo have to be committed manually, this allows you to change the public facing configuration).

    When you clone a repository that has submodules, all you are getting is the “.gitmodules” file. It also gets an entry that refers to the sha of the submodule to check out, I’ve written about this previously. It takes two steps to actually set up the repository. First, git submodule init copies the submodule settings from “.gitmodules” to “.git/config” and then git submodule update pulls down the repository at the sha that is referenced. Normally, you can do this with one step: git submodule update --init as in the Hello2 example. But If you do it in two steps, you have a chance to edit the “.git/config” file before the repository is pulled down, which means you can customise the way that the submodule is set up in your own repository.

    Tagged: git submodule config private sharing

    Posted on November 10, 2011 with 27 notes ()

    1. everyone78rt liked this
    2. ethernet7tu9 liked this
    3. practicing90fg liked this
    4. transientyou83 liked this
    5. carp89d liked this
    6. digdog liked this
    7. 365git posted this

Field Notes Theme. Designed by Manasto Jones. Powered by Tumblr.