假设我有以下历史记录日志:
* hash8 (HEAD -> branch_4, origin/branch_4) Message 8
|
* hash7 Message 7
|
* hash6 (origin/branch_3, branch_3) Message 6
|
* hash5 Message 5
|
* hash4 (origin/branch_2, branch_2) Message 4
|
* hash3 Message 3
|
* hash2 (origin/branch_1, branch_1) Message 2
|
* hash1 Message 1
我想做一些代码更改以提交hash4
和历史记录,使其看起来相同。请注意,我之间也有分支,不仅是提交。你会怎么做?
答案 0 :(得分:0)
您根本无法执行此操作。任何提交的任何部分都不能修改。
您可以做一些不同的事情,这些事情可能(也可能不是)足够好。
给出任何Git提交,您可以:
并完成了 new 的提交,然后可以重复此操作。因此,假设您具有以下一系列提交:
A--B <-- branch_1, origin/branch_1
\
C--D <-- branch_2, origin/branch_2
\
E--F <-- branch_3, origin/branch_3
\
G--H <-- branch_4, origin/branch_4
(这是您绘制的同一张图,不同之处在于,我使用大写字母表示哈希ID,并在右侧而不是顶部放置了较新的提交)。完全不可能更改任何现有的提交,但是我们可以将D
提取到工作区,然后进行更改,然后进行新的改进的D'
:< / p>
A--B <-- branch_1, origin/branch_1
\
C--D <-- branch_2, origin/branch_2
\ \
D' \ <-- [remember this hash]
\
E--F <-- branch_3, origin/branch_3
\
G--H <-- branch_4, origin/branch_4
现在我们有了D'
,我们在其上面复制了E
,改变了它的父项,从而制作了E'
,就像我们复制但改变了{{1} }制作D
:
D'
我们还需要将A--B <-- branch_1, origin/branch_1
\
C--D <-- branch_2, origin/branch_2
\ \
D' \ <-- [remember this hash]
\ \
E' E--F <-- branch_3, origin/branch_3
\
G--H <-- branch_4, origin/branch_4
复制到F
,将F'
复制到G
,将G'
复制到H
,复制到新的和改进的提交中的五个提交:
H'
我们现在有 new 分支,它们与旧分支“一样好”(因为它们的提交与旧分支一样好或更好,但是具有不同的哈希ID)。现在,我们必须丢弃旧的分支名称,取而代之的是新的分支名称,也许是通过将旧的分支重命名为A--B <-- branch_1, origin/branch_1
\
C--D <-- branch_2, origin/branch_2
\ \
\ \ <-- [remember this hash]
\ \
\ E--F <-- branch_3, origin/branch_3
\ \
\ G--H <-- branch_4, origin/branch_4
\
D' <-- new_branch_2
\
E'-F' <-- new_branch_3
\
G'--H' <-- new_branch_4
,而将新的分支重命名为old_*
。
(我们的new_
名称不再非常有用,因此我们迟早可以将其完全删除。)
最后,我们的远程跟踪名称old_*
会记住存储在某些 other Git中的分支名称,因此现在我们必须说服 other Git存储库放弃这些提交的副本 并开始使用我们的新副本。为此,我们将需要使用origin/*
或类似的东西将我们的新提交发送到另一个Git,并告诉它放弃您以前拥有的所有工作,转而使用这些新的和改进的提交< / em>。例如:
git push --force
可以做到这一点(git push --force-with-lease branch_2 branch_3 branch_4
将确保它们在我们--force-with-lease
名称中的哈希ID与我们认为的匹配)。
origin/*
或git rebase
或类似的当像这样“改进”的提交次数很少时,您可以一次使用git filter-branch
一次提交,只留下标记:这是new_branch_3的去处例如。当它很大时,这很痛苦。您将希望使该过程自动化。
不幸的是,这很棘手。幸运的是,有几种强大的工具可用于此,包括git cherry-pick
。这样就可以插入 graft 。但是,嫁接不会在克隆上转移:克隆存储库的任何人都会看到原始的未嫁接历史。幸运的是,git replace
或新的git filter-branch
随后可以将嫁接的克隆转换为具有一系列新提交的克隆,从而更新分支名称。有关详细信息,请参见其他StackOverflow答案。