如何给旧的git提交添加额外的父提交?

izkcnapc  于 2023-02-28  发布在  Git
关注(0)|答案(5)|浏览(184)

我有一个包含两个分支的项目:master和gh-pages。它们本质上是两个不同的项目,gh-pages项目依赖于master项目(反之亦然)。可以将其视为“master包含源代码,gh-pages包含从这些源文件构建的二进制文件”。定期地,我将master中累积的更改提交给gh-pages分支,并使用提交消息“与主委托xxxxxxxx保持一致。”

这样做了一段时间后,我意识到如果gh-pages提交“Bring in line with master commit xxxxxxxx”在git仓库中的父提交是xxxxxxxx,那就更好了。

有没有办法让仓库看起来像上面第二张图?我知道如何让新提交遵循这个模式:我可以在“git commit--amend adv550.z8”(这里adv550.z8是实际上正在修改的二进制文件)之后执行“git merge -s ours master”(设置一个空提交的父提交),但是git能让我们很容易地回到过去,在旧提交中添加新的父提交吗?
我非常愿意“git push -f”,并吹走我的Github存储库的当前历史,一旦我得到我的本地repo看起来正确。问题是,* 能 * 我得到我的本地repo看起来正确吗?

**几年后编辑补充:**我最终放弃了让gh-pages的git历史看起来像这样的尝试;我认为这样做工作量太大,没有任何好处。我的新做法是积极地压缩提交到gh-pages,因为保存这些提交消息对我来说真的不重要。(这只是一长串“与主提交保持一致......“,没有一个是历史上有趣的。)然而,如果我需要再次这样做,我会听取这样的回答

git merge $intended_parent_1 $intended_parent_2
git checkout $original_commit -- .
git commit --amend -a -C $original_commit
nszi6y05

nszi6y051#

git replace --graft $commit $parent1 $optional_parent2
git replace --graft $original_commit \
    $(git show --pretty=%P $original_commit) \
    $additional_parent

说明:git replace --graft允许重新指定某个提交的父提交,其工作方式是写一个带有相应修改的新提交,并写一个replace ref,使git在访问新提交时查找新提交而不是原来的提交。
git show --pretty=%P $original_commit只列出原始父对象。

j1dl9f46

j1dl9f462#

这是你的咒语

git merge origin/master --strategy ours

gh-pages分支中执行此命令,以便记录与master的关系,而不实际更改任何内容。当我创建gh-pages分支--orphan时,这对我很有效,如this answer
你甚至可以在之后提交--amend这个空的合并提交,以引入你真正想对你的“页面”所做的修改。

qnzebej0

qnzebej03#

你不能回到过去改变已经存在的提交,即使你做了git commit --amend这样的操作,你也没有真正改变提交;您将在树中的同一位置创建一个新的存储库,其中包含原始存储库的所有内容(加上您的更改),您将注意到提交哈希在--amend之后发生了更改,原始存储库仍然存在--您可以使用git reflog返回到它。
另一方面,你可以回到过去,创建另一个宇宙。本质上,你可以回到你的gh-pages分支点,重新创建整个分支(例如git cherry-pick或其他)作为一个并行分支。哈希值会改变,因为提交是不同的对象。
(我很好奇为什么要将repo设置为单独的分支,而不是同一个分支中的单独目录。看起来code -〉build过程会变得很乏味。)

0md85ypi

0md85ypi4#

@rumpel给出了正确的答案,请允许我分享我使用的片段。
首先,我创建了孤立的master分支:

git checkout --orphan master
git commit --allow-empty -m 'Init'

我的用例稍有不同,我想要的站点在develop分支上的_site目录中。

git checkout master
git rm -rf .
git read-tree develop^{tree}:_site
git checkout -- .
git commit -m "Update from develop SHA1:$(git rev-parse --short develop) ($(git log -1 --format=%cd develop))"
git replace --graft @ $(git show --pretty=%P @ | head -n1) develop

注意,在最后一个命令中,我必须按| head -n1进行过滤,因为git的输出远不止父对象。

mw3dktmi

mw3dktmi5#

你可以重写提交,但这需要重写整个分支,从第一个需要额外父提交的提交开始,直到分支尖端。Is(和rebase一样)是一个新的分支,只是有相同的内容。
诀窍是使用commit-tree,它包含所有内容(提交者/作者信息、时间戳、提交消息、父节点列表),尽管这是一种相当不实用的方式。

相关问题