git 如何在不删除内容的情况下取消暂存大量文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7103631/
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
How to unstage large number of files without deleting the content
提问by sarat
I accidentally added a lot of temporary files using git add -A
我不小心添加了很多临时文件使用 git add -A
I managed to unstage the files using the following commands and managed to remove the dirty index.
我设法使用以下命令取消暂存文件并设法删除脏索引。
git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
The above commands are listed in the git help rm
. But sadly, my files were also deleted on execution, even though I had given cache option. How can I clear the index without losing the content?
上述命令列在git help rm
. 但遗憾的是,即使我提供了缓存选项,我的文件也在执行时被删除。如何在不丢失内容的情况下清除索引?
Also it would be helpful if someone can explain the way this pipe operation works.
如果有人可以解释此管道操作的工作方式,这也会很有帮助。
回答by Ian Maddox
git reset
git reset
If all you want is to undo an overzealous "git add" run:
如果您只想撤消过度热心的“git add”运行:
git reset
Your changes will be unstaged and ready for you to re-add as you please.
您的更改将取消暂存并准备好让您根据需要重新添加。
DO NOT RUN git reset --hard
.
不要跑git reset --hard
。
It will not only unstage your added files, but will revert any changes you made in your working directory. If you created any new files in working directory, it will notdelete them though.
它不仅会取消暂存您添加的文件,还会还原您在工作目录中所做的任何更改。如果您在工作目录中创建了任何新文件,它不会删除它们。
回答by sehe
If you have a pristine repo (or HEAD isn't set)[1]you could simply
如果你有一个原始的回购(或 HEAD 没有设置)[1]你可以简单地
rm .git/index
Of course, this will require you to re-add the files that you didwant to be added.
当然,这需要你重新添加文件,您也想加入。
[1]Note (as explained in the comments) this would usually only happen when the repo is brand-new ("pristine") or if no commits have been made. More technically, whenever there is no checkout or work-tree.
[1]注意(如评论中所述)这通常只会在回购是全新的(“原始”)或没有提交时才会发生。从技术上讲,只要没有结帐或工作树。
Just making it more clear :)
只是让它更清楚:)
回答by Amber
Use git reset HEAD
to reset the index without removing files. (If you only want to reset a particular file in the index, you can use git reset HEAD -- /path/to/file
to do so.)
用于git reset HEAD
在不删除文件的情况下重置索引。(如果您只想重置索引中的特定文件,您可以使用git reset HEAD -- /path/to/file
它。)
The pipe operator, in a shell, takes the stdout
of the process on the left and passes it as stdin
to the process on the right. It's essentiallythe equivalent of:
在 shell 中,管道操作符stdout
将左边的进程的 传递stdin
给右边的进程。它本质上相当于:
$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out
but instead it's $ proc1 | proc2
, the second process can start getting data before the first is done outputting it, and there's no actual file involved.
但相反$ proc1 | proc2
,第二个进程可以在第一个完成输出之前开始获取数据,并且不涉及实际文件。
回答by Bijan
git stash && git stash pop
回答by jjlin
If HEAD isn't set (i.e., you have no commits yet, but you don't want to just blow away .git
because you've already set up other repo config you want to keep), you can also do
如果 HEAD 没有设置(即,你还没有提交,但你不想只是吹走,.git
因为你已经设置了你想保留的其他 repo 配置),你也可以这样做
git rm -rf --cached .
to unstage everything. This is effectively the same as sehe's solution, but avoids mucking with Git internals.
取消一切。这实际上与 sehe 的解决方案相同,但避免了 Git 内部的混乱。
回答by SQB
Warning: do not use the following command unless you want to lose uncommitted work!
警告:除非您想丢失未提交的工作,否则不要使用以下命令!
Using git reset
has been explained, but you asked for an explanation of the piped commands as well, so here goes:
使用git reset
已经解释过,但你也要求解释管道命令,所以这里是:
git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
The command git ls-files
lists all files git knows about. The option -z
imposes a specific format on them, the format expected by xargs -0
, which then invokes rm -f
on them, which means to remove them without checking for your approval.
该命令git ls-files
列出了 git 知道的所有文件。该选项-z
对它们强加了特定格式,即 预期的格式xargs -0
,然后调用rm -f
它们,这意味着删除它们而无需检查您的批准。
In other words, "list all files git knows about and remove your local copy".
换句话说,“列出 git 知道的所有文件并删除您的本地副本”。
Then we get to git diff
, which shows changes between different versions of items git knows about. Those can be changes between different trees, differences between local copies and remote copies, and so on.
As used here, it shows the unstaged changes; the files you have changed but haven't committed yet. The option --name-only
means you want the (full) file names only and --diff-filter=D
means you're interested in deleted files only. (Hey, didn't we just delete a bunch of stuff?)This then gets piped into the xargs -0
we saw before, which invokes git rm --cached
on them, meaning that they get removed from the cache, while the working tree should be left alone — except that you've just removed all files from your working tree. Now they're removed from your index as well.
然后我们到达git diff
,它显示了 git 知道的不同版本的项目之间的变化。这些可能是不同树之间的更改、本地副本和远程副本之间的差异等等。
在这里使用时,它显示了未分阶段的更改;您已更改但尚未提交的文件。该选项--name-only
意味着您只需要(完整)文件名,并且--diff-filter=D
意味着您只对已删除的文件感兴趣。(嘿,我们不是刚刚删除了一堆东西吗?)然后这会通过管道传输到xargs -0
我们之前看到的,它会调用git rm --cached
它们,这意味着它们会从缓存中删除,而工作树应该单独留下——除了您刚刚从工作树中删除了所有文件。现在它们也从您的索引中删除了。
In other words, all changes, staged or unstaged, are gone, and your working tree is empty. Have a cry, checkout your files fresh from origin or remote, and redo your work. Curse the sadist who wrote these infernal lines; I have no clue whatsoever why anybody would want to do this.
换句话说,所有已暂存或未暂存的更改都消失了,并且您的工作树是空的。大哭一场,从原始或远程签出您的文件,然后重做您的工作。诅咒写下这些地狱台词的虐待狂;我不知道为什么有人想要这样做。
TL;DR: you just hosed everything; start over and use git reset
from now on.
TL;DR:你刚刚处理了所有事情;git reset
从现在开始重新开始使用。
回答by Mark Longair
I'm afraid that the first of those command lines unconditionally deleted from the working copy all the files that are in git's staging area. The second one unstaged all the files that were tracked but have now been deleted. Unfortunately this means that you will have lost any uncommitted modifications to those files.
恐怕这些命令行中的第一个无条件地从工作副本中删除了 git 暂存区中的所有文件。第二个取消暂存所有已跟踪但现已删除的文件。不幸的是,这意味着您将丢失对这些文件的任何未提交的修改。
If you want to get your working copy and index back to how they were at the last commit, you can (carefully) use the following command:
如果您想让您的工作副本和索引恢复到上次提交时的状态,您可以(小心地)使用以下命令:
git reset --hard
I say "carefully" since git reset --hard
will obliterate uncommitted changes in your working copyand index. However, in this situation it sounds as if you just want to go back to the state at your last commit, and the uncommitted changes have been lost anyway.
我说“小心”,因为这git reset --hard
会清除您的工作副本和索引中未提交的更改。但是,在这种情况下,听起来好像您只想回到上次提交时的状态,而未提交的更改无论如何都已丢失。
Update: it sounds from your comments on Amber's answer that you haven't yet created any commits (since HEAD cannot be resolved), so this won't help, I'm afraid.
更新:从您对 Amber 的回答的评论中可以看出,您还没有创建任何提交(因为 HEAD 无法解析),所以恐怕这无济于事。
As for how those pipes work: git ls-files -z
and git diff --name-only --diff-filter=D -z
both output a list of file names separated with the byte 0
. (This is useful, since, unlike newlines, 0
bytes are guaranteed not to occur in filenames on Unix-like systems.) The program xargs
essentially builds command lines from its standard input, by default by taking lines from standard input and adding them to the end of the command line. The -0
option says to expect standard input to by separated by 0
bytes. xargs
may invoke the command several times to use up all the parameters from standard input, making sure that the command line never becomes too long.
至于如何将这些管道的工作:git ls-files -z
和git diff --name-only --diff-filter=D -z
两个输出文件名列表分开与字节0
。(这很有用,因为与换行符不同,0
字节保证不会出现在类 Unix 系统的文件名中。)该程序xargs
基本上从其标准输入构建命令行,默认情况下,通过从标准输入中获取行并将它们添加到末尾的命令行。该-0
选项表示期望以0
字节分隔的标准输入。 xargs
可能会多次调用该命令以使用来自标准输入的所有参数,确保命令行永远不会变得太长。
As a simple example, if you have a file called test.txt
, with the following contents:
作为一个简单的例子,如果您有一个名为 的文件test.txt
,其内容如下:
hello
goodbye
hello again
... then the command xargs echo whatever < test.txt
will invoke the command:
...然后该命令xargs echo whatever < test.txt
将调用该命令:
echo whatever hello goodbye hello again
回答by 027
If you want to unstage all the changes use below command,
如果要取消暂存所有更改,请使用以下命令,
git reset --soft HEAD
In the case you want to unstage changes and revert them from the working directory,
如果您想取消暂存更改并从工作目录中恢复它们,
git reset --hard HEAD