首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在git-subtree添加后重新设置基址?

如何在git-subtree添加后重新设置基址?
EN

Stack Overflow用户
提问于 2012-10-12 19:35:06
回答 8查看 14.7K关注 0票数 75

我正在学习新的git-subtree命令,它是在Git1.7.11中添加的。在我添加了一个子树之后,我似乎失去了重设基址的能力。我有一个包含自述文件的主存储库和一个也有一个自述文件的库存储库。我使用subtree add将其添加到lib目录中

代码语言:javascript
复制
$ git subtree add -P lib/mylib myliborigin master

这可以很好地工作,但是现在历史看起来是这样的:

代码语言:javascript
复制
*   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在这里不会考虑它。

有没有什么变通办法(除了永远不会在子树提交时重新建立基础)?

EN

回答 8

Stack Overflow用户

发布于 2018-01-17 11:52:48

这在简单的情况下有效:

代码语言:javascript
复制
git rebase --preserve-merges master

感谢@Techlive Zheng在评论中。

你可能会看到

代码语言:javascript
复制
fatal: refusing to merge unrelated histories
Error redoing merge a95986e...

这意味着git无法自动应用您的子树。这将使您处于他的答案中所描述的情况@ericpeters。解决方案:

重新添加子树(使用最初使用的命令):

代码语言:javascript
复制
git subtree add -P lib lib-origin master

继续重设基准:

代码语言:javascript
复制
git rebase --continue

一切都准备好了!

如果你想知道它是否成功工作,你可以在rebasing之后与你的原始版本进行比较,以确保你没有改变任何东西:

代码语言:javascript
复制
git diff <ref-before-rebase> <ref-after-rebase> -- .

(末尾的-- .指示git只对当前目录中的文件执行diff操作)。

如果所有其他方法都失败了,并且您不关心保留提交本身,那么您可以简单地git cherry-pick原始子树提交。

提交消息将类似于Add 'lib/' from commit '9767e6...' --这就是您想要的消息。

票数 19
EN

Stack Overflow用户

发布于 2017-02-09 09:37:29

这是一个老问题,但我的repo也遇到了同样的问题,我最终找到了一个完整的解决方案,它(希望)保留了所有的子树元数据。

假设我们有这样的提交树:

代码语言:javascript
复制
B   (master) Add README.md
|     
A            Initial commit

我们使用驻留在lib/中的子树派生了一个feature分支

代码语言:javascript
复制
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-dirgit-subtree-split)。

代码语言:javascript
复制
   D     (feature) Merged commit 'F' as 'lib/'
  / \    
 /   F             Squashed 'lib/' content from GGGGGG
B        (master)  Add README.md
|     
A                  Initial commit

稍后,我们将一些提交独立地添加到两个分支。

代码语言:javascript
复制
   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分支的新副本。

代码语言:javascript
复制
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的历史,使其永久化。

代码语言:javascript
复制
git checkout feature
git replace --graft D' C F
git filter-branch --tag-name-filter cat -- master..

现在我们得到一张与开头的图片完全相同的图片。旧的提交D和E仍然存在,但它们可以稍后被垃圾回收。

代码语言:javascript
复制
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,因此您可能已经意识到这一点:-)

票数 11
EN

Stack Overflow用户

发布于 2014-04-16 05:19:39

这不是一个解决方案,但它目前的工作,我使用…

使用您的初始示例:

代码语言:javascript
复制
*   22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - 
|\                                                                                                                
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
* b99d55b Add readme
* 020e372 Initial

在子树添加之前,以交互方式重新建立到第二次提交:

代码语言:javascript
复制
$ git rebase -i 020e372

删除两个子树条目并标记为先前提交的编辑:

代码语言:javascript
复制
e b99d55b Add readme

保存文件/关闭,然后当它到达"Add readme“提交时,运行修订命令:

代码语言:javascript
复制
$ git commit --amend

然后重新添加新的子树:

代码语言:javascript
复制
$ git subtree add -P lib/mylib myliborigin master

继续重设基准:

代码语言:javascript
复制
$ git rebase --continue

然后你的分支应该在master的基础上重新建立,子树将是“正常的”,Squash +合并原封不动:

代码语言:javascript
复制
*   22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - 
|\                                                                                                                
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12858199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档