【问题标题】:git checkout after a git add?git add 之后的 git checkout?
【发布时间】:2019-10-16 06:29:25
【问题描述】:

我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?

【问题讨论】:

    标签: git git-checkout git-add


    【解决方案1】:

    我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?

    假设文件在Git中,答案是肯定的。

    重要的是要认识到,一些已提交文件的可修改副本不是一个,而是 两个,还有 许多不能的副本被改变。只读副本存在于每个提交中,因为您所做的每个提交都会保存每个文件的完整快照。1 但它使此快照不是来自副本查看并与之合作。它从 second 可修改副本生成快照,Git 将其保存在 Git 有时称为 index 有时称为 staging area 的位置。

    indexstaging area 指的是同一个东西。它有时也称为缓存The gitglossarycache 定义为“索引已过时”。考虑索引的一种好方法是它是提议的下一次提交。当您签出一些现有的提交时,Git 会同时填写索引 来自该现有提交的工作树。当您运行 git add <em>file</em> 时,Git 会将当前版本的 file 复制到索引中,替换索引中 曾经 的副本。也就是说,git add 只是更新提议的新提交。

    (如果 Git 直接从工作树提交,则根本不需要索引。但 Git 不会从工作树提交,并且索引在冲突合并期间扮演扩展角色,所以你有点卡在学习索引上。)

    通常你使用git checkout <em>branchname</em>切换到一个分支,但你也可以写git checkout [--] <em>filename</em>git checkout <em>branchname</em> [--] <em>filename</em>2这两个都不同于git checkout <em>branchname</em>

    • git checkout <em>branchname</em> 表示切换分支
    • git checkout <em>branchname</em> [--] <em>filename</em> 表示从指定分支顶端的提交中获取给定文件3
    • git checkout [--] <em>filename</em> 表示从索引/暂存区获取给定文件

    我想这样想的方式是,当您进行新的提交时,该文件有 三个 活动副本。一个是您当前(HEAD@)提交中的冻结文件,一个是您在索引中提议的下一个提交中的可修改副本,第三个是您可以查看和使用的普通文件。使用git checkout -- file.txt 进入工作树,您可以在其中使用它,middle 副本 - 索引副本 - 您已经用之前的 git add 覆盖了它。因此,您需要git checkout HEAD -- file.txt:这将获得只读的、已提交的副本。此时,它在您的工作树中的索引 中结束,因此这两个可修改副本都已被此命令覆盖。4 您提出的新提交有旧版本的 file.txt 在当前提交之外,你的工作树有旧版本的 file.txt 在当前提交之外。所有三个副本——HEAD、索引和工作树——再次匹配。


    1即使git log -pgit show 向您显示提交的父级和提交之间的差异,情况也是如此。这是因为git log -pgit show 发现差异的方式是,它同时提取文件的父提交副本和提交副本,然后将它们进行比较以查看有什么不同。

    因为提交的副本只读的,每个重用旧版本文件的提交不会产生新的 em> copy,它只是指回现有的,已经冻结的副本。因此,例如,README.md 在一千个提交中,所有 README.md 副本完全相同,这实际上意味着有一千个提交共享一个副本。

    2[--] 中的方括号表示-- 是可选的。当您的意思是下一部分是文件名时,开始使用它是一个好习惯。假设您创建了一个名为master文件。稍后,您运行:

    git checkout master
    

    你的意思是:给我一个名为master的文件,还是你的意思是:*切换到分支master`?如果你输入:

    git checkout -- master
    

    Git 知道你的意思给我一个名为master 的文件。-- 之后的任何内容都被假定为一个文件名。如果你在没有-- 的情况下输入这个,Git 认为你的意思是切换到分支master

    3您可以在此处输入提交哈希 ID,或解析为提交的任何其他名称或字符串。

    4Git 就是这样,还有另一种方法可以完成这一切。其实有很多方法,但是还有另外一种main方法:你可以使用git reset [--] <em>filename</em>HEAD复制到索引,然后git checkout [--] <em>filename</em>从索引复制到工作树。但是git checkout <em>commit-ish</em> -- <em>filename</em> 更短更快。

    【讨论】:

      【解决方案2】:

      这个在那儿很难找到,所以就在这里。如果您有一个未提交的更改(仅在您的工作副本中)您希望(以 SVN 术语)恢复到最新提交中的副本,请执行以下操作:

      git checkout filename
      

      这将从 HEAD 签出文件,覆盖您的更改。该命令也用于检出分支,您可能碰巧有一个与分支同名的文件。一切都不会丢失,您只需输入:

      git checkout -- filename
      

      您也可以对来自其他分支的文件执行此操作,等等。 man git-checkout 有详细信息。

      互联网上的其他人会告诉你使用 git reset --hard,但这会重置你在工作副本中所做的所有未提交的更改。小心输入。

      来自https://www.norbauer.com/rails-consulting/notes/git-revert-reset-a-single-file

      【讨论】:

      • 好的,我试过了,但它不起作用我执行“cat file.txt”来查看它是否已更改并取消,但它什么也没做。如果我之前已经将文件放在 github 上,如果我现在更改它并执行“结帐”,它就不起作用并且保持不变。
      猜你喜欢
      • 2012-07-17
      • 2014-09-11
      • 2022-11-10
      • 1970-01-01
      • 2013-12-22
      • 2019-10-21
      • 2018-07-09
      • 2016-02-14
      • 2010-10-09
      相关资源
      最近更新 更多