git submodule commit / push / pull

时间:2013-01-09 11:11:29

标签: git git-submodules

我想使用git子模块。

我需要采取的将我的更改推送到项目的步骤是

  
      
  1. 从子模块目录添加/提交/推送
  2.   
  3. 从父目录添加/提交/推送
  4.   

我需要采取措施来改变我的项目。

  
      
  1. 来自父目录的git pull
  2.   
  3. 来自父目录的git子模块更新
  4.   

从原始仓库更新子模块的步骤

  
      
  1. 来自子模块目录的git pull
  2.   

令我担心的是http://git-scm.com/book/en/Git-Tools-Submodules

以下的内容
  

问题在于您通常不希望在分离的HEAD中工作   环境,因为它很容易失去变化。如果你做一个初始   子模块更新,在该子模块目录中提交而不创建   一个分支工作,然后从中再次运行git submodule update   超级项目没有在此期间提交,( ?? update / commit / update会失去更改吗?)Git会覆盖   你的改变没有告诉你。从技术上讲,你不会失去工作,   但你不会有一个指向它的分支,所以它会有所不同   很难找回。

     

要避免此问题,请在处理子模块时创建分支   目录与git checkout -b work或等效的东西。当你   子模块第二次更新,它仍然会恢复你的工作,   但至少你有一个指针可以回到。

我要修改子模块并且不想搞砸,上面的文档简要提到了失去变化的可能性,我不明白可能导致丢失的原因。

  

我想知道除了上面列出的更多的其他步骤,我需要采取什么来防止   失利。   特别是几个团队成员修改子模块,他们需要做些什么不搞乱?

1 个答案:

答案 0 :(得分:20)

我想与您分享我在Visual Studio解决方案中尝试解决类似问题的外部项目的经验。我对git比较陌生,所以如果有人有任何建设性的批评,我会很感激。

如果您正在使用Visual Studio,Git源代码控制提供程序扩展是免费的(http://visualstudiogallery.msdn.microsoft.com/63a7e40d-4d71-4fbb-a23b-d262124b8f4c),并且在我测试它时似乎以递归方式提交子模块。

然而,我在家里使用VS Web Developer Express进行开发,所以我不想依赖扩展(我也认为了解一下发生了什么事情是好的)。因此我被迫弄清楚命令,我在下面添加了一些注释。

备注

如果您还没有完成,请仔细阅读http://git-scm.com/book/en/Git-Tools-Submodules。有很多警告,我将回顾这个页面。如果您尝试使用子模块而不阅读此内容,则会很快给您带来麻烦。

我的方法遵循本教程,增加了一些额外内容:http://blog.endpoint.com/2010/04/git-submodule-workflow.html

初始化超级项目后(例如git init& git remote add origin ...),开始添加子模块,如下所示:

git submodule add git://github.com/you/extension1.git extension
git submodule init
git submodule update

检查您的.gitmodules文件是否反映了此添加内容,例如

[submodule "extension1"]
        path = extension
        url = git://github.com/you/extension1.git

切换到您的子模块目录(即cd extension)。运行:

git fetch #I use fetch here - maybe you can use pull?
git checkout -b somebranchname #See the Git-Tools-Submodules link above for an explanation of why you need to branch

我在这里对README.txt进行了更改,所以我可以提交它(也是因为我将记录我在此提交中所做的事情),然后提交模块以应用分支(仍在子模块目录中) :

git add .
git commit -a -m "Branching for extension submodule"

现在进入超级项目(即cd ..)。你还需要在这里提交(如果你看一下我提到的git子模块页面,它解释了为什么这是必要的):

git status #will show you that your submodule has been modified
git commit -a -m "Commiting submodule changes from superproject"

现在我们可以根据需要反复推动我们的项目:

git push --recurse-submodules=on-demand

您需要对所有子模块执行一次上述步骤。

为所有子模块完成此操作并开始进行要提交和推送的更改后,您可以使用:

git submodule foreach 'git add .' #recursively add files in submodules

不幸的是,我没有找到一种方法来递归提交而不使用像git-slave(任何人?)这样的东西,所以你需要进入每个子模块目录并为你刚刚添加的文件运行常规提交。在超级项目中:

git status #tells you that `extension` submodule has been modified
cd extension
git commit -a -m "Commiting extension changes in superproject edit session"

一旦子模块提交,你还需要再次提交超级项目,所以:

cd ..
git add .
git commit -a -m "Altered extension submodule"
git status #should now show 'working directory clean', otherwise commit other submodules in the same manner

这可能会有点烦人(因为你最终会提交两次),但是一旦你意识到它,它实际上并没有那么糟糕(因为它迫使你检查你在每个项目中提交的内容)。只是我的意见 - 如果你已经将一些超级项目的功能分离到子模块中,它应该与你的其他项目隔离开来(所以在不同时间提交它们而烦人不是世界末日)。

现在我们可以再次推动......

git push --recurse-submodules=on-demand

如果你然后进入你的子模块并尝试再次推送,你会发现它不会做任何事情,因为已经推送了最新的提交。

对超级项目进行克隆(或使用远程源)也可能非常混乱 - 例如需要在git submodule update之后运行git submodule init两次。阅读http://git-scm.com/book/en/Git-Tools-Submodules的“使用子模块克隆项目”部分。

在克隆我的超级项目时抓住了我的东西是获取子模块的最新更改。见Easy way pull latest of all submodules

我的变体是对已检出的子模块使用'development'分支(但你可以随意调用它),然后在超级项目中使用它:

git submodule foreach git pull origin development

当我设置它时,我也交换到我希望将更改推送到已检出子模块的分支,如下所示:

cd extension
git checkout -b development #This will tell you this is a new branch, but I believe this means a new branch of the local git repository - this will get pushed to the 'development' branch
#Make your changes, commit etc.

我可以确认,当我按照上述步骤进行操作时,克隆/远程源项目中子模块的更改(推送时)会显示在同一项目的其他克隆/远程源中(不要忘记最后一个子模块拉取命令)

我希望这对你有用。