Git 如何在具有子分支的分支上修改提交?
假设我有这个历史记录:Git 如何在具有子分支的分支上修改提交?,git,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_
* 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
提交,并使历史看起来相同。请注意,我在两者之间也有分支,而不仅仅是提交。你会怎么做呢?你根本不能这样做。任何提交的任何部分都不能修改
你可以做一些不同的事情,这可能不够好,也可能不够好
给定任何Git提交,您可以:
- 提取该提交,以便您可以处理它
- 做些工作
- 进行新的提交,该提交将具有不同的哈希ID
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
既然我们有了D'
,我们就把E
复制到它上面,把一个东西的父对象改变成E'
,就像我们复制的方法一样,但把D
改成了D'
:
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
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
我们现在有了新的分支,它们与旧分支“一样好”(因为它们有同样好或更好的提交,但具有不同的散列ID)。现在,我们必须抛弃旧的分支名称,取而代之的是新的分支,也许可以将旧的分支重命名为old.*
,而将新的分支重命名为new.
(我们的旧的*
名称不再非常有用,因此我们迟早可以完全删除它们。)
最后,我们的远程跟踪名称origin/*
正在记住存储在其他Git中的分支名称,因此现在我们必须说服其他Git存储库放弃这些提交的副本,并开始使用我们的新副本。要做到这一点,我们需要使用git push--force
或类似的方法将我们的新提交发送到另一个git,并告诉它放弃您以前的所有工作,转而支持这些新的和改进的提交。例如:
git push --force-with-lease branch_2 branch_3 branch_4
这样做(并且,--force with lease
将确保它们的哈希ID(位于我们的源代码/*
名称中)与我们认为它们所做的匹配)
要在实际情况下实现这一点,请使用git-rebase
或git-filter-branch
或类似工具
当像这样“改进”的提交次数很少时,您可以使用git cherry pick
,一次提交一次,留下自己的标记:例如,新分支3就是这样做的。当它很大的时候,这是痛苦的。您将希望自动化该过程
不幸的是,这很棘手。幸运的是,有几种工具可以实现这一点,包括
git replace
。这样可以插入移植物。但是,移植不会在克隆上传输:任何克隆您的存储库的人都会看到原始的、未移植的历史。幸运的是,git-filter-branch
或新的git-filter-repo
可以将移植的克隆转换为具有一系列新提交的克隆,并整体更新分支名称。有关详细信息,请参阅其他StackOverflow答案。您根本无法执行此操作。任何提交的任何部分都不能修改
你可以做一些不同的事情,这可能不够好,也可能不够好
给定任何Git提交,您可以:
- 提取该提交,以便您可以处理它
- 做些工作
- 进行新的提交,该提交将具有不同的哈希ID
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
既然我们有了D'
,我们就把E
复制到它上面,把一个东西的父对象改变成E'
,就像我们复制的方法一样,但把D
改成了D'
:
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
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
我们现在有了新的分支,它们与旧分支“一样好”(因为它们有同样好或更好的提交,但具有不同的散列ID)。现在,我们必须抛弃旧的分支名称,取而代之的是新的分支,也许可以将旧的分支重命名为old.*
,而将新的分支重命名为new.
(我们的旧的*
名称不再非常有用,因此我们迟早可以完全删除它们。)
最后,我们的远程跟踪名称origin/*
正在记住存储在其他Git中的分支名称,因此现在我们必须说服其他Git存储库放弃这些提交的副本,并开始使用我们的新副本。要做到这一点,我们需要使用git push--force
或类似的方法将我们的新提交发送到另一个git,并告诉它放弃您以前的所有工作,转而支持这些新的和改进的提交。例如:
git push --force-with-lease branch_2 branch_3 branch_4
这样做(并且,--force with lease
将确保它们的哈希ID(位于我们的源代码/*
名称中)与我们认为它们所做的匹配)
要在实际情况下实现这一点,请使用git-rebase
或git-filter-branch
或类似工具
当像这样“改进”的提交次数很少时,您可以使用git cherry pick
,一次提交一次,留下自己的标记:例如,新分支3就是这样做的。当它很大的时候,这是痛苦的。您将希望自动化该过程
不幸的是,这很棘手。幸运的是,有几种工具可以实现这一点,包括
git replace
。这样可以插入移植物。但是,移植不会在克隆上传输:任何克隆您的存储库的人都会看到原始的、未移植的历史。幸运的是,git-filter-branch
或新的git-filter-repo
可以将移植的克隆转换为具有一系列新提交的克隆,并整体更新分支名称。有关详细信息,请参阅其他StackOverflow答案。这是否回答了您的问题?我已经试过了。但是树枝没有被保存下来。相反,这样做会得到两个路径:一个是原始提交和分支,另一个是只有一个分支和所有提交,以及hash4上的新更改