我的仓库中有几个子树(例如./sub1/
,./sub2/
,...),我想将其提取到单独的回购中,保留提交历史和相同的目录结构,即新的回购for sub1
应该有来自主回购的./sub1/
子树。我怎么能这样做?
答案 0 :(得分:5)
你可以使用git的filter-branch和子树过滤器。
以下是步骤:
克隆工作副本。此操作将更改本地仓库,因此我们必须先拥有工作副本。您可以执行如下的git克隆,也可以只复制它。
git clone --no-hardlinks <original repository> <working copy>
使用子树文件管理器。
cd <working copy>
git filter-branch --subdirectory-filter <subdir path to be splited> --prune-empty --tag-name-filter cat -- --all
# reset current working directory
git reset --hard
我们完成了我们的任务,最好做一些清洁工作,因为很多旧物体无法到达。
删除旧遥控器
git remote rm origin
删除旧的reflog
# clean unneeded reflog in order to free space
refbak=$(git for-each-ref --format="%(refname)" refs/original/)
if [ -n "$refbak" ];then
echo -n $refbak | xargs -n 1 git update-ref -d
fi
git reflog expire --expire=now --all
重新包装并压缩回购
# prune loose objects
git gc --aggressive --prune=now
这将使repos结构从
更改repo/
|-- sub1/
|-- sub11
|-- sub12
|-- sub2
到
repo/
|-- sub11
|-- sub12
但是,似乎你想要它成为
repo/
|-- sub1/
|-- sub11
|-- sub12
然后,还有一个步骤需要完成,用index-filter重写git commit history。
# replace <subdir path> with the actual subdir path, for this case, it should be "sub1"
git filter-branch --index-filter 'git ls-files -s | sed "s-\t-&<subdir path>/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD