为什么有两种方法可以在 Git 中取消暂存文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6919121/
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
Why are there two ways to unstage a file in Git?
提问by Senthess
Sometimes git suggests git rm --cached
to unstage a file, sometimes git reset HEAD file
. When should I use which?
有时 git 建议git rm --cached
取消暂存文件,有时git reset HEAD file
. 我什么时候应该使用哪个?
EDIT:
编辑:
D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
D:\code\gt2>touch b
D:\code\gt2>git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# b
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add b
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
回答by Ryan Stewart
git rm --cached <filePath>
does not unstagea file, it actually stages the removal of the file(s)from the repo (assuming it was already committed before) but leaves the file in your working tree (leaving you with an untracked file).
git rm --cached <filePath>
不会取消暂存文件,它实际上暂存从存储库中删除文件(假设它之前已经提交),但将文件留在您的工作树中(留下未跟踪的文件)。
git reset -- <filePath>
will unstageany staged changes for the given file(s).
git reset -- <filePath>
将取消暂存给定文件的任何暂存更改。
That said, if you used git rm --cached
on a new file that is staged, it would basically look like you had just unstaged it since it had never been committed before.
也就是说,如果您git rm --cached
在暂存的新文件上使用,它基本上看起来就像您刚刚取消暂存,因为它以前从未被提交过。
Update git 2.24
In this newer version of git you can use git restore --staged
instead of git reset
.
See git docs.
更新的Git 2.24
Git中,你可以使用这个新版本git restore --staged
代替git reset
。请参阅git 文档。
回答by manojlds
git rm --cached
is used to remove a file from the index. In the case where the file is already in the repo, git rm --cached
will remove the file from the index, leaving it in the working directory and a commit will now remove it from the repo as well. Basically, after the commit, you would have unversioned the file and kept a local copy.
git rm --cached
用于从索引中删除文件。如果文件已经在 repo 中,git rm --cached
将从索引中删除该文件,将其保留在工作目录中,现在提交也会将其从 repo 中删除。基本上,在提交之后,您将取消版本化文件并保留本地副本。
git reset HEAD file
( which by default is using the --mixed
flag) is different in that in the case where the file is already in the repo, it replaces the index version of the file with the one from repo (HEAD), effectively unstaging the modificationsto it.
git reset HEAD file
(默认情况下使用--mixed
标志)的不同之处在于,在文件已经在 repo 中的情况下,它将文件的索引版本替换为来自 repo (HEAD) 的索引版本,有效地取消对它的修改。
In the case of unversioned file, it is going to unstage the entire file as the file was not there in the HEAD. In this aspect git reset HEAD file
and git rm --cached
are same, but they are not same ( as explained in the case of files already in the repo)
在未版本化文件的情况下,它将取消整个文件的暂存,因为该文件不在 HEAD 中。在这方面git reset HEAD file
并且git rm --cached
是相同的,但它们不相同(如在 repo 中已有文件的情况下所解释的)
To the question of Why are there 2 ways to unstage a file in git?
- there is never really only one way to do anything in git. that is the beauty of it :)
关于Why are there 2 ways to unstage a file in git?
- 从来没有真正只有一种方法可以在 git 中做任何事情。这就是它的美妙之处:)
回答by waldyrious
Quite simply:
很简单:
git rm --cached <file>
makes git stop tracking the file completely(leaving it in the filesystem, unlike plaingit rm
*)git reset HEAD <file>
unstages any modifications made to the file since the last commit(but doesn't revert them in the filesystem, contrary to what the command name might suggest**). The file remains under revision control.
git rm --cached <file>
使 git 完全停止跟踪文件(将其留在文件系统中,与普通git rm
*不同)git reset HEAD <file>
取消自上次提交以来对文件所做的任何修改(但不会在文件系统中恢复它们,这与命令名称可能暗示的相反**)。该文件仍处于修订控制之下。
If the file wasn't in revision control before (i.e. you're unstaging a file that you had just git add
ed for the first time), then the two commands have the same effect, hence the appearance of these being "two ways of doing something".
如果该文件之前未处于修订控制中(即您正在取消git add
第一次编辑的文件),则这两个命令具有相同的效果,因此它们看起来是“做某事的两种方式” ”。
* Keep in mind the caveat @DrewT mentions in his answer, regarding git rm --cached
of a file that was previously committedto the repository. In the context of this question, of a file just added and not committed yet, there's nothing to worry about.
*请记住@DrewT提到了他的答案,对于警告git rm --cached
,这是一个文件的先前提交到仓库。在这个问题的上下文中,对于刚刚添加但尚未提交的文件,没有什么可担心的。
** I was scared for an embarrassingly long time to use the git reset command because of its name -- and still today I often look up the syntax to make sure I don't screw up. (update: I finally took the time to summarize the usage of git reset
in a tldr page, so now I have a better mental model of how it works, and a quick reference for when I forget some detail.)
** 由于它的名字,我很长时间都害怕使用 git reset 命令——直到今天我仍然经常查看语法以确保我没有搞砸。(更新:我终于花时间总结git reset
了 tldr 页面中的用法,所以现在我对它的工作方式有了更好的心理模型,以及当我忘记一些细节时的快速参考。)
回答by Daniel Alder
This thread is a bit old, but I still want to add a little demonstration since it is still not an intuitive problem:
这个线程有点老了,但我仍然想添加一点演示,因为它仍然不是一个直观的问题:
me$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: to-be-added
# modified: to-be-modified
# deleted: to-be-removed
#
me$ git reset -q HEAD to-be-added
# ok
me$ git reset -q HEAD to-be-modified
# ok
me$ git reset -q HEAD to-be-removed
# ok
# or alternatively:
me$ git reset -q HEAD to-be-added to-be-removed to-be-modified
# ok
me$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: to-be-modified
# deleted: to-be-removed
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# to-be-added
no changes added to commit (use "git add" and/or "git commit -a")
git reset HEAD
(without -q
) gives a warning about the modified file and its exit code is 1 which will be considered as an error in a script.
git reset HEAD
(without -q
) 给出有关修改文件的警告,其退出代码为 1,这将被视为脚本中的错误。
Edit: git checkout HEAD to-be-modified to-be-removed
also works for unstaging, but removes the change completely from the workspace
编辑:git checkout HEAD to-be-modified to-be-removed
也适用于取消暂存,但从工作区中完全删除更改
Update git 2.23.0:From time to time, the commands change. Now, git status
says:
更新 git 2.23.0:命令会不时更改。现在,git status
说:
(use "git restore --staged <file>..." to unstage)
... which works for all three types of change
... 适用于所有三种类型的变化
回答by ives
if you've accidentally staged files that you would not like to commit, and want to be certain you keep the changes, you can also use:
如果您不小心暂存了您不想提交的文件,并希望确保保留更改,您还可以使用:
git stash
git stash pop
this performs a reset to HEAD and re-applies your changes, allowing you to re-stage individual files for commit. this is also helpful if you've forgotten to create a feature branch for pull requests (git stash ; git checkout -b <feature> ; git stash pop
).
这会重置 HEAD 并重新应用您的更改,从而允许您重新暂存单个文件以进行提交。如果您忘记为拉取请求 ( git stash ; git checkout -b <feature> ; git stash pop
)创建功能分支,这也很有帮助。
回答by DrewT
These 2 commands have several subtle differences if the file in question is already in the repo and under version control (previously committed etc.):
如果有问题的文件已经在 repo 中并且在版本控制之下(以前提交等),这 2 个命令有几个细微的区别:
git reset HEAD <file>
unstages the file in the current commit.git rm --cached <file>
will unstage the file for future commits also. It's unstaged untill it gets added again withgit add <file>
.
git reset HEAD <file>
在当前提交中取消暂存文件。git rm --cached <file>
也将取消暂存文件以供将来提交。它不会被暂存,直到它被再次添加git add <file>
。
And there's one more important difference:
还有一个更重要的区别:
- After running
git rm --cached <file>
and push your branch to the remote, anyone pulling your branch from the remote will get the file ACTUALLYdeleted from their folder, even though in your local working set the file just becomes untracked (i.e. not physically deleted from the folder).
- 运行后
git rm --cached <file>
,并把你的分支到远程,任何人从远程拉你的分公司将得到的文件ACTUALLY从文件夹中删除,即使与你的工作仅有变得未经跟踪(即未从文件夹中删除)的文件。
This last difference is important for projects which include a config file where each developer on the team has a different config (i.e. different base url, ip or port setting) so if you're using git rm --cached <file>
anyone who pulls your branch will have to manually re-create the config, or you can send them yours and they can re-edit it back to their ip settings (etc.), because the delete only effects people pulling your branch from the remote.
最后一个区别对于包含配置文件的项目很重要,其中团队中的每个开发人员都有不同的配置(即不同的基本 url、ip 或端口设置),因此如果您使用git rm --cached <file>
任何拉取分支的人,则必须手动重新 -创建配置,或者您可以将您的配置发送给他们,他们可以将其重新编辑回他们的 ip 设置(等),因为删除只会影响人们从远程拉出您的分支。
回答by jiminikiz
Let's say you stage
a whole directory via git add <folder>
, but you want to exclude a file from the staged list (i.e. the list that generates when running git status
) and keepthe modifications within the excluded file (you were working on something and it's not ready for commit, but you don't want to lose your work...). You could simply use:
假设您stage
通过 整个目录git add <folder>
,但您想从暂存列表(即运行时生成的列表git status
)中排除一个文件,并将修改保留在排除的文件中(您正在处理某些事情,但尚未准备好提交,但是你不想失去你的工作......)。你可以简单地使用:
git reset <file>
git reset <file>
When you run git status
, you will see that whatever file(s) you reset
are unstaged
and the rest of the files you added
are still in the staged
list.
当您运行git status
,你会看到,无论文件()你reset
是unstaged
,你的文件的剩余部分added
仍然在staged
列表中。
回答by Timothy L.J. Stewart
1.
1.
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
(use "git rm --cached ..." to unstage)
(使用“git rm --cached ...”取消暂存)
git is a system of pointers
you do not have a commit yet to change your pointer to
the only way to 'take files out of the bucket being pointed to' is to remove files you told git to watch for changes
git 是一个指针系统
您还没有提交将指针更改为
“从指向的存储桶中取出文件”的唯一方法是删除您告诉 git 监视更改的文件
2.
2.
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a
git commit -m a
git commit -ma
- you commited, 'saved'
- 你承诺,“保存”
3.
3.
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
(use "git reset HEAD ..." to unstage)
(使用“git reset HEAD ...”取消暂存)
- you made a commit in your code at this time
- now you can reset your pointer to your commit 'revert back to last save'
- 您此时在代码中进行了提交
- 现在您可以将指针重置为您的提交“恢复到上次保存”
回答by Edgar Quintero
Just use:
只需使用:
git reset HEAD <filename>
git reset HEAD <filename>
This unstages the file and keeps the changes you did to it, so you can, in turn, change branches if you wanted and git add
those files to another branch instead. All changes are kept.
这将取消暂存文件并保留您对它所做的更改,因此您可以反过来,根据需要更改分支,并将git add
这些文件改为另一个分支。保留所有更改。
回答by Alex
I'm surprised noone mentioned the git reflog (http://git-scm.com/docs/git-reflog):
我很惊讶没有人提到 git reflog ( http://git-scm.com/docs/git-reflog):
# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}
The reflog is a git history that not only tracks the changes to the repo, but also tracks the user actions (Eg. pull, checkout to different branch, etc) and allows to undo those actions. So instead of unstaging the file that was mistakingly staged, where you can revert to the point where you didn't stage the files.
reflog 是一个 git 历史记录,它不仅跟踪对 repo 的更改,还跟踪用户操作(例如拉取、结帐到不同分支等)并允许撤消这些操作。因此,您无需取消暂存错误暂存的文件,而是可以恢复到未暂存文件的位置。
This is similar to git reset HEAD <file>
but in certain cases may be more granular.
这类似于git reset HEAD <file>
但在某些情况下可能更精细。
Sorry - not really answering your question, but just pointing yet another way to unstage files that I use quite often (I for one like answers by Ryan Stewart and waldyrious very much.) ;) I hope it helps.
抱歉 - 没有真正回答你的问题,只是指出了我经常使用的另一种取消暂存文件的方法(我非常喜欢 Ryan Stewart 和 waldyrious 的答案。);)我希望它有所帮助。