git 将两个仓库合并成一个,一个应该是一个分支
git merge two repositories into a new one, one should be a branch
我想把两个版本库放在一起,但是第二个版本库应该放到一个分支中
A - B - C - D - E - F - G - H Repo1
A1 - B1 - C1 Repo2
Crete new repo reponew
git init reponew
为旧的 repo Repo1 添加远程并获取旧的 repo Repo1
git remote add -f Repo1 ..\..\output\Repo1
将 Repo1/master 中的文件合并到 new/master
git merge Repo1/master --allow-unrelated-histories
新的存储库 reponew 看起来像:
A - B - C - D - E - F - G - H master
现在我在特定的提交和检出上创建了一个新分支
git branch branchX 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74
git checkout branchX
为旧的 repo Repo1 添加远程并获取旧的 repo Repo1
git remote add -f Repo2 ..\..\output\Repo2
将 Repo1/master 中的文件合并到 new/master
git merge -Xtheirs Repo2/master --allow-unrelated-histories
现在新的存储库 repnew 如下所示:
A1 - B1 - C1 branchX
\
A - B - C - - - - - - - - - - - - - -
\
D - E - - - - - F - G - H master
看起来这是由合并日期为现在的合并请求引起的
但我希望它看起来像这样:
A - B - C - D - E - - - - - F - G - H master
\
- - - A1 - B1 - C1 branchX
"move" 提交 AFTER 现有历史记录的主要方式是使用 rebase
。合并只能添加一个新的提交,将两个历史记录作为父项。
但是 rebase
不会真正移动 commist 而是在指定的 onto
之后重播它们。因此,如果旧提交上仍有引用(分支或标记),它们将在整个提交历史中保持可用。
在您的情况下,您希望将 Repo2/master
的历史重新设置为提交 C
.
所以解决方案是:
git branch branchX --no-track Repo2/master
git rebase -Xtheirs 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74 branchX
你应该得到你想要的结果。
@torek 建议,还有 filter-branch
。
filter-branch
允许您通过对每个重写的提交应用过滤器来重写提交历史。它主要用于删除错误提交的敏感数据(例如密码),从历史记录中删除大文件,或更改存储库的根文件夹。
filter-branch
的优点是它也会移动标签。
它还会过滤带有空消息的提交。
使用 filter-branch
,有一个 --parent-filter
允许您在过滤时更改提交的父项。
它将过滤列出的所有引用,因此要移动标签,我们必须列出当前 branchX
: git tag --merged branchX
中的所有标签,然后使用 --tag-name-filter cat
.[=30= 按原样过滤它们]
所以命令将是:
git branch branchX --no-track Repo2/master
git filter-branch \
--parent-filter 'test $GIT_COMMIT = <FULL-commit-id-of-A1> && echo "-p 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74" || cat' \
--tag-name-filter cat \
-- branchX $(git tag --merged branchX)
然后您将拥有重写的历史,但仍然可以使用以 refs/original/
为前缀的旧历史。
如果没问题,您可以删除原始引用(rm -rf .git/refs/original/
),否则您可以恢复它们(cp -r .git/refs/original/refs .git && rm -rf .git/refs/original/
)。
我想把两个版本库放在一起,但是第二个版本库应该放到一个分支中
A - B - C - D - E - F - G - H Repo1
A1 - B1 - C1 Repo2
Crete new repo reponew
git init reponew
为旧的 repo Repo1 添加远程并获取旧的 repo Repo1
git remote add -f Repo1 ..\..\output\Repo1
将 Repo1/master 中的文件合并到 new/master
git merge Repo1/master --allow-unrelated-histories
新的存储库 reponew 看起来像:
A - B - C - D - E - F - G - H master
现在我在特定的提交和检出上创建了一个新分支
git branch branchX 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74
git checkout branchX
为旧的 repo Repo1 添加远程并获取旧的 repo Repo1
git remote add -f Repo2 ..\..\output\Repo2
将 Repo1/master 中的文件合并到 new/master
git merge -Xtheirs Repo2/master --allow-unrelated-histories
现在新的存储库 repnew 如下所示:
A1 - B1 - C1 branchX
\
A - B - C - - - - - - - - - - - - - -
\
D - E - - - - - F - G - H master
看起来这是由合并日期为现在的合并请求引起的
但我希望它看起来像这样:
A - B - C - D - E - - - - - F - G - H master
\
- - - A1 - B1 - C1 branchX
"move" 提交 AFTER 现有历史记录的主要方式是使用 rebase
。合并只能添加一个新的提交,将两个历史记录作为父项。
但是 rebase
不会真正移动 commist 而是在指定的 onto
之后重播它们。因此,如果旧提交上仍有引用(分支或标记),它们将在整个提交历史中保持可用。
在您的情况下,您希望将 Repo2/master
的历史重新设置为提交 C
.
所以解决方案是:
git branch branchX --no-track Repo2/master
git rebase -Xtheirs 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74 branchX
你应该得到你想要的结果。
@torek 建议,还有 filter-branch
。
filter-branch
允许您通过对每个重写的提交应用过滤器来重写提交历史。它主要用于删除错误提交的敏感数据(例如密码),从历史记录中删除大文件,或更改存储库的根文件夹。
filter-branch
的优点是它也会移动标签。
它还会过滤带有空消息的提交。
使用 filter-branch
,有一个 --parent-filter
允许您在过滤时更改提交的父项。
它将过滤列出的所有引用,因此要移动标签,我们必须列出当前 branchX
: git tag --merged branchX
中的所有标签,然后使用 --tag-name-filter cat
.[=30= 按原样过滤它们]
所以命令将是:
git branch branchX --no-track Repo2/master
git filter-branch \
--parent-filter 'test $GIT_COMMIT = <FULL-commit-id-of-A1> && echo "-p 200303b0b215cc0fb2d92f50ffc9d7df8bbaab74" || cat' \
--tag-name-filter cat \
-- branchX $(git tag --merged branchX)
然后您将拥有重写的历史,但仍然可以使用以 refs/original/
为前缀的旧历史。
如果没问题,您可以删除原始引用(rm -rf .git/refs/original/
),否则您可以恢复它们(cp -r .git/refs/original/refs .git && rm -rf .git/refs/original/
)。