在某些情况下,为了代码检查或更清晰的版本历史记录,我想将现有提交分成两部分。但是,在拆分提交时,您会发现某些不一致之处出现,或者您必须修改新的父提交来维护构建。但是,我往往不得不做很多手工工作来跟踪/维护我编写的最终代码。
是否可以在不修改最终提交的树形哈希的情况下运行变基。
示例我们有3个提交,分别为A
,B
和C
:
这是提交A
# test_file.py
# this is commit A
does_stuff()
这是一个新的提交B
# test_file.py
# this is commit B
does_stuff()
这是一个新的提交C
# test_file.py
# this is commit C
does_stuff()
原始树的样子
... -- C -- A
但是我们想将A
“拆分”为两个提交
... -- C -- B -- A
当我们使用交互式资源库创建B
时,A
的注释也将被更新以显示# this is commit B
(假设除了该文件以外,还有其他一些更改)。但是,我们希望保持原样。注意:A
由于具有不同的父对象而具有不同的整体哈希值,但是其树哈希值应与以前相同。
答案 0 :(得分:3)
不可能修改任何提交。相反,您将一些现有的提交集复制到新的提交集。这实际上是个好消息,因为这意味着原始提交仍然可用。
当我们使用交互式资源库创建
B
时,A
的注释也将被更新以显示# this is commit B
(假设除了该文件以外,还有其他一些更改)。
在您显示的特定示例中,它不应:您应该遇到合并冲突。
对于其他案例,您当然是正确的。
但是,我们希望保持注释不变。注意:
A
由于具有不同的父对象而具有不同的整体哈希值,但是其树哈希值应与以前相同。
请记住,您从开始:
... -- C -- A
我将其绘制为:
...--C--A <-- branchname (HEAD)
表示某些名为branchname
的现有分支指向提交C
,并且HEAD
附加到A
。
然后您运行了git rebase -i <hash-of-C>
或类似名称。这为您提供了要做的事情的清单,您可以选择“编辑” A
。现在Git:
将HEAD分离到变基目标:
A <-- branchname
/
...--C <-- HEAD
复制提交A
(在这种情况下,使用完全相同的副本/快进,以便它重新使用A
本身;如果您喜欢{{ 1}},尽管最终没有什么区别:
--no-ff
或:
A <-- HEAD, branchname
/
...--C
(使用 A <-- branchname
/
...--C--A' <-- HEAD
强制复制)。
这时,您将进行一些更改并运行--no-ff
和git add
以将当前的提交移开,并使git commit --amend
指向新的提交HEAD
,其父为B
。假设您没有使用C
;结果是:
--no-ff
((如果您确实使用过 A <-- branchname
/
...--C--B <-- HEAD
,还会有另外--no-ff
个没有名字的视频群聊;它将在大约一个月内被垃圾回收。然后,我们必须调用下一个副本{ {1}}来区分它们,所以假设您没有使用A'
。)
现在,您要从提交A"
获取文件,并从提交--no-ff
获取提交消息,然后进行新的提交。由于A
仍指向原始提交A
,因此只需执行以下操作:
branchname
现在您拥有:
A
此时,您使用$ git checkout branchname -- . # assumes you're at the top level of your repo
$ git commit -C branchname # or -c if you want to edit it again
完成了重新配置。由于没有要复制的提交,就涉及rebase而言,您已经完成了对最后一个提交 A <-- branchname
/
...--C--B--A' <-- HEAD
的复制,因此,完成了rebase的最后一步,即从原始提交中删除分支名称。链并移动它以指向与git rebase --continue
相同的提交,同时重新附加A
:
HEAD
作为副作用,rebase会将HEAD
设置为记住 A <-- ORIG_HEAD
/
...--C--B--A' <-- branchname (HEAD)
所指向的位置,因此很容易确保一切正常工作,并且最终处于所需的状态:
ORIG_HEAD
,如果错了,您可以branchname
,结果是:
git diff ORIG_HEAD HEAD
请注意,其他命令(包括git reset --hard ORIG_HEAD
)设置了 A <-- branchname (HEAD)
/
...--C--B--A' <-- ORIG_HEAD
(这就是它们在此处交换的原因)。最终,除了reflog条目外,这两个提交之一将被完全放弃,并且当这些到期时,无法访问的提交将真正消失。这种提交的默认到期时间是30天。