如何把GIT仓库的子目录独立为子模块
2015-01-04 19:39
274 查看
http://graycarl.me/post/articles/git-split-subdir-to-submodule
最近在给考拉山后台添砖加瓦的过程中,发现了两个问题:
对于当前的同一套逻辑,我已经有4个view层工作在上面了,马上还要再加上一个view,专门用来显示分享出去的页面;
接下来还要再加上同步evernote这种异步任务;
而现在这些代码都还在同一个GIT仓库中;
这种混乱的场景已经快让我不能忍了,于是乎决定把这个大仓库中的所有
还好之前的代码结构还算比较好,所有
对GIT还没精通到这个程度,只能上网Google,现贴出方案;
当前的目录结构如下:
Clone一个新的仓库到目录
这时
通常刚clone出来的
最后
这一步是最重要的步骤,命令如下:
该命令过滤所有历史提交,保留对coloshine子目录有影响的提交,并且把子目录设为该仓库的根目录。下面解释下各参数意思:
--tag-name-filter cat 该参数控制我们要如何保存旧的tag,参数值为bash命令,cat表示原样输出。所以,如果你不关心tag,就不需要这个参数了;
--prune-empty 删除空的(对子目录没有影响的)的提交
--subdirectory-filter coloshine 指定子模块路径
-- --all 该参数必须跟在
该命令执行完毕后,查看当前目录结构就会发现里面已经是子目录的内容了。
至此,主要工作已经完成。但是当前的仓库中还保存这一下不需要的
这些命令到底是怎么work的我也没仔细研究,就不解释了。总是,我的实践证明它们是正常work的,仓库体积减小了不少。
最后,我们就可以把这个新的仓库提交到服务器上,然后把旧仓库中的
参考链接:
Detach
subdirectory into separate Git repository
Splitting a
subpath out into a new repository
另一种简单方式
http://blog.kidwm.net/341
以往要達到分拆子目錄成新的 repo ,就像這個問題在 Stack Overflow 上原本的解答那樣,得用上
git filter-branch 跟一堆繁複的流程才能達成,不過後來有人寫了 git-subtree來專門處理這件事,由於這個功能似乎太常被用到,所以在 git 1.7.11 以後就有內建這個模組了(但是不一定有裝上去),現在使用
git subtree 指令可以很簡單地把單一資料夾相關的 commit 都抽出來。
以下是我從 central 這個 repo 中把 wiki 獨立出來的過程:
如果還要徹底清理掉原本 central 裡 wiki 的資料:
雖然可以節省 repo 佔用的空間,但是這會 rewrite commits history,請斟酌使用。
值得一提的是,git subtree 原本是為了提供 git submodule 以外的另一種方便管理子專案的選擇,因此也有相關的用法可以嘗試看看。
至於把 repo 合併回來成一個子目錄嘛,雖然也做得到,不過與其真要這樣做好像還是用 git subtree 來管理會更好用一些。
另外關於 git filter-branch 的更多用法可以參看這篇文章。
最近在给考拉山后台添砖加瓦的过程中,发现了两个问题:
对于当前的同一套逻辑,我已经有4个view层工作在上面了,马上还要再加上一个view,专门用来显示分享出去的页面;
接下来还要再加上同步evernote这种异步任务;
而现在这些代码都还在同一个GIT仓库中;
这种混乱的场景已经快让我不能忍了,于是乎决定把这个大仓库中的所有
business和
model的代码独立到一个
submodule中,这样接下来就可以进一步的拆分各个view让它们都引用这个
submodule。
还好之前的代码结构还算比较好,所有
business和
model的代码都在一个名为
coloshine的目录中,所以接下来只要解决如何把一个子目录独立成一个
submodule并且保存分支和提交历史这个问题就好了。
对GIT还没精通到这个程度,只能上网Google,现贴出方案;
准备
当前的目录结构如下:coloshine-server ├── .... ├── coloshine -> 想要变成子模块的目录 ├── coloshine_account ├── coloshine_admin ├── coloshine_api ├── coloshine_pics ├── ...
Clone一个新的仓库到目录
coloshine
:::bash git clone coloshine-server coloshine
这时
coloshine仓库的目录结构应该是和
coloshine-server完全一样的。
选择要保存的分支
通常刚clone出来的coloshine仓库本地只会有一个分支(比如master),如果我们希望在马上要做的子模块中保存其他的分支,那就首先把它们创建出来:
:::bash git branch -r br1 origin/br1 git branch -r br2 origin/br2
最后
origin这个remote是不需要的,把它删除了
:::bash git remote rm origin
转化成子模块
这一步是最重要的步骤,命令如下::::bash git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter coloshine -- --all
该命令过滤所有历史提交,保留对coloshine子目录有影响的提交,并且把子目录设为该仓库的根目录。下面解释下各参数意思:
--tag-name-filter cat 该参数控制我们要如何保存旧的tag,参数值为bash命令,cat表示原样输出。所以,如果你不关心tag,就不需要这个参数了;
--prune-empty 删除空的(对子目录没有影响的)的提交
--subdirectory-filter coloshine 指定子模块路径
-- --all 该参数必须跟在
--后面,表示对所有分支做操作,即对上一步创建的所有本地分支做操作。所以,如果你只想保存当前分支,就不需要这个参数了
该命令执行完毕后,查看当前目录结构就会发现里面已经是子目录的内容了。
git log查看提交历史已经正常保存了。
至此,主要工作已经完成。但是当前的仓库中还保存这一下不需要的
object,如果想清理这些来减小当前仓库的体积,再看下一步。
清理
:::bash git reset --hard git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d git reflog expire --expire=now --all git gc --aggressive --prune=now
这些命令到底是怎么work的我也没仔细研究,就不解释了。总是,我的实践证明它们是正常work的,仓库体积减小了不少。
最后,我们就可以把这个新的仓库提交到服务器上,然后把旧仓库中的
coloshine子目录删除并以
submodule的方式添加
coloshine仓库就好了。
参考链接:
Detach
subdirectory into separate Git repository
Splitting a
subpath out into a new repository
另一种简单方式
http://blog.kidwm.net/341
使用 git subtree 來分拆子目錄成獨立的新 repo
以往要達到分拆子目錄成新的 repo ,就像這個問題在 Stack Overflow 上原本的解答那樣,得用上git filter-branch 跟一堆繁複的流程才能達成,不過後來有人寫了 git-subtree來專門處理這件事,由於這個功能似乎太常被用到,所以在 git 1.7.11 以後就有內建這個模組了(但是不一定有裝上去),現在使用
git subtree 指令可以很簡單地把單一資料夾相關的 commit 都抽出來。
以下是我從 central 這個 repo 中把 wiki 獨立出來的過程:
cd central git subtree split -P wiki -b mediawiki (這會把 wiki 這個資料夾抽出來成為一個叫 mediawiki 的 branch) cd .. mkdir wiki.moztw.org cd wiki.moztw.org git init git pull ../central mediawiki (從 central 中把 mediawiki 這個 branch 的資料拉回來) git remote add origin https://github.com/moztw/wiki.moztw.org.git git push origin -u master |
git filter-branch -f --index-filter "git rm -r -f -q --cached --ignore-unmatch wiki" --prune-empty HEAD |
值得一提的是,git subtree 原本是為了提供 git submodule 以外的另一種方便管理子專案的選擇,因此也有相關的用法可以嘗試看看。
至於把 repo 合併回來成一個子目錄嘛,雖然也做得到,不過與其真要這樣做好像還是用 git subtree 來管理會更好用一些。
另外關於 git filter-branch 的更多用法可以參看這篇文章。
相关文章推荐
- 如何把GIT仓库的子目录独立成新仓库
- 如何将一个已存在的目录转换为一个 GIT 项目并托管到 GITHUB 仓库
- 如何将现有 git 仓库中的子项目单独抽出来作为一个独立仓库并保留其提交历史
- 如何将一个已存在的目录转换为一个 GIT 项目并托管到 GITHUB 仓库
- 我如何添加一个空目录到Git仓库?
- 我如何添加一个空目录到Git仓库?
- 如何从一个 git repo 中分离出部分目录或文件至独立的 git repo
- 如何添加一个空目录到Git仓库?
- 如何将一个已存在的目录转换为一个 GIT 项目并托管到 GITHUB 仓库
- [Git]06 如何提交空目录
- 如何将文件夹及文件夹下的文件保存到git的远程仓库
- 如何利用单台服务器实现10万多个Git仓库托管
- 如何通过ssh与Git远程仓库建立加密连接
- git如何删除远程仓库的某次错误提交
- 如何在windows下使用git及github仓库管理项目
- git如何删除子模块
- 如何快速的搜索git仓库
- 如何 clone git 项目到一个非空目录
- 如何永久删除git仓库中敏感文件的提交记录
- git如何复制远程仓库