将推送的分支恢复为具体的提交

Posted

技术标签:

【中文标题】将推送的分支恢复为具体的提交【英文标题】:Revert pushed branch to a concrete commit 【发布时间】:2012-05-07 00:59:15 【问题描述】:

我已将一个 dev 分支(具有恒定的,有时是不稳定的更改)合并到我们的 master 分支(我们存储已发布的稳定代码的地方)。我想将 master 分支恢复到之前的状态,就像从未发生过与 dev 分支的合并一样(并且当将来我们合并 dev 分支时,我们现在将丢弃的所有更改都将“再次”合并)。

这是 master 分支的当前状态,我希望它在 HEAD 处具有“professional-1.1.2”提交/标记。

我试过了:

$ git revert -n professional-1.1.2..HEAD
fatal: Commit 9167e846a387c793edbc089c7ab6bd9eb8260456 is a merge but no -m option was given.
$ git revert -n -m 1 professional-1.1.2..HEAD
fatal: Mainline was specified but commit 380169097f35d07466640bc0db1b639278cd25fa is not a merge.
$ git revert -n -m 2 professional-1.1.2..HEAD
fatal: Mainline was specified but commit 380169097f35d07466640bc0db1b639278cd25fa is not a merge.

经过一番研究,我认为更好的选择是使用git reset --hard professional-1.1.2git push --force 作为Git: How to ignore fast forward and revert origin [branch] to earlier commit? 或reverting push'd git commit 的答案。其他开发人员在同一个办公室,他们不应该向 master 提交任何东西(我也不应该,但是......是的,我们没有每个分支的权限),所以告诉他们并做任何事情都不是什么大问题需要采取行动。

所以最后的问题是:git revert something 还是git reset --hard <TAG> && git push --force?如果git revert,我应该使用哪个命令行?

【问题讨论】:

Jefromi 在***.com/questions/3556501/… 中给出的答案可能会对您有所帮助。 @vpatil 在我的情况下使用git reset --hard 比使用git revert 更好吗? 是的,我认为是这样,因为 revert 创建了一个新的提交,它取消了最后一次提交。我肯定会建议使用重置。 @CarlosCampderrós 唯一的规则是永远不要覆盖公共存储库中的历史记录。如果它是您的私有存储库,您可以为所欲为。但是在公共存储库中,如果您重写历史记录,就会破坏所有已经下载您正在重写的部分的存储库。 @Let_Me_Be 是的,我知道。我真的不喜欢这样做,但最后我认为对于我目前的情况是最好的选择,因为环境是可控的,没有人应该对 master 分支中的代码什么都不做。 【参考方案1】:

-m number 选项指定要恢复到哪个父级(因为合并有多个父级)。

所以你想要git revert -m 1 HEADgit revert -m 1 SHA_OF_MERGE_COMMIT(假设你做了git checkout master; git merge devel;

【讨论】:

但我不想只恢复合并提交,而是该合并附带的所有提交。顺便说一句,我编辑git checkout master; git pull origin develop @CarlosCampderrós 你认为合并提交是什么?是的,这将恢复合并,这意味着:它将删除您合并到分支中的所有更改。 好的,我只是恢复语法错误(所以当我第一次尝试时它不起作用(正如你在问题中看到的那样))并且当我使用你的答案时我选择了错误的父级。现在......如果我在 2 个月内再次合并 dev 分支,我正在恢复的所有提交都将被合并?还是只合并我现在要恢复的合并后的更改? @CarlosCampderrós 合并不关心提交。合并将合并两个(或更多)HEAD。历史上的内容完全无关紧要。只有 HEAD 上的当前状态是相关的。 @Let_Me_Be:实际上,这取决于使用哪种合并策略-git的基本三向策略考虑两个父母共同的祖先-历史上的提交是用作共同祖先对合并的结果有很大的影响。【参考方案2】:

如果你只是想让master的状态和professional-1.1.2完全一样,同时避免重写历史和强制推送,你可以在master上创建一个代表相同状态的新提交项目为professional-1.1.2。您可以通过以下步骤做到这一点:

# Check that "git status" is clean, since the steps that follow will throw
# way uncommitted changes:
git status

# Set the index (staging area) to be as it was at professional-1.1.2:
git read-tree professional-1.1.2

# Create a commit based on that index:
git commit -m "Reverting to the state at professional-1.1.2"

# Your working tree will still be as it was when you started, so
# you'll want to reset that to the new commit:
git reset --hard

作为替代方案,您可以按照this answer by Charles Bailey 中建议的步骤进行操作,它完成了同样的事情,但我认为有点混乱(即使我建议的步骤涉及“管道”命令git read-tree )。

【讨论】:

使用这个(以专业 1.1.2 的状态进行新的提交并推送它),这是否允许开发分支的未来合并再次带来我现在所做的更改“还原”? 如果我建议引入的提交以对象名称f414f31 结尾,我认为您可以通过在git merge dev 之前执行git revert f414f31 来使未来的合并工作。 (我觉得原理和reverting-a-reverted-merge是一样的。) 读完code.google.com/p/git-core/source/browse/Documentation/howto/…我认为你是对的@MarkLongair。这更复杂且容易出错(因为可能在执行git merge dev 之前我们忘记了还原还原。由于回购是私有的并且环境是受控的,我想我会选择git reset --hardgit push --force . @CarlosCampderrós:是的 - 我不清楚分支机构的公开程度。只要您与可能从该分支撤出的任何人交谈并向他们解释如何处理重写的历史,就可以采用其他方法...【参考方案3】:

如果你是个胆大的人(对于所有其他提交者来说,从上游 rebase 中恢复可能是必要的)

git checkout yourbranch
git reset HEAD <commit-hash>
git push origin yourbranch -f

【讨论】:

以上是关于将推送的分支恢复为具体的提交的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个 Git 提交(已推送)还原到已发布的存储库?

在没有变基的情况下恢复合并

恢复到不属于任何分支的提交

从 GitHub.com 上的受保护分支恢复合并提交

sh 将所有未提交的更改移动到新分支,并将现有分支恢复为HEAD。“master”具有未提交的更改。你决定了

如何查看新的 git 分支将推送哪些 git 提交?