我有遥控器Foo和Bar。 Foo是一个包含大量目录的Web应用程序,其中相关的是/public
,其中包含各种文件和其他目录。
Bar是一组库,在前端使用了什么,因此,它应该在Foo中的/public/bar
中。 Foo没有文件。
无论子模块还是子树合并,这都是小菜一碟。然而...
Bar的树很乱,它有各种各样的预生产文件,比如PSD和FLA,唯一真正有用的部分就是/www/tools
里面的内容。
所以,我想要做的是将Bar的/www/tools
合并到Foo的/public/bar
中,并假装Bar的其余部分甚至不存在。
可以吗?
(我认为这与你最初将你的项目合并为子树的项目非常类似。我不知道该怎么做。)
答案 0 :(得分:11)
我已成功使用以下命令(为您的方案重写)。
$ git remote add Bar /path/to/bar
$ git merge -s ours --no-commit Bar/master
$ git read-tree --prefix=public/bar -u Bar/master:www/tools/
巨大的警告!我仍然在弄清楚如何从Bar获取/合并。这只会带来一次。
我目前合并更改的方式是这样的:
$ get fetch Bar
$ git pull -X subtree=public/bar Bar master
这会让您发现已删除大量文件的冲突,您只需git rm
个,然后git commit
。
我当然愿意接受更好的改变方式的建议。
由于这是一个旧线程,我应该补充说我正在运行Git 1.7.9。
答案 1 :(得分:4)
尝试使用git subtree。它允许您将项目的子树提取到另一个项目中,然后可以将其合并到您的项目中。
答案 2 :(得分:2)
编辑:我发现你只能使用git merge --no-commit
执行此操作。这将尝试合并,即使它没有冲突,它将在提交之前停止。此时,您可以删除所有不需要的垃圾(包括必要时还原冲突的文件),并创建仅包含所需子树的合并提交。
原始答案:
您确实可以使用filter-branch。大纲:
克隆您的源代码:
git clone --bare /path/to/bar /path/to/bar_clone
使用裸克隆将为您节省创建工作目录的时间和空间。
接下来,在克隆上使用filter-branch:
git filter-branch --index-filter 'git rm -rf <unwanted files/directories>' -- --all
--all
让它知道您想要使用所有引用,而不仅仅是当前的HEAD。您现在将拥有一个仅包含所需子目录的存储库,以及与之关联的所有历史记录。
注意:抱歉,我不知道一种非常简单的方法可以删除除了你想要的所有东西。你必须小心使用通配符,因为你不想破坏任何git目录。这里的东西会起作用,虽然速度较慢,特别是如果你有很多文件:
git filter-branch --index-filter 'git rm -f `git ls-files | grep -v ^www/tools`' -- --all
无论如何,无论您管理要删除的文件列表,都可以继续进行子树合并,从bar_clone
拉入foo
。
答案 3 :(得分:0)
我不认为这可以使用合并本身来完成,但这些步骤可能会起作用,至少就最终产品而言。第一:
% git fetch Bar
这将从Bar存储库中获取最新的提交,但不会尝试合并它们。它在.git / FETCH_HEAD
中记录提交的SHA% cat .git/FETCH_HEAD
b91040363160aab4b5dd46e61e42092db74b65b7 branch 'Bar' of ssh://blah...
这显示了远程分支的最新提交的SHA标识符是什么。
% git checkout b91040363160aab4b5dd46e61e42092db74b65b7 www/tools
这将获取www / tools中用于获取提交的文件的副本,并覆盖工作树中的内容。然后,您可以像平常一样将这些更改提交到本地存储库。生成的提交将不会引用它的来源,但至少应该使用所需文件的版本获取存储库。
答案 4 :(得分:0)
我建议使用子树两次 - 一次提取所有的/ www /工具,一次提取/公开 - 听起来像/ public应该在自己的repo中所以,我建议你推送/公开一个新的repo - 包含所有子树的历史记录,然后将/ www / tools的子树历史合并到新的/公共repo中,并将其作为Foo的子树添加回来。
cd foo
git subtree split --prefix=public --branch=new-shared-public --annotate='(split) '
cd../bar
git subtree split --prefix=www/tools --rejoin --branch=new-shared-www-tools --annotate='(split) '
您的回购现在有两个新的分支机构。一个是公共的提交历史,另一个是www / tools。我将从此处省略cd
。
创建你的新公共仓库(我在这里假设github,但听起来你可能想在本地做)并在那里推送你的子树: git checkout new-shared-public git push git@github.com:my_id/new-shared-repo.git HEAD:master
然后将您的其他分支合并到:
git checkout new-shared-www-tools
git remote add Foo git@github.com:my_id/new-shared-repo.git
git merge -s ours --no-commit Bar/master
虽然我已将ours
指定为提交策略,但它可能(可能)并不重要。
最后,在您完成合并并将其推送到新的仓库之后,请返回Foo仓库。从那里获取公共历史并添加新的公共回购作为子树:
git subtree add --squash --prefix shared git@github.com:my_id/new-shared-repo.git master
git subtree pull --squash --prefix shared git@github.com:my_id/new-shared-repo.git master
git push