如何把GIT仓库的子目录独立成新仓库

背景1:最近准备把公司某项目下的某个目录下的前端代码拆分出来,单独作为一个项目进行编译部署。那么,应该怎么操作GIT仓库才能把仓库的某个子目录独立出来,并保留之前的历史记录呢?

背景2:因为之前并不知道,有这样的操作可以实现将仓库的子目录独立成新仓库,我已经从头创建了一个新的仓库从零开始开发了,又如何并独立出来的仓库呢?

在网上查找到两种方法可以实现这样的操作:

假如我有一个项目 project,它的项目目录结构如下:

/project/
----/test/
----|----test.md
----README.md

我想把该项目下的test目录独立成一个新的仓库。

使用git filter-branch

1、clone一个新的project仓库到~/test

git clone path/to/project ~/test

2、通常刚clone出来的~/elake仓库本地只会有一个master分支,如果我们希望保存其他的分支,那就首先把它们创建出来:

cd ~/test
git branch -r br1 origin/br1
git branch -r br2 origin/br2

如果不希望保留其他的分支,就无需上操作。

3、删掉无用的origin

git remote rm origin

4、过滤所有历史提交,只保留对elake子目录有影响的提交,并且把子目录设为该仓库的根目录

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter test -- --all

其中各参数的意义如下:

  • –tag-name-filter cat : 该参数控制我们要如何保存旧的tag,参数值为bash命令,cat表示原样输出。所以,如果你不关心tag,就不需要这个参数了;
  • –prune-empty: 删除空的(对子目录没有影响的)的提交
  • –subdirectory-filter elake: 指定子模块路径
  • –all: 该参数必须跟在–后面,表示对所有分支做操作,即对上一步创建的所有本地分支做操作。所以,如果你只想保存当前分支,就不需要这个参数了

该命令执行完毕后,查看当前目录结构就会发现里面已经是子目录的内容了, git log查看提交历史已经正常保存了。

5、至此,主要工作已经完成。但是当前的仓库中还保存着一些不需要的object,如果想清理这些来减小当前仓库的体积

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

使用git subtree

git 1.7.11之后使用 git subtree 指令可以很简单地把GIT仓库下某个目录的 commit 都抽出來。

1、将project仓库中test目录的提交信息抽出为新的branch

cd path/to/project
git subtree split -P test -b test-new-br

2、新建test仓库,并从project的test-new-br branch中拉内容

mkdir ~/test
cd ~/test
git init
git pull path/to/project test-new-br

大功告成 《完》

参考资料:

Detach (move) subdirectory into separate Git repository

这篇文章目前没有评论

Leave a Reply

(必填项)

(必填项)

(可选)