将一个父项的提交重新定位到另一个父项
Rebasing commit from one parent onto another
我有一个正在处理的现有存储库,但最近我学到了很多关于良好实践和 git 本身的知识。我想按照自己的喜好改变我的历史,尤其是一些早期的提交。
以下是当前历史的片段。我想将 e5cb9b8 提交重新定位到 1a92e84,这样我就可以在历史图表中获得 one/two 级别的深度(在视觉上,更改 e5cb9b8 的父级)。我试过变基
git rebase -p --onto 1a92e84 e5cb9b8 master
并挑选到从 9ecbe00 创建的新分支。 Cherrypicking 让我的历史变得平坦,rebase 失败并显示以下消息
error: commit ca230d8c048d22de6f219da8a22e70a773827c38 is a merge but no -m option was given.
fatal: cherry-pick failed
Could not pick ca230d8c048d22de6f219da8a22e70a773827c38
* | 45a0a21 - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8 - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8 - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
* | 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ \
| |/
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
预计:
* | 45a0a21' - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8' - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8' - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
|/
* 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\
| |
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
我在 Whosebug 上搜索了类似的问题,似乎没有人描述过如此深入历史的此类修改。
解决方案
好的,为了未来的读者和我自己,我正在写下我的问题的解决方案。 @alfunx 是解决它的关键 - 我在 git rebase
和 git rebase --onto
的其他主题解释中找到并开始在我的存储库上进行试验。通过反复试验,我设法*通过执行
实现了预期的历史图
git rebase -ir --onto 1a92e84 81761ff develop
并替换待办事项列表的后续片段
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset 9ecbe00 # Initial commit
merge -C 1a92e84 onto # Merge pull request #1 from KamilPacanek/enable-gh-pages
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
以下(更改了重置位置并删除了一个,多余的,合并提交):
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset onto
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
*)
实际上,要达到那种状态还有很多工作要做,但我不想用次要问题混淆解决方案。第一个 git rebase
失败并显示该消息:
error: refusing to update ref with bad name 'refs/rewritten/Implement-durability-loss.'
hint: Could not execute the todo command
hint: label Implement-durability-loss.
如您所见,我在提交消息的末尾有一个句号。在我解决了这个问题之后(通过 reword
命令的另一个变基)我能够继续前进。
此外,似乎 git rebase --abort
doesn't clear 在 git rebase -r
期间创建的 refs。所以我的历史记录一团糟。通过 rm -rf .git/refs/rewritten
解决了那个问题。另一件事,我有一个剩余的 .git/sequencer 文件夹,可以通过 git revert --quit
.
移除
你为 rebase 选择的基数是错误的,应该是 81761ff
而不是 e5cb9b8
。我建议您进行交互式变基并使用 --rebase-merges
而不是 --preserve-merges
。所以命令应该是:
git rebase -ir --onto 1a92e84 81761ff master
现在,Git 可能会产生一个额外的合并提交。为避免这种情况并产生您想要的结果,您应该将 todo-list 调整为:
label onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label new
reset onto
merge -C ca230d8 new
pick 45a0a21 #17 Updates README.md
# Remaining commits...
在todo-list中,label
可以用来标记当前提交(HEAD
),而reset
可以用来设置HEAD
一些 commit/label。 merge
显然用于生成合并提交,-C
使合并使用与原始合并提交相同的提交消息。
这是相当高级的,实际上大多数用户和用例不需要,所以请考虑 man git-rebase
,部分 Rebase Merges(或the online version here)以获得更深入的信息。那里的例子其实和你的情况很相似
如果您使用 git rebase -ir
,请使用 Git 2.25(2020 年第一季度)。
由“git rebase --rebase-merges
”生成的 todo
列表中使用的标签用作引用名称的一部分;提出标签的逻辑已经收紧,以避免不能这样使用的名称。
参见 commit cd55222 (17 Nov 2019) by Matthew Rogers (soniqua
)。
参见 commit 867bc1d (17 Nov 2019) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 917d0d6 合并,2019 年 12 月 5 日)
rebase -r
: let label
generate safer labels
Signed-off-by: Matthew Rogers
Signed-off-by: Johannes Schindelin
The label
todo command in interactive rebases creates temporary refs in the refs/rewritten/
namespace. These refs are stored as loose refs, i.e. as files in .git/refs/rewritten/
, therefore they have to conform with file name limitations on the current filesystem in addition to the accepted ref format.
This poses a problem in particular on NTFS/FAT, where e.g. the colon, double-quote and pipe characters are disallowed as part of a file name.
Let's safeguard against this by replacing not only white-space characters by dashes, but all non-alpha-numeric ones.
However, we exempt non-ASCII UTF-8 characters from that, as it should be quite possible to reflect branch names such as ↯↯↯
in refs/file names.
并且:
使用 Git 2.25(2020 年第一季度),避免由“git rebase --rebase-merges
”生成的重复标签名称的逻辑忘记了机器本身使用“onto
”作为标签名称,自动生成的标签必须避免这种情况,已更正。
参见 commit e02058a (18 Nov 2019) by Doan Tran Cong Danh (congdanhqx-zz
)。
(由 Junio C Hamano -- gitster
-- in commit 995b1b1 合并,2019 年 12 月 5 日)
sequencer
: handle rebase-merges for "onto" message
Signed-off-by: Doan Tran Cong Danh
Acked-by: Johannes Schindelin
In order to work correctly, git rebase --rebase-merges
needs to make initial todo list with unique labels.
Those unique labels is being handled by employing a hashmap and appending an unique number if any duplicate is found.
But, we forget that beside those labels for side branches, we also have a special label onto
for our so-called new-base.
In a special case that any of those labels for side branches named `onto', git will run into trouble.
Correct it.
我有一个正在处理的现有存储库,但最近我学到了很多关于良好实践和 git 本身的知识。我想按照自己的喜好改变我的历史,尤其是一些早期的提交。
以下是当前历史的片段。我想将 e5cb9b8 提交重新定位到 1a92e84,这样我就可以在历史图表中获得 one/two 级别的深度(在视觉上,更改 e5cb9b8 的父级)。我试过变基
git rebase -p --onto 1a92e84 e5cb9b8 master
并挑选到从 9ecbe00 创建的新分支。 Cherrypicking 让我的历史变得平坦,rebase 失败并显示以下消息
error: commit ca230d8c048d22de6f219da8a22e70a773827c38 is a merge but no -m option was given.
fatal: cherry-pick failed
Could not pick ca230d8c048d22de6f219da8a22e70a773827c38
* | 45a0a21 - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8 - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8 - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
* | 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ \
| |/
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
预计:
* | 45a0a21' - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8' - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8' - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
|/
* 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\
| |
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
我在 Whosebug 上搜索了类似的问题,似乎没有人描述过如此深入历史的此类修改。
解决方案
好的,为了未来的读者和我自己,我正在写下我的问题的解决方案。 @alfunx git rebase
和 git rebase --onto
的其他主题解释中找到并开始在我的存储库上进行试验。通过反复试验,我设法*通过执行
git rebase -ir --onto 1a92e84 81761ff develop
并替换待办事项列表的后续片段
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset 9ecbe00 # Initial commit
merge -C 1a92e84 onto # Merge pull request #1 from KamilPacanek/enable-gh-pages
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
以下(更改了重置位置并删除了一个,多余的,合并提交):
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset onto
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
*)
实际上,要达到那种状态还有很多工作要做,但我不想用次要问题混淆解决方案。第一个 git rebase
失败并显示该消息:
error: refusing to update ref with bad name 'refs/rewritten/Implement-durability-loss.'
hint: Could not execute the todo command
hint: label Implement-durability-loss.
如您所见,我在提交消息的末尾有一个句号。在我解决了这个问题之后(通过 reword
命令的另一个变基)我能够继续前进。
此外,似乎 git rebase --abort
doesn't clear 在 git rebase -r
期间创建的 refs。所以我的历史记录一团糟。通过 rm -rf .git/refs/rewritten
解决了那个问题。另一件事,我有一个剩余的 .git/sequencer 文件夹,可以通过 git revert --quit
.
你为 rebase 选择的基数是错误的,应该是 81761ff
而不是 e5cb9b8
。我建议您进行交互式变基并使用 --rebase-merges
而不是 --preserve-merges
。所以命令应该是:
git rebase -ir --onto 1a92e84 81761ff master
现在,Git 可能会产生一个额外的合并提交。为避免这种情况并产生您想要的结果,您应该将 todo-list 调整为:
label onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label new
reset onto
merge -C ca230d8 new
pick 45a0a21 #17 Updates README.md
# Remaining commits...
在todo-list中,label
可以用来标记当前提交(HEAD
),而reset
可以用来设置HEAD
一些 commit/label。 merge
显然用于生成合并提交,-C
使合并使用与原始合并提交相同的提交消息。
这是相当高级的,实际上大多数用户和用例不需要,所以请考虑 man git-rebase
,部分 Rebase Merges(或the online version here)以获得更深入的信息。那里的例子其实和你的情况很相似
如果您使用 git rebase -ir
,请使用 Git 2.25(2020 年第一季度)。
由“git rebase --rebase-merges
”生成的 todo
列表中使用的标签用作引用名称的一部分;提出标签的逻辑已经收紧,以避免不能这样使用的名称。
参见 commit cd55222 (17 Nov 2019) by Matthew Rogers (soniqua
)。
参见 commit 867bc1d (17 Nov 2019) by Johannes Schindelin (dscho
)。
(由 Junio C Hamano -- gitster
-- in commit 917d0d6 合并,2019 年 12 月 5 日)
rebase -r
: letlabel
generate safer labelsSigned-off-by: Matthew Rogers
Signed-off-by: Johannes SchindelinThe
label
todo command in interactive rebases creates temporary refs in therefs/rewritten/
namespace. These refs are stored as loose refs, i.e. as files in.git/refs/rewritten/
, therefore they have to conform with file name limitations on the current filesystem in addition to the accepted ref format.This poses a problem in particular on NTFS/FAT, where e.g. the colon, double-quote and pipe characters are disallowed as part of a file name.
Let's safeguard against this by replacing not only white-space characters by dashes, but all non-alpha-numeric ones.
However, we exempt non-ASCII UTF-8 characters from that, as it should be quite possible to reflect branch names such as
↯↯↯
in refs/file names.
并且:
使用 Git 2.25(2020 年第一季度),避免由“git rebase --rebase-merges
”生成的重复标签名称的逻辑忘记了机器本身使用“onto
”作为标签名称,自动生成的标签必须避免这种情况,已更正。
参见 commit e02058a (18 Nov 2019) by Doan Tran Cong Danh (congdanhqx-zz
)。
(由 Junio C Hamano -- gitster
-- in commit 995b1b1 合并,2019 年 12 月 5 日)
sequencer
: handle rebase-merges for "onto" messageSigned-off-by: Doan Tran Cong Danh
Acked-by: Johannes SchindelinIn order to work correctly,
git rebase --rebase-merges
needs to make initial todo list with unique labels.Those unique labels is being handled by employing a hashmap and appending an unique number if any duplicate is found.
But, we forget that beside those labels for side branches, we also have a special label
onto
for our so-called new-base.In a special case that any of those labels for side branches named `onto', git will run into trouble.
Correct it.