git subtree有效管理公共第三方lib

  如果你的项目中有很多第三方的lib,你希望使用它,并且也希望可能对该lib做修改并且贡献到原始的项目中去,或者你的项目希望模块化,分为几个repo单独维护,那么git subtree就是一个选择。

  git subtree是附属于git的附加工具,默认情况下并不会安装。https://github.com/git/git/tree/master/contrib/subtree。

# git clone https://github.com/git# cd git

# make prefix=/usr/local/git install
# echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
# source /etc/bashrc# cd contrib/subtree# make prefix=/usr/local/git/bin
# make prefix=/usr/local/git/bin install
# make prefix=/usr/local/git/bin install-doc
# cp git-subtree /usr/local/git/bin
就ok了!

  在本文中,我们假设我们工作在subtree-p这个项目中(放在github上的一个repo),而在该项目中,我们需要subtree-sub这个子模块(或者说是Lib).

  当前我们的subtree-p项目中,没有引入任何subtree-sub这个模块,现在我们通过以下命令来实现:

(master)$ git remote add subtree-sub-remote https://github.com/cnweibo/subtree-sub.git
(master)$ git remote -v
origin  https://github.com/cnweibo/subtree-p.git (fetch)
origin  https://github.com/cnweibo/subtree-p.git (push)
subtree-sub-remote      https://github.com/cnweibo/subtree-sub.git (fetch)
subtree-sub-remote      https://github.com/cnweibo/subtree-sub.git (push)
(master)$ pwd
/home/cabox/workspace/subtreetest/subtree-p
(master)$ ls
README.md
(master)$ git subtree add --prefix=mysubtree subtree-sub-remote master
git fetch subtree-sub-remote master
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/cnweibo/subtree-sub
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> subtree-sub-remote/master
Added dir ‘mysubtree‘
(master)$ ls
README.md  mysubtree
(master)$ ls -la mysubtree/
total 12
drwxrwxr-x 2 cabox cabox 4096 May 31 02:14 .
drwxrwxr-x 4 cabox cabox 4096 May 31 02:14 ..
-rw-rw-r-- 1 cabox cabox   14 May 31 02:14 README.md     

上面的一系列命令中,首先在subtree-p项目目录中引入了subtree-sub这个子项目,它存放在目录mysubtree中,和我们的subtree-sub-remote这个remote相对应。这时,subtree-p项目由于增加了新的目录(subtree-sub子项目repo),因此需要commit和push.

注意:在mysubtree这个子目录中是没有任何.git文件的,它实际上是subtree-sub这个子项目repo的纯代码copy!!

(master)$ git s
On branch master
Your branch is ahead of ‘origin/master‘ by 2 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean
(master)$ git push
Username for ‘https://github.com‘: kidsit
Password for ‘https://[email protected]‘:
Counting objects: 5, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 528 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/cnweibo/subtree-p.git
   67da25d..c1e6018  master -> master       

这时,我们查看在github上的subtree-p repo,你就可以看到这个父项目已经引入了mysubtree(代表了subtree-sub repo!)

现在我们在parent项目中对子项目做修改并且commit, push:

(master)$ echo "kidsit add subfile1 within parent" >subfile1
(master)*$ git s
On branch master
Your branch is up-to-date with ‘origin/master‘.
Untracked files:
  (use "git add <file>..." to include in what will be committed)                                                                                                           

        subfile1                                                                                                                                                           

nothing added to commit but untracked files present (use "git add" to track)
(master)*$ git a .
(master)*$ git ci "kidsit add subfile1 within parent"
[master ed30a68] kidsit add subfile1 within parent
 1 file changed, 1 insertion(+)
 create mode 100644 mysubtree/subfile1
(master)$ git s
On branch master
Your branch is ahead of ‘origin/master‘ by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean
(master)$ git push
Username for ‘https://github.com‘: kidsit
Password for ‘https://[email protected]‘:
Counting objects: 4, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 398 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To https://github.com/cnweibo/subtree-p.git
   c1e6018..ed30a68  master -> master
(master)$                      

这时我们再查看github上的subtree-p我们就能看到我们对子项目的新的改动了:

我们来继续模拟代码开发过程:修改subtree-p和subtree-sub后,统一一次性做一个提交:

(master)$ echo "kidsit change README for p" >README.md
(master)*$ echo "kidsit add new subfileNew2 " >mysubtree/subfileNew2
(master)*$ git s
On branch master
Your branch is up-to-date with ‘origin/master‘.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)                                                                                                

        modified:   README.md                                                                                                                                              

Untracked files:
  (use "git add <file>..." to include in what will be committed)                                                                                                           

        mysubtree/subfileNew2                                                                                                                                              

no changes added to commit (use "git add" and/or "git commit -a")
(master)*$ git a .
(master)*$ git ci "kidsit change p and s in ONE commit"
[master a27d335] kidsit change p and s in ONE commit
 2 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 mysubtree/subfileNew2
(master)$ git push
Username for ‘https://github.com‘: kidsit
Password for ‘https://[email protected]‘:
Counting objects: 5, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 461 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/cnweibo/subtree-p.git
   ed30a68..a27d335  master -> master
(master)$                               

这时,我们要注意,我们再subtree-p项目中对父项目和子项目分别都做了修改,但是子项目本身的repo还没有做过任何更新,它根本不知道你曾经做过修改,这时,如果你希望将你对子项目的修改贡献出来,可以执行git subtree push命令

(master)$ git push
Username for ‘https://github.com‘: kidsit
Password for ‘https://[email protected]‘:
Counting objects: 5, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 461 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/cnweibo/subtree-p.git
   ed30a68..a27d335  master -> master
(master)$ git subtree push --prefix=mysubtree/ subtree-sub-remote master
git push using:  subtree-sub-remote master
Username for ‘https://github.com‘: kidsit
Password for ‘https://[email protected]‘:
Counting objects: 6, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 563 bytes | 0 bytes/s, done.
Total 6 (delta 1), reused 0 (delta 0)
To https://github.com/cnweibo/subtree-sub.git
   9a0ef93..001c5d8  001c5d86c4da43ab676aaeb49763d5353353159f -> master                                                                                                    

上面我们分别对subtree-p这个父项目和subtree-sub这个子项目分别作了push操作分享(一般来说对子项目push是非常少见的动作,因为我们更多的是拿别人的lib来用而不是开发),这时如果我们去看github上的两个项目repo的commit历史,你会发现两个repo上都有了同一个commit!!

正因为如此,我们最好是将父项目和子项目分别做commit,不要混淆在一起!这样做的好处是git subtree push时,git会自动将对父项目和子项目的commit区分清楚的,对父项目的修改不会出现在子项目repo修改历史中!

时间: 2024-10-03 14:45:41

git subtree有效管理公共第三方lib的相关文章

git subtree:无缝管理通用子项目

移动互联网的爆发以及响应式页面的尴尬症,开发web和mobile项目成为了标配,当然实际情况下,会有更多的项目. 多项目开发对于前端来说是个很大的挑战? 重复,重复的前端架构,重复的前端依赖,重复的工具函数等? 局限,不同后台有不同的规则,"因地制宜"真难受,刚伺候好rails又突然来个php? 最优,后台工程做前端构建,总是显得不够"最优". 所以,我们需要单独抽离出前端开发项目,按照前端的方式来组织代码,通过构建工具来对前端资源文件做最优处理那么新问题来了,如何

使用GIT SUBTREE集成项目到子目录(转)

原文:http://aoxuis.me/post/2013-08-06-git-subtree 使用场景 例如,在项目Game中有一个子目录AI.Game和AI分别是一个独立的git项目,可以分开维护.为了避免直接复制粘贴代码,我们希望Game中的AI子目录与AI的git项目关联,有3层意思: AI子目录使用AI的git项目来填充,内容保持一致. 当AI的git项目代码有更新,可以拉取更新到Game项目的AI子目录来. 反过来,当Game项目的AI子目录有变更,还可以推送这些变更到AI的git项

git subtree 使用

这个是备忘录.原网页(https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec , http://cncc.bingj.com/cache.aspx?q=master+git+subtree&d=5034897297048421&mkt=zh-CN&setlang=en-US&w=LLr-ePxnq8vxmyPDrHjzRWkbxVPwbcO4)被gfw墙,从cache中复制过来的,以备忘. Mas

Git subtree和Git submodule

git submodule允许其他的仓库指定以一个commit嵌入仓库的子目录. git subtree替代git submodule命令,合并子仓库到项目中的子目录.不用像submodule那样每次子项目修改了后要init和update.万一哪次没update就直接"commit -a" 或者 "add ." 全commit上去就悲剧了. git subtree虽然比git submodule更好用,但也不是特别完美的解决方案,使用时一定要特别注意. git-su

基于git的源代码管理模型——git flow

说明: 本文以nvie的“a successful git branching model”为蓝本,结合我个人理解写成.如有谬误,还请各位指出.多谢! Note: This article is highly based on nvie's a successful git branching model. Thanks nvie. Git Flow 是什么 Git Flow是构建在Git之上的一个组织软件开发活动的模型,是在Git之上构建的一项软件开发最佳实践.Git Flow是一套使用Git

Git学习 -- 标签管理

新建标签 git tag <tagname>   默认为HEAD,也可以指定一个commit id eg.   git tag v0.9  git tag v1.0 31aa59c git tag <tagname> -m "xxx"   可以指定标签信息 git tag -s <tagname>             可以用PGP签名标签 查看标签 git tag     查看所有标签 git show <tagname>    参看

无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它?

Error: E: 无法获得锁 /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它? 解 决方法一: #:ps -aux (列出进程,形式如) root 5765 0.0 1.0 18204 15504 ? SN 04:02 0:00 apt-get -qq -d 找到最后一列以apt-get 开头的进程 #:sudo kill -9 该进

git 实现分支管理项目,是羡慕管理更高效;

利用git 的分支管理的能力实现更有章法的协同开发的模式: 其实在我们进行 git init 时就创建了 master 的主分支: 那现在我如何建立第二个分支呢? :git branch local 初始时分支的内容是完全和主分支是一样的,在分支中所有的操作都不影响主分支里的情况,你可以在其中做任何修改: 如何查看分支呢? :git branch local * master 星号是表示当前所在的分支:其实两个分支一模一样,只是大家都是把master当作主分支的: 如何切换分支呢? :git c

VS2015 Git 源码管理工具简单入门

1.VS Git插件 1.1 环境 VS2015+GitLab 1.2 Git操作过程图解 1.3 常见名词解释 拉取(Pull):将远程版本库合并到本地版本库,相当于(Fetch+Meger) 获取(Fetch):从远程版本库获得最新版本 合并(Meger):将两个版本库进行合并操作 提交(Commit):将所做的更改,存入本地暂存库 推送(Push):将所做的更改,存入远程版本库 同步(Pull+Push):先将远程库拉取,再将本地库推送到远程库,相当于(Pull+Push) 变基到(Swi