如何在具有后代分支的分支上修改提交?

时间:2020-03-24 15:24:25

标签: git

假设我有以下历史记录日志:

* 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和历史记录,使其看起来相同。请注意,我之间也有分支,不仅是提交。你会怎么做?

1 个答案:

答案 0 :(得分:0)

您根本无法执行此操作。任何提交的任何部分都不能修改

可以做一些不同的事情,这些事情可能(也可能不是)足够好。

给出任何Git提交,您可以:

  • 提取该提交,以便您可以对其进行处理
  • 做点事
  • 进行一次 new 提交,该提交将具有不同的哈希ID

并完成了 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答案。