我尝试在另一个分支的顶部移动一个提交,忽略了目标分支中所做的所有更改。
当前情况是:
master
↓
--A--B--C
D--E
我想在C
面前移动提交E master
↓
--A--B--C--E'
D--E
e'与e相同,除了parrent现在是c而不是d(这意味着e和e'的树应该是相同的)。
是更多的先例:
"git cat-file -p E" shows e.g.
tree b98c9a9f9501ddcfcbe02a9de52964ed7dd76d5a
parent D
"git cat-file -p E'" should show
tree b98c9a9f9501ddcfcbe02a9de52964ed7dd76d5a
parent C
我尝试使用不同的参数以及樱桃挑选的重新构想,但最终都试图将C中的任何更改合并到新的E'commit中:(
唯一防止我发现的大规模合并的解决方案是
check out C
copy over all stuff from E to C
commit and get E'
现在,树是相同的,父母是不同的,但是必须有一种更简单,更快的方法,因为必须完成的所有操作是用现有的树木对象创建一个简单的提交对象。
是的,您的图是准确的!😀
a,git中没有明显的工具来实现您想要的结果。这里的问题在于,rebase只是自动选择樱桃,挑选樱桃是关于转换提交以及它们的快照 - 更改和将这些更改与其他一些提交的变更合并,以做出新的提交,这不想要您想要:您想保留原始快照。
幸运的是,有几种非常容易的方法可以做到这一点。不幸的是,其中一些使用至少一个 plumbing Command ,即,不符合用户,不是闪亮的瓷器,内部git命令。
首先,让我们注意您自己的解决方案是正确的:
唯一防止我发现的大规模合并的解决方案是
check out C copy over all stuff from E to C commit and get E'
在实际的git命令中,例如:
$ git checkout -b new-branch master
$ git rm -r . # in case there are files in C that aren't in E at all
$ git checkout <hash-of-E> -- . # overwrite using E
$ git commit
这实际上还不错,但会导致工作树的大量更新,如果您的下一个make
花费一个小时或任何内容,这可能会很烦人。
更轻松的方法#1
第一个更轻松的方法是:
$ git checkout -b new-branch master
$ git read-tree -u <hash-of-E>
$ git commit
read-tree
操作用commit E替换 index 内容。-u
标志告诉GIT:您进行此索引更新,也更新工作环:如果文件:如果文件完全从索引中删除,也将其从工作树中删除,或者如果在索引中替换文件,则也将其替换在工作树中。实际上不需要此标志,因为git commit
正在进行使用索引中的内容,但这对于理智是个好主意。
更轻松的方式#2
第二个更轻松的方法是:
$ git commit-tree -p master -m "<message>" <hash-of-E>^{tree}
此打印出新提交的哈希ID;然后,我们需要将某些内容设置为这个新的哈希ID:
$ git update-ref refs/heads/new-branch <hash-ID>
或一行:
$ git update-ref refs/heads/new-branch $(git commit-tree -p master -m "<message>" <hash-of-E>^{tree})
请注意,-m "<message>"
可以用-F <file>
替换,以读取文件,甚至可以读取-F -
的消息,以阅读STDIN的消息。然后,您可以使用git log --no-walk --format=%B <hash-of-E>
复制E
的提交消息,然后将其管道输送到单行命令的其余部分。
确保new-branch
确实是一个新的分支名称,或者如果不是,则是您要重新设置的分支,而不是当前分支,因为git update-ref
默认没有错误检查。
更轻松的方法#3
您也可以这样做:
$ git checkout -b new-branch <hash-of-E> # now at E, with E in index and work-tree
$ git reset --soft master # make new-branch identify C, without
# touching index or work-tree
$ git commit -c <hash-of-E> # make new commit using E's message
这种最后的方法的工作树木搅动最少,这也许是三种中最好的。但是,方法#2创建了新的提交而不触摸任何东西,因此,如果您实际上不希望在新分支上,方法#2也许是最好的。