当前位置:   article > 正文

如何在提交之前撤消“git add”?_git撤销add到未提交状态

git撤销add到未提交状态

问题描述:

想要改进这篇文章?提供这个问题的详细答案,包括引文和解释为什么你的答案是正确的。没有足够细节的答案可能会被编辑或删除。

我错误地使用以下命令将文件添加到 Git:

git add myfile.txt

  • 1
  • 2

我还没有运行 git commit。如何撤消此操作,以使这些更改不会包含在提交中?

解决方案1:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

撤消 git add 用于未提交的更改:

git reset 

  • 1
  • 2

这将从当前索引(“即将提交”列表)中删除文件,而不更改任何其他内容。

取消暂存所有文件的所有更改:

git reset

  • 1
  • 2

在旧版本的 Git 中,上述命令分别相当于 git reset HEAD 和 git reset HEAD,如果 HEAD 未定义(因为您尚未在存储库中进行任何提交)或不明确(因为您创建一个名为 HEAD 的分支,这是你不应该做的愚蠢的事情)。但是,这个 was changed in Git 1.8.2,因此在现代版本的 Git 中,您甚至可以在进行第一次提交之前使用上述命令:

“git reset”(不带选项或参数)用于在您的历史记录中没有任何提交时出错,但现在它为您提供一个空索引(以匹配您甚至不存在的不存在的提交)。

文档:git reset

当然,这不是真正的撤消,因为如果错误的 git add 覆盖了之前暂存的未提交版本,我们将无法恢复它。我试图在下面的回答中澄清这一点。

git reset HEAD *.ext 其中 ext 是您要取消添加的给定扩展名的文件。对我来说是 *.bmp & *.zip

@Jonny,索引(又名暂存区)包含 所有 文件,而不仅仅是更改的文件。它“开始生命”(当您签出提交或克隆存储库时)作为 HEAD 指向的提交中所有文件的副本。因此,如果您从索引 (git rm --cached) 中删除 一个文件,则意味着您正准备提交 删除 该文件。另一方面,git reset HEAD 会将文件从 HEAD 复制到索引,以便下一次提交不会显示对该文件所做的任何更改。

我刚刚发现有一个 git reset -p 就像 git add -p。这太棒了!

实际上,您可以恢复覆盖的先前暂存但未提交的更改,但不是以用户友好的方式,也不是 100% 安全(至少我没有找到):转到 .git/objects,搜索当时创建的文件您想要恢复的 git add 个(61/3AF3... -> 对象 ID 613AF3...),然后是 git cat-file -p (恢复几个小时的工作可能是值得的,但也是更频繁地提交的教训......)

解决方案2:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

你要:

git rm --cached 

  • 1
  • 2

推理:

当我是新手时,我第一次尝试

git reset .

  • 1
  • 2

(撤消我的整个初始添加),只是为了得到这个(不是那么)有用的信息:

fatal: Failed to resolve 'HEAD' as a valid ref.

  • 1
  • 2

事实证明,这是因为 HEAD ref(分支?)直到第一次提交之后才存在。也就是说,如果你的工作流程像我的一样,你会遇到和我一样的初学者问题:

cd 到我伟大的新项目目录来试用 Git,新的热点 git init git add 。 git status …很多废话滚动… =>该死的,我不想添加所有这些。谷歌“撤消 git add”=> 找到堆栈溢出 - 耶 git reset 。 => 致命:无法将“HEAD”解析为有效参考。

进一步证明,在邮件列表中有 a bug logged 反对这样做的无益。

并且正确的解决方案就在 Git 状态输出中(是的,我掩饰为“废话”)

… # 要提交的更改:# (使用 “git rm --cached …” to unstage) …

解决方案确实是使用 git rm --cached FILE。

请注意此处其他地方的警告 - git rm 会删除文件的本地工作副本,但如果您使用 --cached,则不会。这是 git help rm 的结果:

–cached 使用此选项仅从索引中取消暂存和删除路径。工作树文件,无论是否修改,都将被保留。

我继续使用

git rm --cached .

  • 1
  • 2

删除所有内容并重新开始。但是没有用,因为虽然 add . 是递归的,但结果是 rm 需要 -r 才能递归。叹。

git rm -r --cached .

  • 1
  • 2

好的,现在我回到我开始的地方。下次我将使用 -n 进行试运行,看看会添加什么:

git add -n .

  • 1
  • 2

在相信 git help rm 关于 --cached 不会破坏任何东西(如果我拼错了怎么办)之前,我把所有东西都拉到了一个安全的地方。

哈。我遵循了同样的过程。除了我放弃并说 rm -rf .git、git init,因为我不相信 git rm --cached 会保留我的工作副本。它稍微说明了 git 在某些地方仍然过于复杂。 git unstage 应该只是一个标准命令,我不在乎是否可以将其添加为别名。

对我来说 git 说 git reset HEAD ...

git rm --cached 实际上是正确的答案,如果它是 到存储库的初始导入。如果您尝试取消对文件的更改, git reset 是正确的答案。说这个答案是错误的人们正在考虑一个不同的问题。

这实际上会起作用,但仅在第一次提交时,该文件之前不存在,或者 git add 命令添加了新文件,但不是更改为现有文件。

只是为了展示 git 是多么不直观和令人费解。而不是并行的“撤消”命令,您必须找出如何撤消它们。就像试图在快速的沙子中释放你的腿,然后让你的手臂卡住,然后让你的另一只手臂卡住......每个命令都应该通过 GUI 完成,带有选项的下拉菜单项......想想所有的 UI,我们已经获得了生产力的提高,但是我们有一个复古的命令行界面。它不像 git GUI 程序使这更直观。

解决方案3:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

如果您键入:

git status

  • 1
  • 2

Git 会告诉你暂存的内容等,包括如何取消暂存的说明:

use "git reset HEAD ..." to unstage

  • 1
  • 2

我发现 Git 在推动我在这种情况下做正确的事情方面做得很好。

注意:最近的 Git 版本 (1.8.4.x) 已更改此消息:

(use "git rm --cached ..." to unstage)

  • 1
  • 2

消息会有所不同,具体取决于是否已跟踪 added 文件(add 仅将新版本保存到缓存中 - 此处将显示您的消息)。在其他地方,如果文件之前没有暂存,它将显示 use "git rm --cached ..." to unstage

伟大的! git reset HEAD 是唯一可以在您想取消暂存文件删除的情况下使用的

我的 git 版本 2.14.3 说 git reset HEAD 取消暂存。

从 Git v2.23 开始,消息又发生了变化。它现在显示 git restore --staged 。有关更新,请参阅 my answer below。

解决方案4:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

澄清一下:git add 将更改从当前工作目录移动到 暂存区(索引)。

这个过程称为分期。因此,用于暂存更改(更改的文件)的最自然命令是显而易见的命令:

git stage

  • 1
  • 2

git add 只是 git stage 的一个更易于键入的别名

可惜没有 git unstage 或 git unadd 命令。相关的更难猜测或记住,但很明显:

git reset HEAD --

  • 1
  • 2

我们可以很容易地为此创建一个别名:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

  • 1
  • 2
  • 3

最后,我们有了新命令:

git add file1
git stage file2
git unadd file2
git unstage file1

  • 1
  • 2
  • 3
  • 4
  • 5

我个人使用更短的别名:

git a # For staging
git u # For unstaging

  • 1
  • 2
  • 3

“动”?这表明它已从工作目录中消失。事实并非如此。

实际上,git stage 是 git add 的别名,它是 Git 和其他 SCM 上的历史命令。如果我可以说,它已于 2008 年 12 月在“Git 的 git 存储库”中添加,提交 11920d28da。

我同意,Linus Torvalds 没有创建 simmetric 命令,而是为不同的命令创建了一个新词,这很烦人。对于 simmetric,我的意思是:提交 - 取消提交;阶段-非阶段。或者可以用于许多命令的关键字 UNDO:git commit X - git UNDO commit x。很多单词都要背下来,这似乎很自然。那些不经常使用的很容易被遗忘......我们都在这个页面上

解决方案5:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

除了已接受的答案之外,如果您错误添加的文件很大,您可能会注意到,即使在使用“git reset”从索引中删除它之后,它似乎仍会占用 .git 目录中的空间。

这没什么好担心的;该文件确实仍在存储库中,但仅作为“松散对象”。它不会被复制到其他存储库(通过克隆、推送),并且空间最终会被回收——尽管可能不会很快。如果你着急,你可以运行:

git gc --prune=now

  • 1
  • 2

更新(以下是我试图消除最受好评的答案可能引起的一些混淆):

那么,git add 的真正撤消是什么?

git reset HEAD ?

或者

git rm --cached ?

严格来说,如果我没记错的话:没有。

git add 无法撤消 - 通常是安全的。

让我们首先回顾一下 git add 的实际作用:

如果 之前没有被跟踪, git add 将它添加到缓存中,以及它的当前内容。如果 已被跟踪,则 git add 将当前内容(快照、版本)保存到缓存中。在 Git 中,这个动作仍然被称为添加,(不仅仅是更新它),因为一个文件的两个不同版本(快照)被视为两个不同的项目:因此,我们确实是在缓存中添加一个新项目,最终后来承诺。

鉴于此,这个问题有点模棱两可:

我错误地使用命令添加了文件…

OP 的场景似乎是第一个(未跟踪的文件),我们希望“撤消”从跟踪的项目中删除文件(不仅仅是当前内容)。 如果是这种情况,则可以运行 git rm --cached 。

我们还可以运行 git reset HEAD 。这通常更可取,因为它适用于两种情况:当我们错误地添加了已跟踪项目的版本时,它也会撤消。

但是有两个警告。

首先:(如答案中所指出的)只有一种情况 git reset HEAD 不起作用,但 git rm --cached 起作用:一个新的存储库(无提交)。但是,实际上,这实际上是一个无关紧要的案例。

第二:请注意,git reset HEAD 无法神奇地恢复以前缓存的文件内容,它只是从 HEAD 重新同步它。如果我们误入歧途的 git add 覆盖了之前分阶段的未提交版本,我们将无法恢复它。这就是为什么严格来说,我们无法撤消 [*]。

例子:

$ git init
$ echo "version 1" > file.txt
$ git add file.txt   # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add  file.txt   # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff  file.txt
-version 2
+version 3
$ git add  file.txt    # Oops we didn't mean this
$ git reset HEAD file.txt  # Undo?
$ git diff --cached file.txt  # No dif, of course. stage == HEAD
$ git diff file.txt   # We have irrevocably lost "version 2"
-version 1
+version 3

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

当然,如果我们只是遵循通常的懒惰工作流程,只为添加新文件(案例 1)执行“git add”,并且我们通过 commit,git commit -a 命令更新新内容,这并不是很关键。

*(编辑:以上内容实际上是正确的,但仍然有一些稍微有点骇人听闻/令人费解的方法来恢复已暂存但未提交然后被覆盖的更改 - 请参阅 Johannes Matokic 和 iolsmit 的评论)

严格来说,有一种方法可以恢复已被 git add 替换的已暂存文件。正如您提到的 git add 为该文件创建一个 git 对象,该对象不仅在完全删除文件时而且在被新内容覆盖时都将成为松散对象。但是没有命令可以自动恢复它。相反,必须手动识别和提取文件,或者使用仅为这种情况编写的工具(libgit2 将允许这样做)。但这只有在文件非常重要且很大并且无法通过编辑以前的版本来重建时才有效。

纠正自己:一旦找到松散的对象文件(使用元数据,如创建日期/时间),git cat-file 可用于恢复其内容。

恢复已暂存但未提交然后被另一个 git add 覆盖的更改的另一种方法是通过 git fsck --unreachable,它将列出所有无法访问的 obj,然后您可以通过 git show SHA-1_ID 或 { 4} 将 >将悬空对象写入 .git/lost-found/commit/ 或 .git/lost-found/other/,具体取决于类型。另见git fsck --help

解决方案6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

撤消已添加的文件使用 Git 非常容易。要重置已添加的 myfile.txt,请使用:

git reset HEAD myfile.txt

  • 1
  • 2

解释:

暂存不需要的文件后,要撤消,您可以执行 git reset。 Head 是本地文件的头部,最后一个参数是文件名。

我在下图中为您创建了更详细的步骤,包括在这些情况下可能发生的所有步骤:

https://i.stack.imgur.com/9JgGD.jpg

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

这确实使 Alireza 清楚,但如果您使用标记而不是图像会更好。通过明智地使用突出显示、代码块和空白,您可以使其看起来一样清晰,但具有用户可以复制粘贴的优势。

解决方案7:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

git rm --cached . -r

  • 1
  • 2

将以递归方式“取消添加”您从当前目录中添加的所有内容

我不想取消添加所有内容,只是一个特定的文件。

如果您之前没有任何提交,也很有帮助。如果没有先前的提交,git reset HEAD 会说 fatal: Failed to resolve 'HEAD' as a valid ref.

不,这会删除当前目录中的所有内容。与仅取消暂存更改非常不同。

解决方案8:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

Git 对每一个可以想象的动作都有命令,但它需要广泛的知识才能把事情做好,因此它充其量是违反直觉的…

你之前做了什么:

更改了文件并使用了 git add . 或 git add 。

你想要什么:

从索引中删除文件,但保留它的版本并在工作副本中保留未提交的更改: git reset HEAD

将文件从 HEAD 重置为最后一个状态,撤消更改并将它们从索引中删除:# Think svn revert IIRC。 git reset HEAD git checkout # 如果你有一个名为 ,使用: git checkout – 这是必需的,因为 git reset --hard HEAD 不会’ t 处理单个文件。

从索引和版本控制中删除 ,在工作副本中保留未版本控制的文件: git rm --cached

从工作副本和版本控制中完全删除 : git rm

我无法理解 'git reset head ' 和 'git rm --cached 的区别。你能解释一下吗?

@jeswang 文件要么对 git 是“已知的”(正在跟踪它们的变化。),要么它们不是“版本化的”。 reset head 撤消您当前的更改,但 git 仍在监视该文件。 rm --cached 将文件从版本控制中取出,因此 git 不再检查它的更改(并且还删除最终索引的当前更改,由先前的 add 告知 git),但更改的文件将保留在您的工作副本中,那是在硬盘上的文件夹中。

不同之处在于 git reset HEAD 是临时的 - 该命令将仅应用于下一次提交,但 git rm --cached 将取消暂存,直到再次使用 git add 添加它。此外,git rm --cached 意味着如果您将该分支推送到远程,任何拉动该分支的人都会从他们的文件夹中实际删除该文件。

正是我搜索的 git checkout -- thanx !

解决方案9:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

git gui

  • 1
  • 2

并手动删除所有文件,或者选择所有文件并单击 unstage from commit 按钮。

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

是的,我明白这一点。我只想含蓄地建议您在回答中指出“您可以使用 git-gui ....” :)

它说,“git-gui:找不到命令”。我不确定这是否有效。

哇,这比做你不理解的命令行要简单得多。这绝对推荐给像我这样的初学者。谢谢你写这个!

git: 'gui' is not a git command. See 'git --help'.

解决方案10:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

问题没有明确提出。原因是git add有两个含义:

将新文件添加到暂存区域,然后使用 git rm --cached file 撤消。将修改后的文件添加到暂存区域,然后使用 git reset HEAD 文件撤消。

如有疑问,请使用

git reset HEAD file

  • 1
  • 2

因为它在这两种情况下都做了预期的事情。

警告:如果您对已修改的文件(以前存在于存储库中的文件)执行 git rm --cached file,则该文件将在 git commit 被删除!它仍然存在于您的文件系统中,但如果其他人拉动您的提交,该文件将从他们的工作树中删除。

git status 会告诉您文件是新文件还是修改:

On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

+1。此页面上大量高度评价的答案和评论对于 git rm --cached somefile 的行为是完全错误的。我希望这个答案能够在页面上占据显着位置,从而保护新手免受所有虚假声明的误导。

这里最好的答案之一,遗憾的是它在列表中很低

解决方案11:

huntsbot.com – 高效赚钱,自由工作

根据许多其他答案,您可以使用 git reset

但:

我发现这篇很棒的小帖子实际上为 git unadd 添加了 Git 命令(嗯,一个别名):有关详细信息,请参阅 git unadd 或…

简单地,

git config --global alias.unadd "reset HEAD"

  • 1
  • 2

现在你可以

git unadd foo.txt bar.txt

  • 1
  • 2

或者/直接:

git reset HEAD foo.txt bar.txt

  • 1
  • 2

原文链接:https://www.huntsbot.com/qa/ZvDv/how-do-i-undo-git-add-before-commit?lang=zh_CN

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/739982
推荐阅读
相关标签
  

闽ICP备14008679号