【问题标题】:How to roll back (reset) a committed change in git on a single file如何在单个文件上回滚(重置)git中已提交的更改
【发布时间】:2025-12-07 07:45:01
【问题描述】:

我的功能分支上有一个提交,由 3 个文件组成,其中一个现在与 master 存在合并冲突。

我想:

  • 回滚对冲突文件的提交
  • 从 master 变基到有冲突的文件
  • 在该文件上手动重新应用我回滚的更改

我尝试过还原,但这适用于整个提交而不是单个文件。

我已经尝试检查单个文件(在我想要回滚的提交之前的修订版)并提交它(基本上恢复单个文件)。但是,当我重新设置基准时,冲突仍然会发生。

我觉得我需要以某种方式对这个单个文件进行硬重置,但我看不到重置单个文件的方法。

【问题讨论】:

    标签: git git-merge git-rebase git-reset


    【解决方案1】:

    您可以在另一个提交中使用 git checkoutget a single file,如下所示:

    git checkout <commit> -- path/to/file
    

    为防止冲突,您应该将新提交压缩到前一个(冲突的)提交中。


    变基将应用列表中的每个提交,一次一个。如果您有冲突,那么每次变基时,您都必须重新解决该冲突。这就是我更喜欢一个好的 ol' 合并的原因之一。合并发生在堆栈的顶部(因此您的反冲突提交将适用),您遇到的任何冲突只需要解决一次。

    如果您真的想使用变基,那么您可以git rebase -i HEAD~N(其中 N 是您需要返回到有冲突的提交的许多提交)然后直接编辑该提交(在旁边放置一个 e它在编辑器中)或将第二个提交压缩到第一个(在新提交旁边放置一个s)。基本上,您需要更改提交历史记录。然后你应该能够从 master 中变基。

    【讨论】:

    • 我试过了,但是之后的 rebase 失败了:“我已经尝试检查单个文件(在我想要回滚的提交之前的修订版)并提交(基本上恢复单个文件)文件)。但是,当我重新设置基准时,冲突仍然会发生。“
    • 将两个提交压缩在一起有帮助!
    【解决方案2】:

    这里的问题是概念性的:您正在使用适用于提交的命令,并尝试将它们应用于文件,这会扭曲您对如何解决手头问题的推理。

    澄清:文件不是单独提交的。每个提交都有一个TREE,代表整个项目内容的状态。您更改了三个文件,这将创建内容的新状态; git commit,这将创建 一个新的 COMMIT 对象,其中 TREE 代表项目的新状态。

    也许混淆来自对其他源代码控制工具的熟悉。 git 使用的提交模型与 CVS 不同,CVS 将更改提交到单个版本化文件。

    因此,如果您使用 reset 之类的内容回滚,您将撤消 所有 的更改。如果您 rebasemaster 获取更改,您将获得 所有来自 master 的更改。

    这并不意味着你无法到达你想去的地方;你只需要用不同的方式来处理它。

    最简单(也是 IMO 最适合这种情况)的做法是在合并操作期间解决此问题。一旦 get 告诉你有冲突,你可以得到一个冲突文件的masters 版本

    git checkout master -- path/to/conflicting/file
    

    然后您可以使用您正在使用的任何编辑器或 IDE 手动重新应用您的更改。 (如果您需要查看最初所做的更改,您可以随时 git diff HEADgit merge-base HEAD master-- path/to/conflicting/file。)然后

    git add path/to/conflicting/file
    

    将冲突标记为已解决,并且

    git commit
    

    完成合并。

    【讨论】:

    • 你是对的。我猜我在哪里说“从 master 变基到有冲突的文件”真的我想简单地“从 master 变基”。因为虽然我希望从 master 对单个文件进行更改,但将文件与 master 隔离开来并没有多大意义。想要回滚单个文件的目的是让我只需要在那个文件上重新应用我的更改,而不是为我的整个提交。我仍然不明白合并比在这里变基“更好”,因为变基会导致更清晰的历史记录,不是吗?
    • 好的,我现在明白了一点。合并保留了历史,从而更容易回滚/修复由合并/冲突引入的问题。我想我以丢失信息为代价沉迷于清白的历史。
    • @andrea- 抱歉,回到这个话题……是的,rebase 有利有弊。许多人发现通过频繁变基可以获得的线性历史令人愉悦。但它也可以创建被破坏的中间提交,并且根据协作开发的方法,可能存在其他问题。我的回答是为了完成合并,因为这似乎是您所要求的; rebase 解决方案是可能的,但可能需要额外的冲突解决步骤。
    • 我实际上最终撤消了变基并进行了合并以保留历史记录(幸运的是,我在我的机器上有一个预变基克隆,我可以强制推送到服务器,从而取消了变基)。但是另一个答案仍然更准确地回答了我可能被误导的问题,即使这个更接近我实际所做的!
    最近更新 更多