【问题标题】:Git - how to get a new file from a future commit when rolling backGit - 回滚时如何从未来的提交中获取新文件
【发布时间】:2015-11-13 17:20:02
【问题描述】:

我有一个 git 分支,上面有正常的 Git 提交历史;在整个开发周期中都有添加/修改/删除。

我想回滚到以前的提交,但保留当前提交中的文件,该文件不在我要回滚的提交中(或者将其翻转,从未来提交中签出文件当前提交中不存在)。

例如:

--------A--------B--------- ...
                 + myFile.txt;

 $ git checkout #A

我想签出提交 #A,但保留在提交 #B 中添加的 myFile.txt

【问题讨论】:

  • 我会签出 A,将我想维护的文件复制到另一个地方,回滚到 B,然后将文件放回去。
  • 谢谢!其他方式虽然;)A在B之前提交,我会回滚到A :)

标签: git git-checkout


【解决方案1】:

您可以使用 git checkout 来执行此操作,它将路径作为可选参数:

git checkout <commit> <path>

假设您当前正处于哈希 B 的提交中,并且您想要重置除 goodFile.txt 之外的所有文件,以及提交 A 中的状态。

git checkout A签出您想要从中获取大部分文件的提交

git checkout B goodFile.txt 现在从提交 B 中签出特定的好文件

git commit goodFile.txt 提交。

您现在将有一个新的提交,因为它的父级包含来自 A 的所有文件和来自 B 的 goodFile.txt

【讨论】:

  • checkout 时需要将命名的提交和文件路径用“--”隔开,提交前不要忘记运行git add goodFile.txt
  • @joran 尽我所能告诉你不需要“--”,没有它它对我有用。你能解释一下什么时候需要“--”,什么时候不需要?
  • 另外,git checkout goodFile.txt 似乎会自动暂存签出的文件。
  • 你是对的,索引在工作树之前更新,不需要暂存文件,在这种情况下不需要使用“--”。如果您已将 tree-ish 命名为与文件路径相同的名称,则需要使用“--”来签出文件,而不是命名的 tree-ish。每天都能学到新东西。
【解决方案2】:

将文件 myFile.txt 从 git repo 复制到某处,然后签出 A。将文件复制回 repo 中。

【讨论】:

    【解决方案3】:

    记下您当前的提交 SHA。您可以使用git show 获取文件在该 SHA 的状态,并在回滚后重现它。

    git show abcd1234:path/to/file > path/to/file
    

    这很方便随时查看任何提交中的任何文件,并且适用于回滚的情况,因为 Git 暂时不会垃圾收集该提交,即使它不再位于您的任何分支上.你至少有,直到它从你的 reflog 中消失,我相信 Git 默认会保留 30 天。

    【讨论】:

      【解决方案4】:

      虽然有多种方法可以获取您想要在回滚时维护的单个文件,但可以轻松想象更复杂的场景,这些场景很快就会变得笨拙。

      这里的主要问题是 A 是否是您将要创建的新分支(作为 B 的修改版本)。如果是,那么您不必担心“重写历史”(因为一切都是新的),并且有一个非常愉快的选择来管理这个和更复杂的场景:git rebase。

      这是一个工作流程,您可以在其中创建一个分支 A,它基于 B,但有一些修改:

      git checkout B          # Go to the tip of branch B.
      git checkout -b A       # Create & checkout a new branch here named A.
      git rebase -i           # Launch interactive rebase
      

      此时,您将进入一个编辑器,其中包含来自 B 分支的所有提交的列表(尽管我们现在在 A 中,是 B 中更改的副本)。帮助文本非常好,但简短的总结是您现在可以重新排序提交(通过重新排序相应的行),删除提交(通过删除其相应的行),将提交压缩在一起(将“pick”更改为“squash”),编辑提交消息,等等。

      对于您的情况,只需删除所有包含您想要丢弃的提交的行,并留下您想要保留的提交。当您对修改后的提交序列感到满意时,保存并退出文件,Git 将磨平,您将留下一个新分支 A,它是原始分支 B 的修改形式。

      Git rebase -i 是一个非常容易养成习惯的超级大国,但请注意,您永远不应该对其他人曾经见过(或已被推送到上游)的现有分支进行 rebase。有空的时候阅读一下“git rebase”,因为这是你的工具箱中肯定需要的 Git 技能。

      【讨论】:

        猜你喜欢
        • 2016-10-18
        • 1970-01-01
        • 2023-02-22
        • 2021-12-11
        • 2018-10-18
        • 2015-05-31
        • 2021-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多