假设我有两个存储库aye
,bee
并且我想摆脱bee
,以这样的方式,bee/master
在 的新子目录(几层深)中“重播”的线性历史记录aye
。我只想要文件和提交消息,我不关心提交 ID。我做想要一个合理的历史,所以git subtree add --prefix=subdirectory
和git read-tree --prefix=subdirectory/
不是我要找的。
这两个存储库都是私有的,因此不存在为其他人重写历史记录的风险。然而,bee
做有一个子模块cee
。
答案1
cd /path/to/bee
git filter-branch --force --prune-empty --tree-filter '
dir="my fancy/target directory"
if [ ! -e "$dir" ]
then
mkdir --parents "${dir}"
git ls-tree --name-only "$GIT_COMMIT" | xargs -I files mv files "$dir"
fi'
git log --stat
应该显示出现在my fancy/target directory
.现在你可以将历史合并到aye
轻松地:
cd /path/to/aye
git remote add -f bee /path/to/bee
git checkout -b bee-master bee/master
git rebase master
git checkout master
git rebase bee-master
在以下位置重新创建子模块aye
:
git submodule add git://my-submodule 'my fancy/target directory/my-submodule'
最后你可以清理aye
:
git rm 'my fancy/target directory/.gitmodules'
git branch --delete --force bee-master
git remote remove bee
您可能还需要修复存储库中的任何绝对路径(例如在.gitignore
)
答案2
更快的版本(帽子提示这个答案):
git filter-branch --index-filter 'git ls-files -s | sed "s-\t\"*-&newsubdir/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"'
替换newsubdir
为您喜欢的任何目录或嵌套目录。在 macOS 上,您可能必须使用gsed
(sed
安装brew install gnu-sed
)。