猿问
下载APP

将git父指针设置为其他父级

如果我在过去提交指向一个父级的提交,但我想更改它指向的父级,我将如何进行此操作?


拉莫斯之舞
浏览 45回答 3
3回答

慕沐林林

用git rebase。它是Git中的通用“take commit(s)and plop it / them on a different parent(base)”命令。但是要注意一些事情:由于提交SHA涉及其父项,因此当您更改给定提交的父项时,其SHA将更改 - 在开发行中将更改其后的所有提交(比它更新)的SHA也将更改。如果您正在与其他人合作,并且您已经将提交的问题公开推送到他们撤回的地方,那么修改提交可能是一个坏主意™。这是由于#1,因此在尝试弄清楚由于您的SHA不再与“相同”提交相匹配时发生的事情时,其他用户的存储库将会遇到混淆。(有关详细信息,请参阅链接手册页中的“从上游重新恢复”部分。)也就是说,如果你目前在一个分支上有一些你希望转移到新父级的提交,它看起来像这样:git rebase --onto <new-parent> <old-parent>这会将当前分支之后 <old-parent>的所有内容移动到顶部<new-parent>。

慕田峪9158850

如果事实证明你需要避免重新定义后续提交(例如,因为历史重写是站不住脚的),那么你可以使用git替换(在Git 1.6.5及更高版本中可用)。# …---o---A---o---o---…## …---o---B---b---b---…## We want to transplant B to be "on top of" A.# The tree of descendants from B (and A) can be arbitrarily complex.replace_first_parent() {&nbsp; &nbsp; old_parent=$(git rev-parse --verify "${1}^1") || return 1&nbsp; &nbsp; new_parent=$(git rev-parse --verify "${2}^0") || return 2&nbsp; &nbsp; new_commit=$(&nbsp; &nbsp; &nbsp; git cat-file commit "$1" |&nbsp; &nbsp; &nbsp; sed -e '1,/^$/s/^parent '"$old_parent"'$/parent '"$new_parent"'/' |&nbsp; &nbsp; &nbsp; git hash-object -t commit -w --stdin&nbsp; &nbsp; ) || return 3&nbsp; &nbsp; git replace "$1" "$new_commit"}replace_first_parent B A# …---o---A---o---o---…#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C---b---b---…## C is the replacement for B.在建立了上述替换后,对对象B的任何请求都将实际返回对象C.除了第一个父项(相同的父项(第一个除外),同一个树之外,C的内容与B的内容完全相同)相同的提交消息)。默认情况下,替换处于活动状态,但可以通过使用git--no-replace-objects选项(在命令名之前)或通过设置环境变量来启用替换。可以通过推送(除正常之外)共享替换。GIT_NO_REPLACE_OBJECTSrefs/replace/*refs/heads/*如果您不喜欢commit-munging(使用上面的sed完成),那么您可以使用更高级别的命令创建替换提交:git checkout B~0git reset --soft Agit commit -C Bgit replace B HEADgit checkout -最大的区别在于,如果B是合并提交,则此序列不会传播其他父项。

HUWWW

请注意,更改Git中的提交要求必须更改其后的所有提交。如果您已经发布了这部分历史记录,那么就不鼓励这样做了,有人可能会在变更前的历史上建立自己的工作。替代解决方案git rebase中提到琥珀的反应是使用移植机制(见Git中移植的定义Git的词汇和文档.git/info/grafts文件在Git仓库布局文档)改变提交父,检查它做正确的事情与一些浏览器的历史(gitk,git log --graph等等,然后使用git filter-branch(如其联机帮助页的“示例”部分所述)使其永久化(然后删除移植物,并选择删除备份git filter-branch或重新定义存储库的原始引用):echo“$ commit-id $ graft-id”>> .git / info / graftsgit filter-branch $ graft-id..HEAD注意 !!!该解决方案是从底垫的解决方案不同的是git rebase将重订/移植的变化,而移植物为基础的解决方案只会重新设置父级提交原样,完全没有考虑到老上级和新的父之间的差异!
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答