简体   繁体   English

Git:如何将子模块推送到远程存储库?

[英]Git: how to push submodule to a remote repository?

I use git to track website I'm working on. 我使用git来跟踪我正在处理的网站。 I work on my machine and push commits to a remote server configured following this guide: using Git to manage a website . 我在我的机器上工作并将提交推送到按照本指南配置的远程服务器: 使用Git管理网站

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. 上周我尝试使用Git子模块来管理一些第三方库,今天我尝试推送到服务器,发现在服务器中所有子模块目录都是空的。

I tried adding and commiting changes to the local submodule, indeed git status says that the working directory is clean. 我尝试添加并提交对本地子模块的更改,实际上git status表示工作目录是干净的。

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. 子模块的意思是它们是存储库中的git存储库,而父存储库只知道应该在子模块中检出哪些提交 - 它对内容一无所知。 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 . 看起来你的工作树与你的GIT_WORK_TREE=/path/to/whatever git submodule update --init分开了一个设置,所以就像那个git checkout -f ,你需要适应它: 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). 之后,当你的钩子在推送后运行git checkout -f ,它还需要运行git submodule update (再次适当地设置工作树)。

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 在父repo中添加子模块(让它知道新的提交)并提交
  • push parent project to its central repo 将父项目推送到其中央仓库
  • parent's central repo hook checks out to your server, and updates submodule there parent的中央repo hook检查到你的服务器,并在那里更新子模块

As Jefromi pointed out, your submodule needs a "remote" to be able to get pushed. 正如Jefromi指出的那样,你的子模块需要一个“遥控器”才能被推动。

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 这里有一个简单的例子: Git:推送一个新的子模块

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. 我遇到了类似的问题:PC(A)中的repo克隆与外部网站中的远程控制器我希望在同一网络中的另一台PC(B)中克隆我的本地存储库,我可以推送我的更改(通过ssh)并进行一些测试(我的一些回归测试需要很长时间),这样我就可以继续在不同的分支上工作(如果需要的话)。 The repo in (A) has a submodule. (A)中的回购有一个子模块。

I created bare repo in (B): 我在(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): 并将其添加为我在(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: 并将(A)中的本地仓库(可能还有尚未公开的变更)推送到我的ssh仓库:

git push name_of_B_repo branch_to_push

After this, I clone my bare repo from within (B): 在此之后,我从内部克隆我的裸仓库(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: 解决方案1 :如果您没有兴趣测试/更改子模块的内容,但是您需要它来进行测试,那么您可以直接在(B)克隆的.git / config中包含外部网站链接:

[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: 解决方案2 :如果您有兴趣更改(A)中子模块的内容并将其发送到(B),首先需要将(B)中的ssh repo添加到本地(A)子模块仓库中作为新的远程:

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: 将子模块本地路径添加到(B)中克隆repo的.git / config文件中:

[submodule]
        url = /path/to/bare_git

and update your modules as before: 并像以前一样更新您的模块:

git submodule update --remote

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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