2
我的回购中有几个子树(例如./sub1/
,./sub2/
,..),我想将其提取到单独的回购中,保留提交历史记录和相同的目录结构,即sub1
的新回购应具有./sub1/
子树回购。我怎样才能做到这一点?从git repo中提取子目录到另一个repo并保留dir结构?
我的回购中有几个子树(例如./sub1/
,./sub2/
,..),我想将其提取到单独的回购中,保留提交历史记录和相同的目录结构,即sub1
的新回购应具有./sub1/
子树回购。我怎样才能做到这一点?从git repo中提取子目录到另一个repo并保留dir结构?
你可以使用git的filter-branch和子树过滤器。
步骤如下:
克隆的工作副本。这个操作会改变本地回购,所以我们必须先有一个工作副本。你可以像下面那样做一个git clone,或者直接拷贝它。
git clone --no-hardlinks <original repository> <working copy>
使用子树fileter。
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
删除旧引用日志
# 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
这将使从
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