如何在git-subtree添加后重新定义?

Epe*_*eli 58 git git-rebase git-subtree

我正在尝试学习在Git 1.7.11中添加的新git-subtree命令.添加子树后,我似乎失去了变基的能力.我有一个带有README文件的主存储库和一个库存储库,它也有一个README文件.我将它添加到lib目录subtree add:

$ git subtree add -P lib/mylib myliborigin master
Run Code Online (Sandbox Code Playgroud)

这很好,但现在历史看起来像这样:

*   22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - 
|\                                                                                                                
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
* b99d55b Add readme
* 020e372 Initial
Run Code Online (Sandbox Code Playgroud)

现在当我想要反对我的repo origin/master并且它失败时因为squash commit直接应用于它不适用的父提交,因为它被应用于repo的根而不是我添加的时候给它的前缀子树.

如果我看一下壁球提交,原因很清楚.没有关于前缀的信息.这只是原始的mylib提交压扁在一起.只有下一个合并提交知道它的任何内容,但rebase不会在此处考虑它.

是否有任何变通方法(除了永远不会对子树提交进行重新定位)?

eri*_*ers 9

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

使用您的初始示例:

*   22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - 
|\                                                                                                                
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
* b99d55b Add readme
* 020e372 Initial
Run Code Online (Sandbox Code Playgroud)

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

$ git rebase -i 020e372
Run Code Online (Sandbox Code Playgroud)

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

e b99d55b Add readme
Run Code Online (Sandbox Code Playgroud)

保存文件/关闭,然后当它进入"添加自述文件"提交时,运行修改命令:

$ git commit --amend
Run Code Online (Sandbox Code Playgroud)

然后重新添加新的子树:

$ git subtree add -P lib/mylib myliborigin master
Run Code Online (Sandbox Code Playgroud)

继续变革:

$ git rebase --continue
Run Code Online (Sandbox Code Playgroud)

然后你的分支应该从主人那里重新开始,并且子树将是"正常的",并且Squash + Merge完好无损:

*   22c1fe6 (HEAD, master) Merge commit 'b6e698d9f4985825efa06dfdd7bba8d2930cd40e' as 'lib/mylib' - 
|\                                                                                                                
| * b6e698d Squashed 'lib/mylib/' content from commit d7dbd3d
Run Code Online (Sandbox Code Playgroud)


jim*_*qaz 8

Git 2.24.0(2019-11-04 发布)添加了对git rebase --rebase-merges --strategy [strategy]. git rebase --rebase-merges --strategy subtree [branch]因此,现在如果您在当前分支包含子树合并时运行,它现在就可以工作了。

对于我的项目,我决定可能不使用git subtree add,而是使用 丢弃合并提交的第二个父级git replace --edit。我还使用了Git 书籍 v1 过时的“子树”教程,它做了同样的事情,但很乏味。

  • 在我第一次尝试使用它时,它根本不“正常工作”。如果我尝试在最新的主/主分支之上使用子树提交对分支进行变基,Git rebase 会因“致命:拒绝合并不相关的历史记录”而崩溃。 (4认同)

Ski*_*nok 7

这是一个老问题,但我的回购问题与我有同样的问题,我终于找到了一个完整的解决方案,它(希望)保留了所有的子树元数据.

假设我们有这个提交树:

B   (master) Add README.md
|     
A            Initial commit
Run Code Online (Sandbox Code Playgroud)

我们feature用一个子树分叉了一个分支lib/:

git remote add -f githublib https://github.com/lib/lib.git
git subtree add --prefix lib/ githublib master --squash
Run Code Online (Sandbox Code Playgroud)

它创建了一个包含两个父项的合并提交D:我们当前的master(B),以及与F外部仓库的压缩历史无关的提交.此提交还在git subtree其提交消息中包含一些元数据(即git-subtree-dirgit-subtree-split).

   D     (feature) Merged commit 'F' as 'lib/'
  / \    
 /   F             Squashed 'lib/' content from GGGGGG
B        (master)  Add README.md
|     
A                  Initial commit
Run Code Online (Sandbox Code Playgroud)

稍后,我们会独立地向两个分支添加一些提交.

   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
Run Code Online (Sandbox Code Playgroud)

现在我们要重新feature加入master.这是如何做:

1.樱桃 - 从feature一个接一个地提交提交,以创建一个新的feature分支副本master.

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
Run Code Online (Sandbox Code Playgroud)

现在我们有相当于一个rebase,但我们已经丢失了所有关于外部回购的信息git subtree.要恢复它:

2. 将缺少的父链接添加为移植,并重写历史记录feature以使其永久化.

git checkout feature
git replace --graft D' C F
git filter-branch --tag-name-filter cat -- master..
Run Code Online (Sandbox Code Playgroud)

现在我们得到的图片与开头的图片完全相同.旧的提交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
Run Code Online (Sandbox Code Playgroud)

警告:这会重写历史记录feature,因此如果有人在此分支上与您合作,请小心发布.但是,既然你想首先做一个变基,你可能会意识到这一点:-)


Kev*_*per 5

这在简单的情况下有效:

git rebase --preserve-merges master
Run Code Online (Sandbox Code Playgroud)

感谢@Techlive Zheng的评论。


你可能会看到

fatal: refusing to merge unrelated histories
Error redoing merge a95986e...
Run Code Online (Sandbox Code Playgroud)

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

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

git subtree add -P lib lib-origin master
Run Code Online (Sandbox Code Playgroud)

继续变基:

git rebase --continue
Run Code Online (Sandbox Code Playgroud)

一切准备就绪!


如果您想知道它是否成功运行,可以在重新定基后与原始版本进行比较,以确保您没有进行任何更改:

git diff <ref-before-rebase> <ref-after-rebase> -- .
Run Code Online (Sandbox Code Playgroud)

-- .最后指示git仅diff显示当前目录中的文件)。


如果所有其他方法都失败了,并且您不关心自己保存提交,则可以简单地git cherry-pick进行原始的子树提交。

提交消息看起来像Add 'lib/' from commit '9767e6...'-这就是您想要的。


Ada*_*ruk 0

你需要使用

git rebase --preserve-merges --preserve-committer --onto new_place start end
Run Code Online (Sandbox Code Playgroud)

  • 这没有帮助。我仍然失去了前缀。 (4认同)

归档时间:

查看次数:

10830 次

最近记录:

5 年,10 月 前