14

我想使用 git 子模块。

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

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

我需要采取的步骤来拉动我的项目的更改。

  1. git从父目录拉取
  2. 从父目录更新 git 子模块

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

  1. git pull 从子模块目录

让我担心的是http://git-scm.com/book/en/Git-Tools-Submodules的以下摘录

问题是您通常不想在分离的 HEAD 环境中工作,因为很容易丢失更改。如果您进行初始子模块更新,则在该子模块目录中提交而不创建要在其中工作的分支,然后从超级项目再次运行 git submodule update 而不同时提交,(??更新/提交/更新将丢失更改?) Git 会在不通知您的情况下覆盖您的更改。从技术上讲,您不会丢失工作,但不会有指向它的分支,因此检索起来会有些困难。

为避免此问题,请在子模块目录中使用 git checkout -b work 或类似的东西创建一个分支。当你第二次更新子模块时,它仍然会恢复你的工作,但至少你有一个指针可以返回。

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

我想知道除了上面列出的之外,我还需要采取哪些额外的步骤来防止损失。尤其是几个团队成员修改子模块,他们需要做什么才不会乱七八糟?

4

1 回答 1

24

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

如果您使用 Visual Studio,Git Source Control Provider 扩展是免费的(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 updategit submodule init. 阅读http://git-scm.com/book/en/Git-Tools-Submodules的“使用子模块克隆项目”部分。

克隆我的超级项目时让我感到震惊的是获得子模块的最新更改。请参阅Easy way pull 最新的所有子模块

我的变体是为签出的子模块使用“开发”分支(但您可以随意调用它),然后在超级项目中使用它:

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.

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

我希望这对你有用。

于 2013-01-10T13:39:39.177 回答