此问题基于Detach subdirectory into separate Git repository
我想要分离两个子目录,而不是分离单个子目录。例如,我的当前目录树如下所示:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ我希望是这样的:
/apps
/AAA
/libs
/XXXgit filter-branch的--subdirectory-filter参数将不起作用,因为它在第一次运行时会删除除给定目录之外的所有内容。我认为对所有不需要的文件使用--index-filter参数都可以(尽管很繁琐),但是如果我尝试多次运行它,我会得到以下消息:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f有什么想法吗?提亚
发布于 2010-06-07 20:51:32
在这里回答我自己的问题...经过大量的试验和错误之后。
我结合使用了git subtree和git-stitch-repo,成功做到了这一点。这些说明基于:
使用git子树在项目之间共享代码的存储库-适合工作的http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/
首先,我将想要保存到各自独立存储库中的目录提取出来:
cd origRepo
git subtree split -P apps/AAA -b aaa
git subtree split -P libs/XXX -b xxx
cd ..
mkdir aaaRepo
cd aaaRepo
git init
git fetch ../origRepo aaa
git checkout -b master FETCH_HEAD
cd ..
mkdir xxxRepo
cd xxxRepo
git init
git fetch ../origRepo xxx
git checkout -b master FETCH_HEAD然后,我创建了一个新的空存储库,并将最后两个导入/缝合到其中:
cd ..
mkdir newRepo
cd newRepo
git init
git-stitch-repo ../aaaRepo:apps/AAA ../xxxRepo:libs/XXX | git fast-import这将创建两个分支master-A和master-B,每个分支都包含一个缝合的repos的内容。要组合它们并进行清理,请执行以下操作:
git checkout master-A
git pull . master-B
git checkout master
git branch -d master-A
git branch -d master-B现在,我不太确定这是如何/何时发生的,但是在第一个checkout和pull之后,代码神奇地合并到主分支中(任何关于这里发生的事情的见解都会受到赞赏!)
一切似乎都像预期的那样工作,除了当变更集同时影响apps/AAA和libs/XXX时,如果我查看newRepo提交历史记录,会发现有重复项。如果有一种方法可以删除重复项,那么它将是完美的。
发布于 2013-07-26 04:15:32
不需要处理子subshell和使用ext glob (作为kynan suggested),可以尝试这种简单得多的方法:
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- apps/AAA libs/XXX' --prune-empty -- --all正如void.pointer's comment提到的,这将从当前存储库中删除除apps/AAA和libs/XXX之外的所有内容。
修剪空的合并提交
这会留下许多空洞的合并。正如raphinesse在他的answer中所描述的那样,这些可以通过另一个过程来删除
git filter-branch --prune-empty --parent-filter \
'sed "s/-p //g" | xargs -r git show-branch --independent | sed "s/\</-p /g"'提交警告:以上必须使用sed和xargs的GNU版本,否则会因为xargs⚠️失败而删除所有提交。brew install gnu-sed findutils,然后使用gsed和gxargs
git filter-branch --prune-empty --parent-filter \
'gsed "s/-p //g" | gxargs git show-branch --independent | gsed "s/\</-p /g"' 发布于 2017-02-17 21:06:14
使用简单的git命令手动执行步骤
该计划是将单独的目录拆分成自己的repos,然后将它们合并在一起。以下手动步骤没有使用极客使用的脚本,而是易于理解的命令,并且可以帮助将额外的N个子文件夹合并到另一个单一存储库中。
Divide
假设您的原始存储库是:original_repo
1-拆分应用程序:
git clone original_repo apps-repo
cd apps-repo
git filter-branch --prune-empty --subdirectory-filter apps master2-拆分库
git clone original_repo libs-repo
cd libs-repo
git filter-branch --prune-empty --subdirectory-filter libs master如果您有两个以上的文件夹,请继续。现在你应该有两个新的临时git库了。
通过合并应用和库来征服
3-准备全新的repo:
mkdir my-desired-repo
cd my-desired-repo
git init而且你至少需要提交一次。如果应该跳过以下三行,您的第一个存储库将立即出现在您的存储库的根目录下:
touch a_file_and_make_a_commit # see user's feedback
git add a_file_and_make_a_commit
git commit -am "at least one commit is needed for it to work"提交临时文件后,后面部分中的merge命令将按预期停止。
根据用户的反馈,您可以选择添加一个.gitignore或README.md等,而不是添加一个像a_file_and_make_a_commit这样的随机文件。
4-首先合并应用程序存储库:
git remote add apps-repo ../apps-repo
git fetch apps-repo
git merge -s ours --no-commit apps-repo/master # see below note.
git read-tree --prefix=apps -u apps-repo/master
git commit -m "import apps"现在,您应该会在新存储库中看到apps目录。git log应该显示所有相关的历史提交消息。
注意:正如Chris在下面的评论中指出的,对于更新版本(>=2.9)的git,您需要在git merge中指定--allow-unrelated-histories
5-接下来以同样的方式合并libs repo:
git remote add libs-repo ../libs-repo
git fetch libs-repo
git merge -s ours --no-commit libs-repo/master # see above note.
git read-tree --prefix=libs -u libs-repo/master
git commit -m "import libs"如果要合并2个以上的存储库,请继续。
https://stackoverflow.com/questions/2982055
复制相似问题