分类:Git| 发布时间:2014-05-06 07:13:52
本文主要介绍了如何组织需要依赖其他项目的代码库。
这种方法在CVS或Subversion中很流行。 简单来说,就是将所有子项目放到一个代码库中, 然后根据工作需要只签出需要的部分子项目。 不过这种方法不适用于Git,目前的Git架构不支持部分签出。
最简单的方法是将需要的库复制到你的项目,然后提交。
这种方法有以下优点:
不幸的是,这种方法有如下缺点:
这种方法很简单就不演示了
为了演示,首先创建一个名为myapp的代码库
$ cd myapp/
$ git init
Initialized empty Git repository in /tmp/myapp/.git/
$ ls
$ echo hello > hello.txt
$ git add hello.txt
$ git commit -m 'first commit'
[master (root-commit) ab46c32] first commit
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
将v1.6.0的git导入我们的代码库
$ ls
hello.txt
$ mkdir git
$ cd git
$ (cd ~/git.git && git archive v1.6.0) | tar -xf -
$ cd ..
$ ls
git/ hello.txt
$ git add git
$ git commit -m 'imported git v1.6.0'
接下来将Git从开始到v1.6.0的历史导入到我们的代码库
$ git pull -s ours ~/git.git refs/tags/v1.6.0
warning: no common commits
remote: Counting objects: 67034, done.
remote: Compressing objects: 100% (19135/19135), done.
remote: Total 67034 (delta 47938), reused 65706 (delta 46656)
Receiving objects: 100% (67034/67034), 14.33 MiB | 12587 KiB/s, done.
Resolving deltas: 100% (47938/47938), done.
From ~/git.git
* tag v1.6.0 -> FETCH_HEAD
Merge made by ours.
现在对git子项目作修改
$ cd git
$ echo 'I am a git contributor!' > contribution.txt
$ git add contribution.txt
$ git commit -m 'My first contribution to git'
Created commit 6c9fac5: My first contribution to git
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 git/contribution.txt
最后,更新我们的git到版本v1.6.0.1
$ git pull -s subtree ~/git.git refs/tags/v1.6.0.1
remote: Counting objects: 179, done.
remote: Compressing objects: 100% (72/72), done.
remote: Total 136 (delta 97), reused 100 (delta 61)
Receiving objects: 100% (136/136), 25.24 KiB, done.
Resolving deltas: 100% (97/97), completed with 40 local objects.
From ~/git.git
* tag v1.6.0.1 -> FETCH_HEAD
Merge made by subtree.
这种方法有以下优点:
当然这种方法有以下问题:
gitlinks是一个tree对象对commit对象的引用,下面来演示下如何创建gitlinks。
首先来创建一个代码库
$mkdir myapp
$cd myapp/
$git init
Initialized empty Git repository in /private/tmp/myapp/.git/
$echo hello > hello.txt
$git add hello.txt
$git commit -m 'first commit'
[master (root-commit) 804b31a] first commit
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
接下来,我们导入git项目,我们会直接导入,而不是使用git archive命令
$git clone ~/src/git/ git
Cloning into 'git'...
done.
$cd git/
$git checkout v1.6.0
Note: checking out 'v1.6.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at ea02eef... GIT 1.6.0
$cd ..
$ls
git hello.txt
$git add git
$git commit -m 'imported git v1.6.0'
[master 414b04d] imported git v1.6.0
1 file changed, 1 insertion(+)
create mode 160000 git
通常来说git add git和git add git/的效果是一样的, 但是当git本身是一个代码库时,这两个命令的效果时不一样的。 git add git表示创建一个gitlink而git add git/表示将git目录的文件都加到当前代码库下。
$git ls-tree HEAD
160000 commit ea02eef096d4bfcbb83e76cfab0fcb42dbcad35e git
100644 blob ce013625030ba8dba906f756967f9e9ca394464a hello.txt
git子目录的类型是commit。这里创建了一个gitlink。 Git会将gitlinks当成一个简单的指向其他代码库的指针。 大多数的Git操作,不会解引用gitlinks然后对子模块进行操作,比如:git clone。
$cd /tmp
$git clone myapp/ app2/
Cloning into 'app2'...
done.
$cd app2/
$ls
git hello.txt
$ls git/
$du git/
0 git/
git submodule命令并不是Git核心的一部分,实际上它就是一个成为git-submodule.sh的脚本。 可以通过git submodule update命令来更新子模块,这个命令实际上相当于以下操作:
$cd /tmp/app2/
$git ls-files --stage -- git
160000 ea02eef096d4bfcbb83e76cfab0fcb42dbcad35e 0 git
$rmdir git/
$git clone ~/src/git git
Cloning into 'git'...
done.
$cd git/
$git checkout ea02eef
Note: checking out 'ea02eef'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at ea02eef... GIT 1.6.0
不幸的是在使用git submodule update之前需要先做一下配置:
我们需要提供.gitmodules文件:
$cd /tmp/app2/
$cat > .gitmodules << EOF
> [submodule "git"]
> path = git
> url = /Users/chenjianlong/src/git
> EOF
(以上内容也可以通过命令git submodule add /Users/chenjianlong/src/git git来实现)
下一步,通过git submodule init来将.gitmodules文件的内容设置到.git/config文件中
$git submodule init
Submodule 'git' (/Users/chenjianlong/src/git) registered for path 'git'
$cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = /tmp/myapp/
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "git"]
url = /Users/chenjianlong/src/git
现在可以用git submodule update命令来更新子模块了
$rm -rf git/
$git submodule update
Cloning into 'git'...
done.
Submodule path 'git': checked out 'ea02eef096d4bfcbb83e76cfab0fcb42dbcad35e'
这是你需要注意的事:
如上可见,git submodule其实是相当复杂的,而且它是一个单独的命令。根据你的实际情况来决定要不要使用它。