TSL 20200506 Managing Git projects with submodules and subtrees

This commit is contained in:
Xiaobin.Liu 2020-05-11 00:11:45 +08:00
parent 791e6d91e0
commit 69366c1952
2 changed files with 211 additions and 212 deletions

View File

@ -1,212 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (lxbwolf)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Managing Git projects with submodules and subtrees)
[#]: via: (https://opensource.com/article/20/5/git-submodules-subtrees)
[#]: author: (Manaswini Das https://opensource.com/users/manaswinidas)
Managing Git projects with submodules and subtrees
======
Submodules and subtrees help you manage child projects across multiple
repositories.
![Digital creative of a browser on the internet][1]
If you are into open source development, you have probably worked with Git to manage source code. You might have come across projects with numerous dependencies and/or sub-projects. How do you manage them?
For an open source organization, it can be tricky to achieve single-source documentation and dependency management for the community _and_ the product. The documentation and project often end up fragmented and redundant, which makes them difficult to maintain.
### The need
Suppose you want to use a single project as a child project inside a repository. The traditional method is just to copy the project to the parent repository. But, what if you want to use the same child project in many parent repositories? It wouldn't be feasible to copy the child project into every parent and have to make changes in all of them whenever you update it. This would create redundancy and inconsistency in the parent repositories and make it difficult to update and maintain the child project.
### Git submodules and subtrees
What if you could put one project within another using a single command? What if you could just add the project as a child to any number of projects and push changes on the go, whenever you want to? Git provides solutions for this: Git submodules and Git subtrees. These tools were created to support code-sharing development workflows on a more modular level, aspiring to bridge the gap between the Git repository's source-code management (SCM) and the sub-repos within it.
![Cherry tree growing on a mulberry tree][2]
Cherry tree growing on a mulberry tree
This is a real-life scenario of the concepts this article will cover in detail. If you're already familiar with trees, here is what this model will look like:
![Tree with subtrees][3]
CC BY-SA opensource.com
### What are Git submodules?
Git provides submodules in its default package that enable Git repositories to be nested within other repositories. To be precise, the Git submodule points to a specific commit on the child repository. Here is what Git submodules look like in my [Docs-test][4] GitHub repo:
![Git submodules screenshot][5]
The format **[folder@commitId][6]** indicates that the repository is a submodule, and you can directly click on the folder to go to the child repository. The config file called **.gitmodules** contains all the submodule repository details. My repo's **.gitmodules** file looks like this:
![Screenshot of .gitmodules file][7]
You can use the following commands to use Git submodules in your repositories.
#### Clone a repository and load submodules
To clone a repository containing submodules:
```
`$ git clone --recursive <URL to Git repo>`
```
If you have already cloned a repository and want to load its submodules:
```
`$ git submodule update --init`
```
If there are nested submodules:
```
`$ git submodule update --init --recursive`
```
#### Download submodules
Downloading submodules sequentially can be a tedious task, so **clone** and **submodule update** will support the **\--jobs** or **-j** parameter.
For example, to download eight submodules at once, use:
```
$ git submodule update --init --recursive -j 8
$ git clone --recursive --jobs 8 &lt;URL to Git repo&gt;
```
#### Pull submodules
Before running or building the parent repository, you have to make sure that the child dependencies are up to date.
To pull all changes in submodules:
```
`$ git submodule update --remote`
```
#### Create repositories with submodules
To add a child repository to a parent repository:
```
`$ git submodule add <URL to Git repo>`
```
To initialize an existing Git submodule:
```
`$ git submodule init`
```
You can also create branches and track commits in your submodules by adding **\--update** to your **submodule update** command:
```
`$ git submodule update --remote`
```
#### Update submodule commits
As explained above, a submodule is a link that points to a specific commit in the child repository. If you want to update the commit of the submodule, don't worry. You don't need to specify the latest commit explicitly. You can just use the general **submodule update** command:
```
`$ git submodule update`
```
Just add and commit as you normally would to create and push the parent repository to GitHub.
#### Delete a submodule from a parent repository
Merely deleting a child project folder manually won't remove the child project from the parent repository. To delete a submodule named **childmodule**, use:
```
`$ git rm -f childmodule`
```
Although Git submodules may appear easy to work with, it can be difficult for beginners to find their way around them.
### What are Git subtrees?
Git subtrees, introduced in Git 1.7.11, allow you to insert a copy of any repository as a subdirectory of another one. It is one of several ways Git projects can inject and manage project dependencies. It stores the external dependencies in regular commits. Git subtrees provide clean integration points, so they're easier to revert.
If you use the [subtrees tutorial provided by GitHub][8] to use subtrees, you won't see a **.gittrees** config file in your local whenever you add a subtree. This makes it difficult to recognize subtrees because subtrees look like general folders, but they are copies of the child repository. The version of Git subtree with the **.gittrees** config file is not available with the default Git package, so to get the git-subtree with **.gittrees** config file, you must download git-subtree from the [**/contrib/subtree** folder][9] in the Git source repository.
You can clone any repository containing subtrees, just like any other general repository, but it may take longer because entire copies of the child repository reside in the parent repository.
You can use the following commands to use Git subtrees in your repositories.
#### Add a subtree to a parent repository
To add a new subtree to a parent repository, you first need to **remote add** it and then run the **subtree add** command, like:
```
$ git remote add remote-name &lt;URL to Git repo&gt;
$ git subtree add --prefix=folder/ remote-name &lt;URL to Git repo&gt; subtree-branchname
```
This merges the whole child project's commit history to the parent repository.
#### Push and pull changes to and from the subtree
```
`$ git subtree push-all`
```
or
```
`$ git subtree pull-all`
```
### Which should you use?
Every tool has pros and cons. Here are some features that may help you decide which is best for your use case.
* Git submodules have a smaller repository size since they are just links that point to a specific commit in the child project, whereas Git subtrees house the entire child project along with its history.
* Git submodules need to be accessible in a server, but subtrees are decentralized.
* Git submodules are mostly used in component-based development, whereas Git subtrees are used in system-based development.
A Git subtree isn't a direct alternative to a Git submodule. There are certain caveats that guide where each can be used. If there is an external repository you own and are likely to push code back to, use Git submodule since it is easier to push. If you have third-party code that you are unlikely to push to, use Git subtree since it is easier to pull.
Give Git subtrees and submodules a try and let me know how it goes in the comments.
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/5/git-submodules-subtrees
作者:[Manaswini Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/manaswinidas
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
[2]: https://opensource.com/sites/default/files/uploads/640px-bialbero_di_casorzo.jpg (Cherry tree growing on a mulberry tree)
[3]: https://opensource.com/sites/default/files/subtree_0.png (Tree with subtrees)
[4]: https://github.com/manaswinidas/Docs-test/
[5]: https://opensource.com/sites/default/files/uploads/git-submodules_github.png (Git submodules screenshot)
[6]: mailto:folder@commitId
[7]: https://opensource.com/sites/default/files/uploads/gitmodules.png (Screenshot of .gitmodules file)
[8]: https://help.github.com/en/github/using-git/about-git-subtree-merges
[9]: https://github.com/git/git/tree/master/contrib/subtree

View File

@ -0,0 +1,211 @@
[#]: collector: (lujun9972)
[#]: translator: (lxbwolf)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Managing Git projects with submodules and subtrees)
[#]: via: (https://opensource.com/article/20/5/git-submodules-subtrees)
[#]: author: (Manaswini Das https://opensource.com/users/manaswinidas)
使用子模块和子仓库管理 Git 项目
======
使用子模块和子仓库来帮助你管理多个仓库中共有的子项目。
![Digital creative of a browser on the internet][1]
如果你参与了开源项目的开发,那么你可能会用 Git 来管理你的源码。你可能遇到过有很多依赖和/或子项目的项目。你怎么管理它们?
对于一个开源组织,社区*和*产品想要实现单一来源文档和依赖管理比较棘手。文档和项目往往会碎片化和变得冗余,这致使它们很难维护。
### 必要性
假设你想要在一个仓库中把一个项目作为子项目来用。传统的方法是把该项目复制到父仓库中。但是,如果你想要在多个父项目中用同一个子项目呢?(如果)把子项目复制到所有父项目中,当有更新时,你不得不在每个父项目中都做修改,这是不太可行的。(因为)这会导致父项目中的冗余和数据不一致,也会使更新和维护子项目变得很困难。
### Git 子模块和子仓库
如果你可以用一条命令把一个项目放进另一个项目中会怎样呢如果你随时可以把一个项目作为子项目添加到任意数目的项目中并可以同步更新修改呢Git 提供了这类问题的解决方案Git 子模块和 Git 子仓库。创建这些工具的目的是以更加模块化的水平来支持共用代码的开发工作流,(创建者)意在消除 Git 仓库<ruby>源码管理<rt>source-code management</rt></ruby>与它下面的子仓库间的障碍。
![Cherry tree growing on a mulberry tree][2]
生长在桑树上的樱桃树
下面是本文要详细介绍的概念的一个真实应用场景。如果你已经很熟悉 tree这个模型看起来是下面这样
![Tree with subtrees][3]
CC BY-SA opensource.com
### Git 子模块是什么?
Git 在它默认的包中提供了子模块,子模块可以把 Git 仓库嵌入到其他仓库中。确切地说Git 子模块是指向子仓库中的某次提交。下面是我 [Docs-test][4] GitHub 仓库中的 Git 子模块:
![Git submodules screenshot][5]
**[文件夹@提交 Id][6]** 格式表明这个仓库是一个子模块,你可以直接点击文件夹进入该子仓库。名为 **.gitmodules** 的配置文件包含所有子模块仓库的详细信息。我的仓库的 **.gitmodules** 文件如下:
![Screenshot of .gitmodules file][7]
你可以用下面的命令在你的仓库中使用 Git 子模块:
#### 克隆一个仓库并加载子模块
克隆一个含有子模块的仓库:
```
`$ git clone --recursive <URL to Git repo>`
```
如果你之前已经克隆了仓库,现在想加载它的子模块:
```
`$ git submodule update --init`
```
如果有嵌套的子模块:
```
`$ git submodule update --init --recursive`
```
#### 下载子模块
串行地连续下载多个子模块是很枯燥的工作,所以 **clone****submodule update** 会支持 **\--jobs** 或 **-j** 参数:
例如,想一次下载 8 个子模块,使用:
```
$ git submodule update --init --recursive -j 8
$ git clone --recursive --jobs 8 &lt;URL to Git repo&gt;
```
#### 拉取子模块
在运行或构建父项目之前,你需要确保依赖的子项目都是最新的。
拉取子模块的所有修改:
```
`$ git submodule update --remote`
```
#### 使用 submodule 创建仓库:
向一个父仓库添加子仓库:
```
`$ git submodule add <URL to Git repo>`
```
初始化一个已存在的 Git 子模块:
```
`$ git submodule init`
```
你也可以通过为 **submodule update** 命令添加 **\--update** 参数在子模块中创建分支和追踪提交:
```
`$ git submodule update --remote`
```
#### 更新子模块提交
上面提到过,一个子模块就是一个指向子仓库中某次提交的链接。如果你想更新子模块的提交,不要担心。你不需要显式地指定最新的提交。你只需要使用通用的 **submodule update** 命令:
```
`$ git submodule update`
```
就像你平时创建父仓库和把父仓库推送到 GitHub 那样添加和提交就可以了。
#### 从一个父仓库中删除一个子模块
仅仅手动删除一个子项目文件夹不会从父项目中移除这个子项目。想要删除名为 **childmodule** 的子模块,使用:
```
`$ git rm -f childmodule`
```
虽然 Git 子模块看起来很容易上手,但是对于初学者来说,有一定的使用门槛。
### Git 子仓库是什么?
Git 子仓库,是在 Git 1.7.11 引入的,让你可以把任何仓库的副本作为子目录嵌入另一个仓库中。它是 Git 项目可以注入和管理项目依赖的几种方法之一。它在常规的提交中保存了外部依赖信息。Git 子仓库提供了整洁的集成点,因此很容易复原它们。
如果你参考 [GitHub 提供的子仓库教程][8] 来使用子仓库,那么无论你什么时候添加子仓库,在本地都不会看到 **.gittrees** 配置文件。这让我们很难分辨哪个是子仓库,因为它们看起来很像普通的文件夹,但是它们却是子仓库的副本。默认的 Git 包中不提供带 **.gittrees** 配置文件的 Git 子仓库版本,因此如果你想要带 **.gittrees** 配置文件的 git-subtree必须从 Git 源码仓库的 [**/contrib/subtree** 文件夹][9] 下载 git-subtree。
你可以像克隆其他常规的仓库那样克隆任何含有子仓库的仓库,但由于在父仓库中有整个子仓库的副本,因此克隆过程可能会持续很长时间。
你可以用下面的命令在你的仓库中使用 Git 子仓库。
#### 向父仓库中添加一个子仓库
想要向父仓库中添加一个子仓库,首先你需要执行 **remote add**,之后执行 **subtree add** 命令:
```
$ git remote add remote-name &lt;URL to Git repo&gt;
$ git subtree add --prefix=folder/ remote-name &lt;URL to Git repo&gt; subtree-branchname
```
上面的命令会把整个子项目的提交历史合并到父仓库。
#### 向子仓库推送修改以及从子仓库拉取修改
```
`$ git subtree push-all`
```
或者
```
`$ git subtree pull-all`
```
### 你应该使用哪个?
任何工具都有优缺点。下面是一些可能会帮助你决定哪种最适合你的特性:
* Git 子模块的仓库占用空间更小,因为它们只是指向子项目的某次提交的链接,而 Git 子仓库保存了整个子项目及其提交历史。
* Git 子模块需要在服务器中可访问,但子仓库是去中心化的。
* Git 子模块大量用于基于组件的开发,而 Git 子仓库多用于基于系统的开发。
Git 子仓库并不是 Git 子模块的直接可替代项。有明确的说明来指导我们该使用哪种。如果有一个归属于你的外部仓库,使用场景是向它回推代码,那么就使用 Git 子模块,因为推送代码更容易。如果你有第三方代码,且不会向它推送代码,那么使用 Git 子仓库,因为拉取代码更容易。
自己尝试使用 Git 子仓库和子模块,然后在评论中留下你的使用感想。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/5/git-submodules-subtrees
作者:[Manaswini Das][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/manaswinidas
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
[2]: https://opensource.com/sites/default/files/uploads/640px-bialbero_di_casorzo.jpg (Cherry tree growing on a mulberry tree)
[3]: https://opensource.com/sites/default/files/subtree_0.png (Tree with subtrees)
[4]: https://github.com/manaswinidas/Docs-test/
[5]: https://opensource.com/sites/default/files/uploads/git-submodules_github.png (Git submodules screenshot)
[6]: mailto:folder@commitId
[7]: https://opensource.com/sites/default/files/uploads/gitmodules.png (Screenshot of .gitmodules file)
[8]: https://help.github.com/en/github/using-git/about-git-subtree-merges
[9]: https://github.com/git/git/tree/master/contrib/subtree