为什么有两种方法来卸载git中的文件?

有时候,gitbuild议git rm --cached到一个文件,有时候git reset HEAD file 。 我应该什么时候使用哪个?

编辑:

 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 -ma [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 # 

git rm --cached <filePath> 不会 取消一个文件,它实际上是从回购文件中删除文件 (假设它已经在之前已经提交),但是把文件留在工作树中(留下未跟踪的文件文件)。

git reset <filePath>取消给定文件的任何阶段性变化。

也就是说,如果你在一个新的文件上使用了git rm --cached ,它基本上看起来就像你刚才没有执行过的那样,因为它从来没有被提交过。

git rm --cached用于从索引中删除文件。 在这个文件已经在repo中的情况下, git rm --cached将会把这个文件从索引中删除,留在工作目录中,一个提交现在也将它从repo中删除。 基本上,在提交之后,您将会unversioned该文件并保留本地副本。

git reset HEAD file (默认情况下使用--mixed标志)与文件已经在repo中的情况不同,它将文件的索引版本replace为来自repo(HEAD)的文件取消对其的修改

在未版本化的文件的情况下,由于文件不在HEAD中,因此将整个文件取消。 在这个方面, git reset HEAD filegit rm --cached是一样的,但是它们不一样(就像已经在repo中的文件所解释的那样)

Why are there 2 ways to unstage a file in git?取消文件的问题Why are there 2 ways to unstage a file in git? – 从来没有真正只有一种方法来做任何事情在混帐。 那是它的美丽:)

很简单:

  • git rm --cached <file> 使git完全停止跟踪文件 (把它留在文件系统中,而不像普通的git rm *)
  • git reset HEAD <file> 取消自上次提交以来对 git reset HEAD <file> 所做的任何修改 (但不会在文件系统中恢复它们,与命令名称可能会提示**相反)。 该文件保持在修订控制下。

如果这个文件之前没有在版本控制之中(也就是说,你正在初始化一个你刚刚git addgit add的文件),那么这两个命令的效果是一样的,因此这两个方法的出现是“做某事“。

*请记住@DrewT在他的回答中提到的警告,关于git rm --cached以前提交到存储库的文件。 在这个问题的背景下,刚添加的文件还没有提交,没有什么可担心的。

**由于名字的缘故,我很害怕使用git reset命令,而且今天仍然经常查找语法来确保我不会搞砸。 更新 :我终于花时间在tldr页面中总结了git reset的用法 ,所以现在我有了一个更好的工作原理模型,以及当我忘记一些细节时的快速参考。)

这个线程有点旧了,但是我仍然想添加一些示范,因为它还不是一个直观的问题:

 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 rm --cached to-be-added rm 'to-be-added' # ok me$ git reset -q HEAD to-be-modified # ok me$ git reset -q HEAD to-be-removed # 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 (不带-q )给出了修改文件的警告,其退出代码是1,这将被视为脚本中的错误。

编辑: git checkout HEAD to-be-modified to-be-removed也适用于暂停,但完全从工作区删除更改

如果您不小心上传了不想提交的文件,并且想要确保保留更改,则还可以使用:

 git stash git stash pop 

这将执行重置为HEAD并重新应用您的更改,允许您重新提交单个文件进行提交。 如果忘记为pull请求创build一个function分支( git stash ; git checkout -b <feature> ; git stash pop ),这也是有帮助的。

这两个命令有几个细微的差别,如果有问题的文件已经在回购和版本控制(以前提交等):

  • git reset HEAD <file>取消当前提交中的文件。
  • git rm --cached <file>将会使文件在未来的提交中被取消。 直到它被添加到git add <file>

还有一个更重要的区别:

  • 运行git rm --cached <file>并将你的分支推送到远程,任何从远端拉你的分支的人都会从文件夹中把ACTUALLY文件从文件夹中删除,即使在你的本地工作集中,文件只是不被跟踪从文件夹中物理删除)。

这个最后的区别对于那些包含一个configuration文件的项目很重要,在这个configuration文件中,团队中的每个开发人员都有不同的configuration(即不同的基本URL,ip或者端口设置),所以如果你使用git rm --cached <file>您的分支将不得不手动重新创buildconfiguration,或者您可以将它们发送给您,并且可以将其重新编辑回它们的ip设置(等等),因为删除只会影响从远程拖动分支的人员。

假设你通过git add <folder>来完成一个完整的目录,但是你希望从staged列表(即运行git status时生成的列表)中排除一个文件,并在排除的文件中保留这些修改(你正在做一些事情而且还没有准备好提交,但是你不想失去你的工作…)。 你可以简单地使用:

git reset <file>

当你运行git status ,你会看到你reset任何文件都是不unstaged的,而你added的其他文件仍然在staged unstaged列表中。

没有人提到git reflog( http://git-scm.com/docs/git-reflog ):

 # git reflog <find the place before your staged anything> # git reset HEAD@{1} 

reflog是一个git历史logging,不仅跟踪repo的更改,而且还跟踪用户的操作(例如,pull,checkout到不同的分支等),并允许撤销这些操作。 因此,不要取消上传错误的文件,在这里可以恢复到没有执行文件的地步。

这与git reset HEAD <file>类似,但在某些情况下可能会更细化。

对不起 – 没有真正回答你的问题,而只是指向另一种方式来取消我经常使用的文件(我喜欢Ryan Stewart的回答,也非常喜欢Waldyrious);)我希望它有帮助。

在我看来, git rm --cached <file>会从索引中删除文件,而不会将其从一个普通的git rm <file>可以同时执行的目录中移除,就像OS rm <file>将删除文件一样从目录中删除其版本。

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 

(使用“git rm –cached …”来取消)

  • git是一个指针系统

  • 你没有一个提交还没有改变你的指针

  • “将文件从被指向的桶中取出”的唯一方法是删除您告诉git的文件以监视更改

2。

 D:\code\gt2>git commit -ma [master (root-commit) c271e05] a 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a 

git commit -ma

  • 你承诺,' 保存 '

3。

 D:\code\gt2>git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: b # 

(使用“git reset HEAD …”来取消)

  • 你现在在你的代码中做了一个提交
  • 现在你可以重置你的指针,提交' 恢复到上次保存 '

为了解开整个目录,recursion地使用rm(-r)

 git rm -r --cached folderpath