简体   繁体   中英

Git: how to push submodule to a remote repository?

I use git to track website I'm working on. I work on my machine and push commits to a remote server configured following this guide: using Git to manage a website .

Last week I tried using Git submodules to manage some third party libraries and today I tried pushing to the server, finding out that in the server all the submodule directories are empty.

I tried adding and commiting changes to the local submodule, indeed git status says that the working directory is clean.

What can I do?

The point of submodules is that they are git repositories within repositories, and the parent repo only knows what commit should be checked out in the submodule - it knows nothing about the content. So a server only aware of the parent project, which hasn't populated the submodules, will naturally see nothing in them.

You'll need to at some point initialize the submodules on your server. It looks like you've got a setup with your work tree separate from your repo, so just like with that git checkout -f , you'll need to accommodate that: GIT_WORK_TREE=/path/to/whatever git submodule update --init . Afterwards, when your hook runs git checkout -f after pushing, it'll also need to run git submodule update (again with the work tree appropriately set).

But it's more complicated than this. You haven't given any information about where your submodules came from, but a submodule is aware of its origin, just like your repository is. When you initialize one, it tries to clone from that origin, and updating it often requires fetching from that origin. If as I suspect, the origin for your third-party libraries is something public that you don't have push access to, you're going to have to set up your own central repositories for the submodules. When you commit in one of the submodules, you'd push to its central repo, and then push the parent project, so that when it tries to update submodules elsewhere, it's able to fetch them.

So, to recap, the workflow is something like this:

  • commit in third-party submodule (or standalone clone of it)
  • push third-party library to its central repository
  • add submodule in parent repo (make it aware of the new commit) and commit
  • push parent project to its central repo
  • parent's central repo hook checks out to your server, and updates submodule there

As Jefromi pointed out, your submodule needs a "remote" to be able to get pushed.

I guess the step you are missing is therefore

submodule-dir/$ git remote add origin <where to push submodule>

Here a simple example step by step: Git: Pushing a new submodule

Submodule is in fact a separate repo, which is pushed to another remote. So basically when you change something in your submodule you need to be in your submodule's working space to push to it. Moreover, after you have pushed to your submodule, you need to push the main project as well.

Here are some examples

I had a similar problem: a clone of a repo in a PC (A) with remote in an external website and I wanted to have a clone of my local repo in another PC (B) in the same network where I could push my changes to (through ssh) and make some tests (some of my regression test take a very long time), so that I could keep on working on (A) on an different branch if needed. The repo in (A) has a submodule.

I created bare repo in (B):

mkdir /path/to/bare_git && cd /path/to/bare_git
git --bare init

and added it as a new remote in my local repo in (A):

git add remote name_of_B_repo ssh://user@host/path/to/bare_git/

and pushed the local repo in (A) (possibly with changes not made public yet) to my ssh repo:

git push name_of_B_repo branch_to_push

After this, I clone my bare repo from within (B):

mkdir /path/to/B_clone && cd /path/to/B_clone
git clone /path/to/bare_git
git submodule update --remote

and I could see that my submodule was not included.

Solution 1 : If you are not interesting in testing/changing the content of your submodule, but you need it to make your tests, then you can include the external website link directly in the .git/config of (B) clone as:

[submodule]
        url = http://submodule_external_website_url

then, just update your submodule:

git submodule update --remote

Solution 2 : If you are interested in changing the content of the submodule in (A) and send them to (B), you first need to add the ssh repo in (B) to your local (A) submodule repo as a new remote:

cd /path/to/submodule
git add remote name_of_B_repo ssh://user@host/path/to/bare_git/

push your changes to it:

cd /path/to/main_A_local_repo
git submodule foreach git push name_of_B_repo branch_to_push

add the submodule local path to the .git/config file of clone repo in (B) as:

[submodule]
        url = /path/to/bare_git

and update your modules as before:

git submodule update --remote

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM