问题 什么可能导致git中的数据丢失?


我不想在git中蠢蠢欲动,我想像他们在FaceBook上所说的那样“快速行动并打破局面”。实际上,我认为这几乎是版本控制的重点。我真正需要注意什么?

我猜git rm,尤其是-r可能很危险。

什么时候分支,什么导致覆盖?


8062
2018-01-10 15:58


起源

如果你不确定它们,你想要避免两件事:使用强制标志推进 -f,并使用触发垃圾收集 git gc。其他一切都可以及时完全恢复。 - poke


答案:


通常,很难导致数据丢失  饭桶。即使在运行从历史记录中删除提交或删除分支的命令时,Git也几乎从未真正删除已经检入存储库的任何内容。

您唯一需要担心的是删除尚未签入git的文件的命令。一般来说,git将需要 --force (-f) 要么 --hard 这些命令的标志。

以下是潜在危险命令的快速列表以及使用它们时需要注意的事项:

可以永久删除未提交给git的数据:

  • git rm -f  - 可以删除尚未签入的文件
  • git reset --hard  - 将删除尚未签入git的更改
  • git clean -f  - 将删除git未跟踪的文件
  • git checkout /path/to/file  - 可以将未签入的更改还原为git
  • git checkout <rev> -f  - 可以覆盖未签入git的更改
  • rm -rf .git  - 不要删除你的 .git 目录!这就是存储您所有本地历史的内容。

可以删除远程存储库上的数据(可逆,但您可能没有恢复远程存储库上的提交所需的访问级别):

  • git push -f  - 从远程存储库中的分支中删除历史记录
  • git push <remote> :<branch> -要么- git push <remote> --delete <branch>  - 删除远程分支

可以永久删除原本可以恢复的已删除数据(类似于清空操作系统上的垃圾箱):

  • git prune  - 永久删除无法从任何分支访问的提交
  • git gc  - 永久删除  无法从任何分支访问的提交

可以删除本地提交(它们很容易恢复):

  • git reset <revision>  - 可以从分支中删除历史记录(它可以在本地恢复,但大约两周左右,除非你运行 git prune
  • git branch -D <branch>  - 删除尚未合并的分支(可在本地恢复)
  • git branch -f <branch> <rev>  - 可以从分支中删除历史记录(可在本地恢复)

5
2018-01-10 20:56



通过签入,你的意思是添加? - Bret Fontecchio
@BretFontecchio通过签到,我的意思是承诺。 (例如。 git commit。)虽然添加了文件,但确实如此 git add 通常也可以恢复,只是不像提交的文件那么容易。 - Ajedi32


学习git最重要的事情就是尽早提交并经常提交。如果您在版本控制中记录了您的更改,那么如果您搞砸了,还有一种方法可以恢复它。在过去的一年中,我有很多时刻,我以为我丢失了数据,但是通过Stack Overflow搜索教会了一些巧妙的技巧。保持您的数据托管在远程服务器(如GitHub或BitBucket)上,这样如果您完全销毁您的仓库,它仍然在某个地方。如果你做了 git branch -D <branch> 并删除一个分支,该分支上的所有提交都将从repo中清除。

我唯一可以真正警告你的是,如果你不确切地知道你在做什么,那就永远不会重写历史。可以做到这一点的事情是 git-resetgit-rebase。永远不要做 git push <remote> <branch> -f 除非你知道自己在做什么,否则会强制用本地仓库覆盖所有提交。如果您在本地更改了分支历史记录,或者其他人对回购协议做出了贡献,则可能会导致严重问题。

@meager也提出了一个很好的观点:如果你删除了一个尚未被git跟踪/提交的文件,你将无法恢复它。

作为旁注,不要害怕使用 git-resetgit-rebase,他们只需要正确使用。例如,我有时会使用git-reset将我的工作树重置为最新的提交(撤消所有已更改的文件) git reset --hard HEAD 或者在保留我的工作树的同时撤消上次提交消息 git reset --soft HEAD^。 Git rebase也可以帮助压缩/重写历史记录中的多个提交。请注意,这些方法可能导致数据丢失,如果您已经推送到远程仓库,则不应该执行此操作(从那时起,您将需要执行 git push -f


4
2018-01-10 16:03





git rm 并不是那么危险,因为您之后可以从之前的提交中检索文件。

作为一般的经验法则,照顾好 -f 选项:它迫使Git做一些它不想做的事情。 (例如: branch -f 要么 push -f


3
2018-01-10 16:03





根据您认为Git可能跟踪或未跟踪的内容,Git可能会“丢失”您可能希望保留的各种信息。如果您对Git内部结构没有很好的理解或者它与其他系统的区别,那么分支和标签很容易在随机播放中丢失。

看到 如何使用git丢失数据


3
2018-01-07 16:54



您可以通过添加一个或两个示例来改进答案。 - Magnilex


作为一个方便的提示,如果您认为已删除分支,带注释的标记或重置为先前的提交,您没有丢失它们,您的本地更改都被记录,您可以看到它们 git reflog

看它只是为了看它记录的内容,这很有意思。

它列出了可用于将分支恢复到该状态的提交shas。


0
2018-01-10 16:23





以上都不是。导致数据丢失非常困难 在Git。 Dataloss发生了  Git,当你删除Git尚未跟踪的文件时。发生任何感知的“数据丢失”  如果您在垃圾收集发生之前尝试恢复,那么Git是可恢复的,这是一个窗口

只需很短的步骤,即可经常提交更改。不要担心产生好的提交消息或漂亮 DAG;无论如何,在合并功能分支之前,你会压缩所有这些东西。在你完成工作之前,这项工作将面临失败的危险。


0
2018-01-10 16:05



丢失数据非常困难 如果你知道你在做什么。如果您不了解Git并应用命令而不了解它们的作用,那么您将丢失数据。 - CharlesB
@CharlesB只有你无意中删除了你尚未提交的文件,我清楚地说明了这一点。你真的不能 失去 一旦它被提交,Git中的数据,除非你通过一些非常极端的措施来强制提前收集垃圾,或者等待很长时间才能恢复它。 - meagar♦
@CharlesB阅读你的答案,你对于“丢失”数据的意义有一些非常有趣的想法。暂时放错了提交,不得不进入 害怕 reflog(“Git Wizardy”?这是一个非常常见的用例)不是 丢失 数据。删除分支不会 失去 数据。这些都是任何人都可以通过一点谷歌搜索恢复。 - meagar♦
不容易恢复的数据几乎丢失了,是的。它可以恢复,但我称之为巫术,因为它很不舒服。当然你可以谷歌它,但......有些人不会有这样做的想法。所以在这种情况下它从用户的角度来看是丢失的(这是重要的一个) - CharlesB
真?我认为无法恢复的数据会丢失,而且可以恢复的数据不会丢失。这不是一个“观点”的事情,它不是主观的。数据就在那里。它不会丢失。我们不是在谈论向这里的数据取证人发送硬盘驱动器,我们正在讨论如何使用您的版本控制系统来检查提交。 - meagar♦


存在风险 当你错误地解决冲突时:在eclipse中,当解决文件冲突时,我们遇到了一个问题。 a.txt声称有冲突,而b.txt被拉/拉并显示在索引中。如果用户现在将文件b.txt从索引删回到未分阶段 - 并且只附加他解决的a.txt,并且提交和推送 - 提交将具有来自用户PARENT提交的b.txt状态 - 不再是他本来会得到的版本。问题是,此更改不会显示 - 文件未在提交中列出。您无法直接发现此问题。 (仅当您检查文件的内容时 - 如果是二进制文件,则只能检查BLOB。)需要两个用户,两个存储库+一个裸文件和两个文件。我们在eclipse / egit中发现了这一点 - 不确定它是否也是控制台的问题。你可以检查斑点 git ls-tree <commit>


0
2018-01-17 15:27





正如梅加尔所说 git rm 是一个记录在新提交中的删除,因此它是可恢复的,可以毫无顾虑地使用。

git reset --hard 可能特别有害,因为它重置了“当前提交”(HEAD 在Git行话中)到另一个。因此,如果之前的HEAD未在分支或标签中引用,则它实际上已丢失(至少没有巫术)。它还会导致您未提交的更改丢失。

删除分支和标记也是如此:它可以导致从存储库中清除一行提交。在这些情况下,提交被隐藏在存储库中,您可以恢复它们,但它是技术性的而且不是很容易,因此您最好知道自己在做什么。

与您的数据非常珍贵的任何其他情况(以及源代码)一样,非常希望拥有存储库的镜像,并定期推送它。它可以是另一个本地存储库,一个私有GitHub存储库,或者只是使用当前备份系统备份存储库。这样你就可以随时恢复。

正如其他人在这里所说,请注意那些确实非常重要的未跟踪文件。未跟踪/忽略的文件应该只是从版本控制下的文件生成的文件:可执行文件等。


-1
2018-01-10 16:06



+1备份遥控器。 - Abizern