我正在学习新的git-subtree命令,它是在Git1.7.11中添加的。在我添加了一个子树之后,我似乎失去了重设基址的能力。我有一个包含自述文件的主存储库和一个也有一个自述文件的库存储库。我使用subtree add将其添加到lib目录中
$ git subtree add -P lib/mylib myliborigin master这可以很好地工作,但是现在历史看起来是这样的:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' -
|\
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
* b99d55b Add readme
* 020e372 Initial现在,当我想要根据origin/master重新设置我的存储库的基础时,它失败了,因为挤压提交直接应用于它的父提交,这不适用,因为它应用于存储库的根,而不是我在添加子树时给它的前缀。
如果我看一下挤压提交,原因就很清楚了。没有关于前缀的信息。它只是将原始的mylib提交压缩在一起。只有下一次合并提交才知道它,但rebase在这里不会考虑它。
有没有什么变通办法(除了永远不会在子树提交时重新建立基础)?
发布于 2018-01-17 11:52:48
这在简单的情况下有效:
git rebase --preserve-merges master感谢@Techlive Zheng在评论中。
你可能会看到
fatal: refusing to merge unrelated histories
Error redoing merge a95986e...这意味着git无法自动应用您的子树。这将使您处于他的答案中所描述的情况@ericpeters。解决方案:
重新添加子树(使用最初使用的命令):
git subtree add -P lib lib-origin master继续重设基准:
git rebase --continue一切都准备好了!
如果你想知道它是否成功工作,你可以在rebasing之后与你的原始版本进行比较,以确保你没有改变任何东西:
git diff <ref-before-rebase> <ref-after-rebase> -- .(末尾的-- .指示git只对当前目录中的文件执行diff操作)。
如果所有其他方法都失败了,并且您不关心保留提交本身,那么您可以简单地git cherry-pick原始子树提交。
提交消息将类似于Add 'lib/' from commit '9767e6...' --这就是您想要的消息。
发布于 2017-02-09 09:37:29
这是一个老问题,但我的repo也遇到了同样的问题,我最终找到了一个完整的解决方案,它(希望)保留了所有的子树元数据。
假设我们有这样的提交树:
B (master) Add README.md
|
A Initial commit我们使用驻留在lib/中的子树派生了一个feature分支
git remote add -f githublib https://github.com/lib/lib.git
git subtree add --prefix lib/ githublib master --squash它创建一个具有两个父对象的合并提交D:我们当前的master (B),以及一个不相关的提交F,其中包含外部存储库的压缩历史记录。此提交还在其提交消息中包含一些git subtree元数据(即git-subtree-dir和git-subtree-split)。
D (feature) Merged commit 'F' as 'lib/'
/ \
/ F Squashed 'lib/' content from GGGGGG
B (master) Add README.md
|
A Initial commit稍后,我们将一些提交独立地添加到两个分支。
E (feature) Remove .gitignore from lib/
C | (master) Add LICENSE.md
| D Merged commit 'F' as 'lib/'
| / \
|/ F Squashed 'lib/' content from GGGGGG
B Add README.md
|
A Initial commit现在我们想在master上重新建立feature的基础。下面是操作步骤:
1.逐个从feature中挑选提交,在master之上创建feature分支的新副本。
git branch -f feature C
git checkout feature
git cherry-pick D E
E' (feature) Remove .gitignore from lib/
|
D' Merged commit 'F' as 'lib/'
|
| E Remove .gitignore from lib/
C | (master) Add LICENSE.md
| D Merged commit 'F' as 'lib/'
| / \
|/ F Squashed 'lib/' content from GGGGGG
B Add README.md
|
A Initial commit现在我们有了相当于rebase的东西,但是我们已经丢失了git subtree所需的关于外部repo的所有信息。要恢复它,请执行以下操作:
2. Add the missing parent link as a graft,重写feature的历史,使其永久化。
git checkout feature
git replace --graft D' C F
git filter-branch --tag-name-filter cat -- master..现在我们得到一张与开头的图片完全相同的图片。旧的提交D和E仍然存在,但它们可以稍后被垃圾回收。
E' (feature) Remove .gitignore from lib/
|
D' Merged commit 'F' as 'lib/'
|\
| \
C \ (master) Add LICENSE.md
| \
| \
| F Squashed 'lib/' content from GGGGGG
B Add README.md
|
A Initial commit警告:这将重写feature的历史,因此如果其他人在此分支上与您合作,请谨慎发布它。但是,由于您希望首先进行rebase,因此您可能已经意识到这一点:-)
发布于 2014-04-16 05:19:39
这不是一个解决方案,但它目前的工作,我使用…
使用您的初始示例:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' -
|\
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
* b99d55b Add readme
* 020e372 Initial在子树添加之前,以交互方式重新建立到第二次提交:
$ git rebase -i 020e372删除两个子树条目并标记为先前提交的编辑:
e b99d55b Add readme保存文件/关闭,然后当它到达"Add readme“提交时,运行修订命令:
$ git commit --amend然后重新添加新的子树:
$ git subtree add -P lib/mylib myliborigin master继续重设基准:
$ git rebase --continue然后你的分支应该在master的基础上重新建立,子树将是“正常的”,Squash +合并原封不动:
* 22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' -
|\
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3dhttps://stackoverflow.com/questions/12858199
复制相似问题