我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?
2 回答
我想知道是否有办法回到 git 上文件的先前更改。如果我创建一个 .txt 文件,我编辑它但我没有“git add”我可以运行“git checkout - file.txt”并返回,但是在执行“git add”之后有没有办法做到这一点?
如果文件在Git 中,答案是肯定的。
重要的是要意识到一些已经提交的文件不是一个而是两个可修改的副本,以及许多无法更改的副本。只读副本位于每个提交中,因为您所做的每个提交都会保存每个文件的完整快照。1 但它使此快照不是来自您看到和使用的副本。它从第二个可修改副本创建快照,Git 将其保存在 Git 有时称为index有时称为staging area的地方。
名称索引和暂存区指的是同一件事。它有时也称为缓存。 gitglossary将缓存定义为“索引过时”。考虑索引的一种好方法是它是建议的 next commit。当您签出一些现有提交时,Git 会从该现有提交中填充索引和工作树。当您运行 时,Git 将 的当前版本复制到索引中,替换索引中的副本。也就是说,只需更新提议的新提交。git add file
file
git add
(如果 Git 直接从工作树提交,你根本不需要索引。但是 Git 不会从工作树提交,并且索引在冲突合并期间扮演扩展角色,所以你是有点坚持学习索引。)
通常,您使用切换到一个分支,但您也可以编写或。2 这些都不同于:git checkout branchname
git checkout [--] filename
git checkout branchname [--] filename
git checkout branchname
git checkout branchname
表示切换分支。git checkout branchname [--] filename
表示从命名分支尖端的提交中获取给定文件。3git checkout [--] filename
表示从索引/暂存区获取给定文件。
我喜欢考虑这个问题的方式是,当您进行新提交时,该文件有三个活动副本。一个是您当前(HEAD
或@
)提交中的冻结文件,一个是您在索引中提议的下一个提交中的可修改副本,第三个是您可以查看和使用的普通文件。使用git checkout -- file.txt
gets,进入你可以使用它的工作树,中间的副本——索引副本——你已经用你之前的git add
. 因此,您想要git checkout HEAD -- file.txt
:这将获得只读的、已提交的副本。此时,它会在索引和您的工作树中结束,因此两个可修改的副本都已被此命令覆盖。4 您提议的新提交具有file.txt
当前提交之外的旧版本,并且您的工作树具有file.txt
当前提交之外的旧版本。所有三个副本——<code>HEAD、索引和工作树——再次匹配。
1即使git log -p
或git show
向您展示了提交的父级和提交之间的差异,这也是正确的。那是因为git log -p
orgit show
发现差异的方式是它提取文件的父提交的副本和提交的副本,然后比较它们以查看有什么不同。
Because the committed copies are read-only, every commit that re-uses an old version of the file, doesn't make a new copy, it just refers back to the existing, already-frozen copy. So the fact that, say, README.md
is in a thousand commits, with all the README.md
copies exactly the same, really means that there's one copy, shared across the thousand commits.
2The square brackets in [--]
indicate that the --
is optional. It's a good habit to get into using it when you mean the next part is a file name. Suppose you create a file named master
. Later, you run:
git checkout master
Did you mean: Get me the file named master
, or did you mean: *Switch to branch master`? If you type in:
git checkout -- master
Git knows you meant Get me the file named master
. Whatever comes after --
is assumed to be a file name. If you type this in without the --
, Git thinks you mean switch to branch master
.
3You can put in a commit hash ID, or any other name or string that resolves to a commit, here.
4Git being what it is, there's another way to do all of this. Actually there are many ways, but there is one other main way: you can use git reset [--] filename
to copy from HEAD
to the index, then git checkout [--] filename
to copy from index to work-tree. But git checkout commit-ish -- filename
is shorter and faster.
这个在那儿很难找到,所以就在这里。如果您有一个未提交的更改(仅在您的工作副本中)您希望(以 SVN 术语)恢复到最新提交中的副本,请执行以下操作:
git checkout filename
这将从 HEAD 签出文件,覆盖您的更改。该命令也用于检出分支,您可能碰巧有一个与分支同名的文件。一切都不会丢失,您只需键入:
git checkout -- filename
您也可以对来自其他分支的文件等执行此操作。man git-checkout 有详细信息。
Internet 的其余部分会告诉您使用 git reset --hard,但这会重置您在工作副本中所做的所有未提交的更改。小心输入。
来自https://www.norbauer.com/rails-consulting/notes/git-revert-reset-a-single-file