将git子树移动到其他存储库中 [英] Moving a git subtree into different repository

查看:61
本文介绍了将git子树移动到其他存储库中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将目录及其所有历史记录从存储库移动到另一个存储库.

I try to move a directory and all its history from repository to another repository.

使用git subtree split可以轻松提取目录的完整历史记录.

Extracting the complete history of the directory is easy with git subtree split.

这将创建一个新分支,可以轻松将其提取到另一个存储库中.

This creates a new branch, which can easily be fetched to the other repository.

现在,我使用git subtree add将该目录粘贴回第二个存储库中.

Now I used git subtree add to paste the directory back into the second repository.

如果我查看gitkgit log --decorate --graph,一切看起来都很好.所有提交均按预期方式存在.此外,所有文件都按预期方式显示.

If I look at gitk or git log --decorate --graph everything looks fine. All commits are present as expected. Also all the files are present as expected.

但是,当我尝试使用git log -- transplanted_dir/somefile查看已移植文件的历史记录时,我只能看到由git subtree add引起的一次合并"提交.

But when I try to see the history of a transplanted file using git log -- transplanted_dir/somefile, I only see the one "merge" commit, resulting from the git subtree add.

为什么我在上面的gitk中看到提交,但在单个文件的日志中却看不到?

Why do I see the commits in gitk above, but not in the log of a single file?

如果我做一个简单的git merge,我可以看到每个文件的历史记录,但是这些文件当然不会存在于子文件夹中.

If I do a simple git merge, I can see the history of each file, but the files will, of course not live in a subfolder.

将移动的提交整合到其他存储库中的正确方法是什么?

What is the right way to integrate the moved commits into the other repository?

重现情况的详细示例命令:

Detailed example commands to reproduce situation:

#create two repositories:
git init a
git init b

# create directory dir with some history
cd a
mkdir dir
echo 1 > dir/file
git add .
git commit -am 1
echo 2 > dir/file
git commit -am 2
echo 3 > dir/file
echo 3 > otherfile
git add .
git commit -am 3

#split subtree
git subtree split --prefix dir -b split

#create a commit on repo b
cd ../b
mkdir otherdir
touch otherdir/file
git add .
git commit -am init

#fetch split branch of repo a
git fetch ../a split
git co -b split FETCH_HEAD
git log --decorate --graph --name-status 
git co master

# add commits to repo b
git subtree add --prefix somedir split

# this looks fine:
git log --decorate --graph --name-status

# no history here - Why?
git log --decorate --graph --name-status somedir/file
git log --decorate --graph --name-status --follow somedir/file

推荐答案

好的,阅读源代码可以清除一切.

Alright, reading the source cleared things up.

git subtree add非常难看:它首先使用git read-tree最新版本添加到给定目录中,而没有任何历史记录.之后,它使用git commit-tree创建一个伪合并提交,以附加包含未添加前缀文件的旧历史记录.

git subtree add is pretty ugly: It first uses git read-tree to add the current version without any history into the given directory. Afterwards it uses git commit-tree to create a fake merge commit to attach the old history containing the unprefixed files.

另一方面,现在HEAD的前缀文件和HEAD ^ 2的未前缀文件应该完全相同,并且应该被--follow识别为移动.

On the other hand, now the prefixed file at HEAD and the unprefixed one in HEAD^2 should be exactly the same and should be recognized as a move by --follow.

不幸的是,它不是这样识别的.不知道为什么.

Unfortuately it is not recognized as such. No idea why.

最好的解决方案可能是添加显式提交,将文件移动到新目录并进行常规合并. -一种替代方法是按照

The best solution is probably to add an explicit commit moving the files to the new directory and do a normal merge. - An alternative is to rewrite the history of the transplanted directory as described in How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?.

对于我的情况git subtree add不好,正常的git merge带有正确准备的子树似乎完全正确.

For my situation git subtree add is bad, a normal git merge with a correctly prepared subtree seems to be exactly the right thing.

这篇关于将git子树移动到其他存储库中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆