【发布时间】:2019-10-16 06:29:25
【问题描述】:
我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?
【问题讨论】:
标签: git git-checkout git-add
我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?
【问题讨论】:
标签: git git-checkout git-add
我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?
假设文件是在Git中,答案是肯定的。
重要的是要认识到,一些已提交文件的可修改副本不是一个,而是 两个,还有 许多 个不能的副本被改变。只读副本存在于每个提交中,因为您所做的每个提交都会保存每个文件的完整快照。1 但它使此快照不是来自副本你查看并与之合作。它从 second 可修改副本生成快照,Git 将其保存在 Git 有时称为 index 有时称为 staging area 的位置。
index 和 staging area 指的是同一个东西。它有时也称为缓存。 The gitglossary 将 cache 定义为“索引已过时”。考虑索引的一种好方法是它是提议的下一次提交。当您签出一些现有的提交时,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 -p 或git show 向您显示提交的父级和提交之间的差异,情况也是如此。这是因为git log -p 或git 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> 更短更快。
【讨论】:
这个在那儿很难找到,所以就在这里。如果您有一个未提交的更改(仅在您的工作副本中)您希望(以 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
【讨论】: