什么是 Git 恢复命令?Git 还原和 Git 重置有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/58003030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is Git Restore Command ? what is the different between Git Restore and Git Reset?
提问by Thinh NV
When I want to Unstaging a Staged File, all of my Git tutorials always show something like that :
当我想取消暂存文件时,我所有的 Git 教程总是显示这样的内容:
$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
modified: CONTRIBUTING.md
The awesome hint shows us use the Git Reset command to Unstaging a Staged File
很棒的提示显示我们使用 Git Reset 命令取消暂存文件
But instead, in my terminal :
但是,在我的终端中:
git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: cat.js -> catcat.js
renamed: tolendo.gogo -> tolendo.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
readme (copy).md
tolendo (copy).txt
zing (copy).html
Not the "(use "git reset HEAD ..." to unstage)"but the (use "git restore --staged ..." to unstage)
不是“(使用“git reset HEAD ...”取消暂存)”而是(使用“git restore --staged ...”取消暂存)
I have no idea about the new restore command and tried to google about the difference about reset and restore but seem nothing fit my question.
我不知道新的恢复命令,并试图谷歌关于重置和恢复的区别,但似乎没有什么适合我的问题。
Can you help me?
你能帮助我吗?
Thanks a lot!
非常感谢!
回答by VonC
I have presented git restore
(which is still marked as "experimental") in "How to reset all files from working directory but not from staging area?", with the recent Git 2.23 (August 2019).
我在最近的 Git 2.23(2019 年 8 月git restore
)中在“如何从工作目录而不是从暂存区重置所有文件?”中介绍了(仍标记为“实验性” )。
It helps separate git checkout
into two commands:
它有助于git checkout
分成两个命令:
- one for files (
git restore
), which can covergit reset
cases. - one for branches (
git switch
, as seen in "Confused by git checkout"), which deals only with branches, not files.
- 一个用于文件 (
git restore
),它可以涵盖git reset
案例。 - 一个用于分支(
git switch
,如“被 git checkout 混淆”中所见),它只处理分支,而不处理文件。
As reset, restore and revertdocumentation states:
作为复位,恢复和还原文档状态:
There are three commands with similar names:
git reset
,git restore
andgit revert
.
git-revert
is about making a new commit that reverts the changes made by other commits.git-restore
is about restoring files in the working tree from either the index or another commit.
This command does not update your branch.
The command can also be used to restore files in the index from another commit.git-reset
is about updating your branch, moving the tip in order to add or remove commits from the branch. This operation changes the commit history.git reset
can also be used to restore the index, overlapping withgit restore
.
有三个名称相似的命令:
git reset
,git restore
和git revert
.
git-revert
是关于进行新提交以恢复其他提交所做的更改。git-restore
是关于从索引或另一个提交恢复工作树中的文件。
此命令不会更新您的分支。
该命令还可用于从另一个提交恢复索引中的文件。git-reset
是关于更新您的分支,移动提示以添加或删除分支中的提交。此操作更改提交历史记录。git reset
也可用于恢复索引,与git restore
.
So:
所以:
To restore a file in the index to match the version in HEAD (this is the same as using
git-reset
)git restore --staged hello.c
or you can restore both the index and the working tree (this the same as using
git-checkout
)git restore --source=HEAD --staged --worktree hello.c
or the short form which is more practical but less readable:
git restore -s@ -SW hello.c
恢复索引中的文件以匹配 HEAD 中的版本(这与使用相同
git-reset
)git restore --staged hello.c
或者您可以同时恢复索引和工作树(这与使用相同
git-checkout
)git restore --source=HEAD --staged --worktree hello.c
或者更实用但可读性较差的简短形式:
git restore -s@ -SW hello.c
With Git 2.25.1 (Feb. 2020), "git restore --staged
" did not correctly update the cache-tree structure, resulting in bogus trees to be written afterwards, which has been corrected.
在 Git 2.25.1(2020 年 2 月)中,“ git restore --staged
”没有正确更新缓存树结构,导致之后写入虚假树,已更正。
See discussion.
见讨论。
See commit e701bab(08 Jan 2020) by Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
--in commit 09e393d, 22 Jan 2020)
请参阅Jeff King ( ) 的commit e701bab(2020 年 1 月 8 日)。(由Junio C Hamano合并-- --在2020 年 1 月 22 日提交 09e393d 中)peff
gitster
restore
: invalidate cache-tree when removing entries with --stagedReported-by: Torsten Krah
Signed-off-by: Jeff KingWhen "
git restore --staged
" removes a path that's in the index, it marks the entry withCE_REMOVE,
but we don't do anything to invalidate the cache-tree.
In the non-staged case, we end up incheckout_worktree()
, which callsremove_marked_cache_entries()
. That actually drops the entries from the index, as well as invalidating the cache-tree and untracked-cache.But with
--staged
, we never callcheckout_worktree()
, and theCE_REMOVE
entries remain. Interestingly, they are dropped when we write out the index, but that means the resulting index is inconsistent: its cache-tree will not match the actual entries, and running "git commit
" immediately after will create the wrong tree.We can solve this by calling
remove_marked_cache_entries()
ourselves before writing out the index. Note that we can't just hoist it out ofcheckout_worktree()
; that function needs to iterate over theCE_REMOVE
entries (to drop their matching worktree files) before removing them.One curiosity about the test: without this patch, it actually triggers a BUG() when running git-restore:
BUG: cache-tree.c:810: new1 with flags 0x4420000 should not be in cache-tree
But in the original problem report, which used a similar recipe,
git restore
actually creates the bogus index (and the commit is created with the wrong tree). I'm not sure why the test here behaves differently than my out-of-suite reproduction, but what's here should catch either symptom (and the fix corrects both cases).
restore
: 使用 --staged 删除条目时使缓存树无效报告人:Torsten Krah
签字人:Jeff King当“
git restore --staged
”删除索引中的路径时,它会标记条目,CE_REMOVE,
但我们不会做任何使缓存树无效的事情。
在非分阶段的情况下,我们最终进入checkout_worktree()
,它调用remove_marked_cache_entries()
。这实际上会从索引中删除条目,并使缓存树和未跟踪缓存无效。但是对于
--staged
,我们从不调用checkout_worktree()
,CE_REMOVE
条目仍然存在。有趣的是,当我们写出索引时它们会被删除,但这意味着结果索引是不一致的:它的缓存树将与实际条目不匹配,然后git commit
立即运行“ ”将创建错误的树。我们可以通过
remove_marked_cache_entries()
在写出索引之前调用自己来解决这个问题。请注意,我们不能只是将其从checkout_worktree()
; 该函数需要CE_REMOVE
在删除条目之前迭代条目(以删除其匹配的工作树文件)。关于测试的一个好奇:如果没有这个补丁,它在运行 git-restore 时实际上会触发一个 BUG():
BUG: cache-tree.c:810: new1 with flags 0x4420000 should not be in cache-tree
但是在使用类似配方的原始问题报告中,
git restore
实际上创建了虚假索引(并且使用错误的树创建了提交)。我不确定为什么这里的测试与我的套件外复制的行为不同,但是这里的内容应该可以捕捉到任何一种症状(并且修复可以纠正这两种情况)。
With Git 2.27 (Q2 2020), "git restore --staged --worktree
" now defaults to take the contents out of "HEAD", instead of erring out.
在 Git 2.27(2020 年第二季度)中,“ git restore --staged --worktree
”现在默认从“HEAD”中取出内容,而不是出错。
See commit 088018e(05 May 2020) by Eric Sunshine (sunshineco
).
(Merged by Junio C Hamano -- gitster
--in commit 4c2941a, 08 May 2020)
请参阅Eric Sunshine ( ) 的提交 088018e(2020 年 5 月 5 日)。(由Junio C Hamano合并-- --在提交 4c2941a 中,2020 年 5 月 8 日)sunshineco
gitster
restore
: default to HEAD when combining --staged and --worktreeSigned-off-by: Eric Sunshine
Reviewed-by: Taylor BlauBy default, files are restored from the index for
--worktree
, and from HEAD for--staged
.When
--worktree
and--staged
are combined,--source
must be specified to disambiguate the restore source, thus making it cumbersome to restore a file in both the worktree and the index.(Due to an oversight, the
--source
requirement, though documented, is not actually enforced.)However, HEAD is also a reasonable default for
--worktree
when combined with--staged
, so make it the default anytime--staged
is used (whether combined with--worktree
or not).
restore
: 组合 --staged 和 --worktree 时默认为 HEAD签字人:Eric Sunshine
评论人:Taylor Blau默认情况下,文件从索引恢复为
--worktree
,从 HEAD恢复--staged
。当
--worktree
和--staged
组合时,--source
必须指定以消除恢复源的歧义,从而使得在工作树和索引中恢复文件变得很麻烦。(由于疏忽,
--source
尽管记录在案,但实际上并未强制执行该要求。)但是, HEAD
--worktree
与 组合时也是合理的默认值--staged
,因此在任何时候--staged
使用时都将其设为默认值(无论是否组合--worktree
)。
So now, this works:
所以现在,这有效:
git restore --staged --worktree
git restore -SW
回答by fieres
For your 1st question "What is git-restore?":
对于您的第一个问题“什么是 git-restore?”:
git-restore is a tool to revert non-commited changes. Non-commited changes are: a) changes in your working copy, or b) content in your index (a.k.a. staging area).
git-restore 是一个恢复未提交更改的工具。未提交的更改是:a) 工作副本中的更改,或 b) 索引中的内容(又名暂存区)。
This command was introduced in git 2.23 (together with the git-switch) to separate multiple concerns previously united in git-checkout.
这个命令是在 git 2.23(与 git-switch 一起)中引入的,用于分离以前在 git-checkout 中联合的多个问题。
git-restore can be used in three different modes, depending on whether you like to revert work in the working copy, in the index, or both.
git-restore 可以在三种不同的模式下使用,具体取决于您是想恢复工作副本、索引中的工作,还是两者兼而有之。
git restore [--worktree] <file>
overwrites <file> in your working copy with the contents in your index (*). In other words, it reverts your changes in the working copy. Whether you specify --worktree
or not does not matter because it is implied if you don't say otherwise.
git restore [--worktree] <file>
用索引 (*) 中的内容覆盖工作副本中的 <file>。换句话说,它会还原您在工作副本中的更改。您是否指定--worktree
并不重要,因为如果您不另行说明,则是隐含的。
git restore --staged <file>
overwrites <file> in your index with the current HEAD from the local repository. In other words, it unstages previously staged content. In so far, it is indeed equivalent to the old git reset HEAD <file>
.
git restore --staged <file>
使用本地存储库中的当前 HEAD 覆盖索引中的 <file>。换句话说,它取消暂存先前暂存的内容。到目前为止,它确实相当于旧的git reset HEAD <file>
.
To overwrite both, the working copy and the index with the current HEAD, use git restore --staged --worktree --source HEAD <file>
. This version does both: revert your working copy to HEAD and unstage previously staged work.
要使用当前 HEAD 覆盖工作副本和索引,请使用git restore --staged --worktree --source HEAD <file>
. 此版本兼具以下两项功能:将您的工作副本恢复为 HEAD 并取消暂存先前暂存的工作。
For your 2nd question "What's the difference between git-restore and git-reset?":
对于您的第二个问题“git-restore 和 git-reset 之间有什么区别?”:
There are overlaps between these two commands, and differences.
这两个命令之间存在重叠和差异。
Both can be used to modify your working copy and/or the staging area. However, only git-reset can modify your repository. In this sense, git-restore seems the safer option if you only want to revert local work.
两者都可用于修改您的工作副本和/或暂存区。但是,只有 git-reset 可以修改您的存储库。从这个意义上说,如果您只想恢复本地工作,git-restore 似乎是更安全的选择。
There are more differences, which I can't enumerate here.
还有更多不同之处,我无法在此一一列举。
(*) A file not add
ed to the index is still regarded to be in the index, however in it's "clean" state from the current HEAD revision.
(*) 未add
编入索引的文件仍被视为在索引中,但在当前 HEAD 修订版中处于“干净”状态。