gpt4 book ai didi

git - 在 Git 中恢复一系列推送的 merge 和提交(不重写历史)

转载 作者:IT王子 更新时间:2023-10-29 01:22:55 26 4
gpt4 key购买 nike

上下文

我的一个队友错误地将一些提交推送到我们的主要开发分支。我们是一个小型的、同地协作的团队。我们的远程存储库托管在内部服务器上。

这是我们提交日志的顶部(所有这些提交都已推送):

$ git log develop -6 --pretty=oneline --abbrev-commit
faada93 Merge branch 'develop' of <our_repo_path>.git
244d174 Support classes again
a97a877 Pruned all unused references (again).
8c29252 Merge branch 'develop' of <our_repo_path>.git
a78b993 Support models & methods - product types & categories
da8b496 Resolved JIRA issue PPF-182

da8b496 是我们希望保留在 develop 分支中的最后一次提交,因此我们需要恢复最后 5 次提交。我们从 8c29252 创建了一个新分支,以继续在“功能分支”中工作。

我在 this answer 的指导下尝试了很多东西和 this post from Linus ,最后做了你可以在下面的终端历史记录中看到的事情。但我不确定我最终做的是否是“正确的方式”。我找到的信息很复杂;对于这个特定问题,我无法找出“最佳解决方案”。

问题

我选择的方法(参见下面的详细信息)是否是在不损害我们的历史记录的情况下恢复这 5 次提交的好方法?是否有更简单或“更正确”的方法来完成同样的事情?

除其他事项外,我考虑过从 da8b496 (git checkout -b new-develop da8b496) 创建一个新分支并放弃我们当前的 develop 分支,但感觉不对。


我最终做了什么(详情)

首先,我为提交 a78b9938c29252 创建了一个新分支,因为这些提交包含我们想要保留并最终 merge 回我们的主要开发分支的工作.

$ git checkout -b new-feature-brach 8c29252

然后我开始在我们的开发分支中恢复有问题的提交。

我先尝试了这个,但没有用(可能是因为一些提交是 merge ):

$ git revert a78b993..HEAD
error: a cherry-pick or revert is already in progress
hint: try "git cherry-pick (--continue | --quit | --abort)"
fatal: revert failed

所以……我手动恢复了每个提交;一个一个:

$ git revert -m 1 faada93
[develop 40965a5] Revert "Merge branch 'develop' of <our_repo_path>.git"
8 files changed, 167 insertions(+), 3 deletions(-)

$ git revert 244d174
[develop 3cebd68] Revert "Support classes again"
45 files changed, 557 insertions(+), 1572 deletions(-)
(list of affected files)

$ git revert a97a877
error: could not revert a97a877... Pruned all unused references (again).
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

$ git mergetool
Merging:
exampleFile1.cs
exampleFile2.cs

Deleted merge conflict for 'exampleFile1.cs':
{local}: deleted
{remote}: modified file
Use (m)odified or (d)eleted file, or (a)bort? m

Deleted merge conflict for 'exampleFile2.cs':
{local}: deleted
{remote}: modified file
Use (m)odified or (d)eleted file, or (a)bort? m

$ git commit -m "Adding files to be reverted along with the next commit."
[develop 15bc02b] Adding files to be able to revert the next commit in line.
2 files changed, 239 insertions(+)
(list of affected files here)

$ git revert -m 1 8c29252
# On branch develop
# Your branch is ahead of 'origin/develop' by 3 commits.
# (use "git push" to publish your local commits)
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# exampleFile1.cs.orig
# exampleFile2.cs.orig
nothing added to commit but untracked files present (use "git add" to track)

$ git revert a78b993
[develop 841e77c] Revert "Support models & methods - product types & categories"
2 files changed, 239 deletions(-)
(list of affected files here)

完成所有还原后提交日志:

$ git log develop -10 --pretty=oneline --abbrev-commit
841e77c Revert "Support models & methods - product types & categories"
15bc02b Adding files to be able to revert the next commit in line.
3cebd68 Revert "Support classes again"
40965a5 Revert "Merge branch 'develop' of <our_repo_path>.git"
faada93 Merge branch 'develop' of <our_repo_path>.git
244d174 Support classes again
a97a877 Pruned all unused references (again).
8c29252 Merge branch 'develop' of <our_repo_path>.git
a78b993 Support models & methods - product types & categories
da8b496 Resolved JIRA issue PPF-182

还原后的图表:

$ git log --graph --oneline -8 develop
* 841e77c Revert "Support models & methods - product types & categories"
* 15bc02b Adding files to be able to revert the next commit in line.
* 3cebd68 Revert "Support classes again"
* 40965a5 Revert "Merge branch 'develop' of <our_repo_path>.git"
* faada93 Merge branch 'develop' of <our_repo_path>.git
|\
| * a97a877 Pruned all unused references (again).
| * 8c29252 Merge branch 'develop' of <our_repo_path>.git
| |\
| | * da8b496 Resolved JIRA issue PPF-182

对我来说似乎是正确的。最后,我删除了一些我不想保留的备份文件:

$ git clean -fd
(list of affected files here)

当前状态是干净的:

$ git status
# On branch develop
# Your branch is ahead of 'origin/develop' by 4 commits.
# (use "git push" to publish your local commits)
#
nothing to commit, working directory clean

然后我将所有内容推送回远程:

git push origin develop

最佳答案

即使您的历史已经改变,您也可以创建分支让您返回并进行试验。 Git means never having to say, “you should have.”如果你专注于你更喜欢的现实,那就顺其自然吧。否则,将其丢弃。

下面的示例将创建新的分支,将所有其他内容单独留在您的存储库中。

备选方案 1:git revert

首先在您开始冒险的地方创建一个临时分支。

$ git checkout -b tmp-revert faada93

通过指定提交范围,git revert将撤消多次提交。

$ git revert da8b496..faada93

备选方案 2:git commit-tree

考虑下图 Git Internals — Git Objects ,第二版第 10.2 节 Pro Git斯科特查孔和本斯特劳布。最顶层的提交(“第三次提交”)有一个以 1a410e 开头的 SHA1 散列。在此历史的上下文中,1a410e^{tree} 将解析为 3c4e9c,即紧邻第三次提交右侧的树对象。

Git Object Graph, Figure 151 from *Pro Git*图 151 来自 Pro Git ,第 2 版。

研究此模型以了解 git 如何跟踪内容。创建一个新的第四次提交,其树与第二次提交的相同(即 0155eb)将添加一个新的提交对象,该对象将共享或“指向”现有树和 blob 而不是添加新的重复对象。

继续阅读以了解如何使用 git commit-tree 执行此低级拼接.

首先创建另一个要处理的临时分支。

$ git checkout -b tmp-ctree faada93

此时,您想要创建一个新的提交,其树(即提交的代码)与 da8b496 的树相同,这是您要保留的最后一次提交。这棵树可以在 git 中直接寻址:da8b496^{tree}

git commit-tree 是“管道”,是 git 中的一个低级命令,而不是“瓷器”。使用起来可能会感到尴尬或不熟悉,但在这种情况下,它可以精确控制您想要的结果。

创建一个新的独立提交,其树与 da8b496 相同,其父级 (-p) 是当前分支的顶端,faada93 在你的情况下。请注意,git commit-tree 读取标准输入上新提交的提交消息,下面的命令通过 echo 命令提供。

$ echo Revert back to da8b496 | \    git commit-tree da8b496^{tree} -p $(git rev-parse tmp-ctree)new-commit-sha1

上面的斜体部分不是命令的一部分。它表示 git commit-tree 输出新创建的提交的 SHA1 哈希。知道新提交的 SHA1,您可以将分支移动到该点,例如

$ git merge new-commit-sha1

在上面的命令中,将 new-commit-sha1 替换为 git commit-tree 的输出。 (您可以执行相同的 git reset --hard new-commit-sha1,但硬重置是最好避免随意使用的利器。)

您可以将以上所有内容整合到一个复合命令中。

$ git merge --ff-only $(echo Revert back to da8b496 | \    git commit-tree da8b496^{tree} -p $(git rev-parse tmp-ctree))

--ff-only 切换到git merge是为了防止意外。您的意图是让新提交成为当前分支头的快进或后代——实际上是它的直接子代!

清理

要删除上面的临时分支,请切换到另一个并开火,McManus 先生。您的其他分支将与您离开时一样。

$ git checkout develop$ git branch -D tmp-revert tmp-ctree

这两个应该是相同的,你可以验证

$ git diff tmp-revert tmp-ctree

要保留一个,请将其 merge 到您的 develop 分支中。

$ git checkout develop$ git merge --ff-only tmp-ctree$ git push origin develop

关于git - 在 Git 中恢复一系列推送的 merge 和提交(不重写历史),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18082830/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com