假设你在的公司要上线一个新功能,大家开发团队为实现这个新功能,写了大约5000行代码,上线没2天,就发现这个功能用户并不喜欢,你老板让你去掉这个功能。html
急须要一个工具,帮你记录每次对代码作了哪些修改,而且能够轻易的把代码回滚到历史上的某个状态。 这个神奇的工具就叫作版本控制。 版本控制工具主要实现如下两个功能:node
在开发中,这是刚需,必须容许能够很容易对产品的版本进行任意回滚,版本控制工具实现这个功能的原理简单来说,就是你每修改一次代码,它就帮你作一次快照。linux
一个复杂点的软件,每每不是一个开发人员能够搞定的,公司为加快产品开发速度,会招聘一堆跟你同样的开发人员开发这个产品。开发人员间来回copy代码,很快就乱了, 因此此时亟需一个工具,能确保一直存储最新的代码库,全部人的代码应该和最新的代码库保持一致。git
此工具是Microsoft提供的,是使用的至关广泛的工具之一,他能够与VS.net进行无缝集成,成为了独立开发人员和小型开发团队所适合的工具,基本上Window平台上开发的中小型企业,当规模较大后,其性能一般是没法忍受的,对分支与并行开发支持的比较有限。github
此工具是一个开源工具,与后面提到的SVN是同一个厂家:Collab.Net提供的。web
CVS是源于unix的版本控制工具,对于CVS的安装和使用最好对unix的系统有所了解能更容易学习,CVS的服务器管理须要进行各类命令行操做。目前,CVS的客户端有winCVS的图形化界面,服务器端也有CVSNT的版本,易用性正在提升。shell
此工具是至关著名,使用得至关普遍的版本控制工具之一,使用成熟的“Copy-Modify-Merge"开发模型,能够大大的提升开发效率,适合于项目比较大,产品发布频繁,分支活动频繁的中大型项目。django
此工具是在CVS 的基础上,由CollabNet提供开发的,也是开源工具,应用比较普遍。编程
他修正cvs的一些局限性,适用范围同cvs,目前有一些基于SVN的第三方工具,如TortoiseSVN,是其客户端程序,使用的也至关普遍。在权限管理,分支合并等方面作的很出色,他能够与Apache集成在一块儿进行用户认证。vim
不过在权限管理方面目前尚未个很好用的界面化工具,SVNManger对于已经使用SVN进行配置的项目来讲,基本上是没法应用的,但对于从头开始的项目是能够的,功能比较强大,可是搭建svnManger比较麻烦。
是一个跨平台的软件,支持大多数常见的操做系统。做为一个开源的版本控制系统,Subversion 管理着随时间改变的数据。 这些数据放置在一个中央资料档案库中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变更。 这样你就能够把档案恢复到旧的版本, 或是浏览文件的变更历史。Subversion 是一个通用的系统, 可用来管理任何类型的文件, 其中包括了程序源码。
由于最初是从Linux起家的,很是依赖文件系统的一些特性,这些在 Linux 下表现的很好,而 Windows 下特别糟糕Git。
Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到很是大的项目版本管理。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Torvalds 开始着手开发 Git 是为了做为一种过渡方案来替代 BitKeeper,后者以前一直是 Linux 内核开发人员在全球使用的主要源代码工具。开放源码社区中的有些人以为 BitKeeper 的许可证并不适合开放源码社区的工做,所以 Torvalds 决定着手研究许可证更为灵活的版本控制系统。尽管最初 Git 的开发是为了辅助 Linux 内核开发的过程,可是咱们已经发如今不少其余自由软件项目中也使用了 Git。例如 最近就迁移到 Git 上来了,不少 Freedesktop 的项目也迁移到了 Git 上。
是由BitMover公司提供的,BitKeeper自称是“分布式”可扩缩SCM系统。
不是采用C/S结构,而是采用P2P结构来实现的,一样支持变动任务,全部变动集的操做都是原子的,与svn、cvs一致。
Git是一个免费、开源的版本控制软件。
Github是全球最大的社交编程及代码托管网站(https://github.com/);Github能够托管各类git库,并提供一个web界面(用户名.github.io/仓库名)
二者关系:Git是版本控制软件;Github是项目代码托管的平台,借助git来管理项目代码。
在你开始使用 Git 前,须要将它安装在你的计算机上。 即使已经安装,最好将它升级到最新的版本。 你能够经过软件包或者其它安装程序来安装,或者下载源码编译安装。
若是你想在 Linux 上用二进制安装程序来安装 Git,可使用发行版包含的基础软件包管理工具来安装。 若是以 Fedora 上为例,你可使用 yum:
$ sudo yum install git
若是你在基于 Debian 的发行版上,请尝试用 apt-get:
$ sudo apt-get install git
要了解更多选择,Git 官方网站上有在各类 Unix 风格的系统上安装步骤,网址为 http://git-scm.com/download/linux。
在 Mac 上安装 Git 有多种方式。 最简单的方法是安装 Xcode Command Line Tools。 Mavericks (10.9) 或更高版本的系统中,在 Terminal 里尝试首次运行 git 命令便可。 若是没有安装过命令行开发者工具,将会提示你安装。
若是你想安装更新的版本,可使用二进制安装程序。 官方维护的 OSX Git 安装程序能够在 Git 官方网站下载,网址为 http://git-scm.com/download/mac。
你也能够将它做为 GitHub for Mac 的一部分来安装。 它们的图形化 Git 工具备一个安装命令行工具的选项。 你能够从 GitHub for Mac 网站下载该工具,网址为 http://mac.github.com。
在 Windows 上安装 Git 也有几种安装方法。 官方版本能够在 Git 官方网站下载。 打开 http://git-scm.com/download/win,下载会自动开始。 要注意这是一个名为 Git for Windows的项目(也叫作 msysGit),和 Git 是分别独立的项目;更多信息请访问 http://msysgit.github.io/。
另外一个简单的方法是安装 GitHub for Windows。 该安装程序包含图形化和命令行版本的 Git。 它也能支持 Powershell,提供了稳定的凭证缓存和健全的 CRLF 设置。 稍后咱们会对这方面有更多了解,如今只要一句话就够了,这些都是你所须要的。 你能够在 GitHub for Windows 网站下载,网址为 http://windows.github.com。
若是你想从源码安装 Git,须要安装 Git 依赖的库:curl、zlib、openssl、expat,还有libiconv。 若是你的系统上有 yum (如 Fedora)或者 apt-get(如基于 Debian 的系统),可使用如下命令之一来安装最小化的依赖包来编译和安装 Git 的二进制版:
$ sudo yum install curl-devel expat-devel gettext-devel \ openssl-devel zlib-devel $ sudo apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \ libz-dev libssl-dev
为了可以添加更多格式的文档(如 doc, html, info),你须要安装如下的依赖包:
$ sudo yum install asciidoc xmlto docbook2x $ sudo apt-get install asciidoc xmlto docbook2x
当你安装好全部的必要依赖,你能够继续从几个地方来取得最新发布版本的 tar 包。 你能够从 Kernel.org 网站获取,网址为 https://www.kernel.org/pub/software/scm/git,或从 GitHub 网站上的镜像来得到,网址为 https://github.com/git/git/releases。 一般在 GitHub 上的是最新版本,但 kernel.org 上包含有文件下载签名,若是你想验证下载正确性的话会用到。
接着,编译并安装:
$ tar -zxf git-2.0.0.tar.gz $ cd git-2.0.0 $ make configure $ ./configure --prefix=/usr $ make all doc info $ sudo make install install-doc install-html install-info
完成后,你可使用 Git 来获取 Git 的升级:
$ git clone git://git.kernel.org/pub/scm/git/git.git
每台计算机上只须要配置一次,程序升级时会保留配置信息。 你能够在任什么时候候再次经过运行命令来修改它们。
Git 自带一个 git config
的工具来帮助设置控制 Git 外观和行为的配置变量。
1)/etc/gitconfig
文件: 包含系统上每个用户及他们仓库的通用配置。 若是使用带有 --system
选项的 git config
时,它会今后文件读写配置变量。
2)~/.gitconfig
或 ~/.config/git/config
文件:只针对当前用户。 能够传递 --global
选项让 Git 读写此文件。
3)当前使用仓库的 Git 目录中的 config
文件(就是 .git/config
):针对该仓库。
注意:
每个级别覆盖上一级别的配置,因此 .git/config
的配置变量会覆盖 /etc/gitconfig
中的配置变量。
在 Windows 系统中,Git 会查找 $HOME
目录下(通常状况下是 C:\Users\$USER
)的 .gitconfig
文件。 Git 一样也会寻找 /etc/gitconfig
文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。
当安装完 Git 应该作的第一件事就是设置你的用户名称与邮件地址。 这样作很重要,由于每个 Git 的提交都会使用这些信息,而且它会写入到你的每一次提交中,不可更改:
$ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com
再次强调,若是使用了 --global
选项,那么该命令只须要运行一次,由于以后不管你在该系统上作任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不一样的用户名称与邮件地址时,能够在那个项目目录下运行没有 --global
选项的命令来配置。
不少 GUI 工具都会在第一次运行时帮助你配置这些信息。
用户信息设置完毕后,你能够配置默认文本编辑器了,当 Git 须要你输入信息时会调用它。 若是未配置,Git 会使用操做系统默认的文本编辑器,一般是 Vim。 若是你想使用不一样的文本编辑器,例如 Emacs,能够这样作:
$ git config --global core.editor emacs
注意:Vim 和 Emacs 是像 Linux 与 Mac 等基于 Unix 的系统上开发者常用的流行的文本编辑器。 若是你对这些编辑器都不是很了解或者你使用的是 Windows 系统,那么可能须要搜索如何在 Git 中配置你最经常使用的编辑器。 若是你不设置编辑器而且不知道 Vim 或 Emacs 是什么,当它们运行起来后你可能会被弄糊涂、不知所措。
若是想要检查你的配置,可使用 git config --list
命令来列出全部 Git 当时能找到的配置。
$ git config --list user.name=John Doe user.email=johndoe@example.com color.status=auto color.branch=auto color.interactive=auto color.diff=auto ...
你可能会看到重复的变量名,由于 Git 会从不一样的文件中读取同一个配置(例如:/etc/gitconfig
与 ~/.gitconfig
)。 这种状况下,Git 会使用它找到的每个变量的最后一个配置。
你能够经过输入 git config <key>
: 来检查 Git 的某一项配置
$ git config user.name Doe Huang
若你使用 Git 时须要获取帮助,有三种方法能够找到 Git 命令的使用手册:
$ git help <verb> $ git <verb> --help $ man git-<verb>
例如,要想得到 config 命令的手册,执行
$ git help config
这些命令很棒,由于你随时随地可使用而无需联网。 若是你以为手册或者本书的内容还不够用,你能够尝试在 Freenode IRC 服务器( irc.freenode.net )的 #git
或 #github
频道寻求帮助。 这些频道常常有上百人在线,他们都精通 Git 而且乐于助人。
有两种取得 Git 项目仓库的方法。 第一种是在现有项目或目录下导入全部文件到 Git 中; 第二种是从一个服务器克隆一个现有的 Git 仓库。
若是你打算使用 Git 来对现有的项目进行管理,你只须要进入该项目目录并输入:
$ git init
若是是windows系统能够在建立的项目的文件夹里面右键点击 Gir Bash Here 把git运行起来。
该命令将建立一个名为 .git
的子目录,这个子目录含有你初始化的 Git 仓库中全部的必须文件,这些文件是 Git 仓库的骨干。 可是,在这个时候,咱们仅仅是作了一个初始化的操做,你的项目里的文件尚未被跟踪。 (参见 Git 内部原理 来了解更多关于到底 .git
文件夹中包含了哪些文件的信息。)
若是你是在一个已经存在文件的文件夹(而不是空文件夹)中初始化 Git 仓库来进行版本控制的话,你应该开始跟踪这些文件并提交。 你可经过 git add
命令来实现对指定文件的跟踪,而后执行 git commit
提交:
若是你想得到一份已经存在了的 Git 仓库的拷贝,好比说,你想为某个开源项目贡献本身的一份力,这时就要用到 git clone
命令。
Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎全部数据,而不是仅仅复制完成你的工做所须要文件。 当你执行 git clone
命令的时候,默认配置下远程 Git 仓库中的每个文件的每个版本都将被拉取下来。 事实上,若是你的服务器的磁盘坏掉了,你一般可使用任何一个克隆下来的用户端来重建服务器上的仓库(虽然可能会丢失某些服务器端的挂钩设置,可是全部版本的数据仍在,详见 在服务器上搭建 Git )。
克隆仓库的命令格式是 git clone [url]
。 好比,要克隆 Git 的可连接库 libgit2,能够用下面的命令:
$ git clone https://github.com/libgit2/libgit2
这会在当前目录下建立一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git
文件夹,从远程仓库拉取下全部数据放入 .git
文件夹,而后从中读取最新版本的文件的拷贝。 若是你进入到这个新建的 libgit2
文件夹,你会发现全部的项目文件已经在里面了。
若是你想在克隆远程仓库的时候,自定义本地仓库的名字,你可使用以下命令:
$ git clone https://github.com/libgit2/libgit2 mylibgit
Git 支持多种数据传输协议。 上面的例子使用的是 https://
协议,不过你也可使用 git://
协议或者使用 SSH 传输协议,好比 user@server:path/to/repo.git
。 在服务器上搭建 Git 将会介绍全部这些协议在服务器端如何配置使用,以及各类方式之间的利弊。
手上有了一个真实项目的 Git 仓库,并从这个仓库中取出了全部文件的工做拷贝。 接下来,对这些文件作些修改,在完成了一个阶段的目标以后,提交本次更新到仓库。
工做目录下的每个文件都不外乎这两种状态:已跟踪或未跟踪。 已跟踪的文件是指那些被归入了版本控制的文件,在上一次快照中有它们的记录,在工做一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。 工做目录中除已跟踪文件之外的全部其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库的时候,工做目录中的全部文件都属于已跟踪文件,并处于未修改状态。
编辑过某些文件以后,因为自上次提交后你对它们作了修改,Git 将它们标记为已修改文件。 咱们逐步将这些修改过的文件放入暂存区,而后提交全部暂存了的修改,如此反复。因此使用 Git 时文件的生命周期以下:
要查看哪些文件处于什么状态,能够用 git status
命令。 若是在克隆仓库后当即使用此命令,会看到相似这样的输出:
$ git init Initialized empty Git repository in /Users/.../s9alipay/.git/ $ git status On branch master nothing to commit, working directory clean
这说明你如今的工做目录至关干净。换句话说,全部已跟踪文件在上次提交后都未被更改过。 此外,上面的信息还代表,当前目录下没有出现任何处于未跟踪状态的新文件,不然 Git 会在这里列出来。 最后,该命令还显示了当前所在分支,并告诉你这个分支同远程服务器上对应的分支没有偏离。 如今,分支名是 “master”,这是默认的分支名。 在 Git 分支 有详细讨论分支和引用。
若是在项目下建立一个新的 README 文件。 若是以前并不存在这个文件,使用 git status
命令,将看到一个新的未跟踪文件:
$ git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed) .idea/workspace.xml README.MD alipay/__pycache__/ app01/__pycache__/ app01/migrations/__pycache__/ utils/__pycache__/ nothing added to commit but untracked files present (use "git add" to track)
在状态报告中能够看到新建的 README 文件出如今 Untracked files
下面。 未跟踪的文件意味着 Git 在以前的快照(提交)中没有这些文件;Git 不会自动将之归入跟踪范围,除非你明明白白地告诉它“我须要跟踪该文件”, 这样的处理让你没必要担忧将生成的二进制文件或其它不想被跟踪的文件包含进来。 不过如今的例子中,咱们确实想要跟踪管理 README 这个文件。
使用命令 git add
开始跟踪一个文件。
$ git add README.MD
注意:git add
命令使用文件或目录的路径做为参数;若是参数是目录的路径,该命令将递归地跟踪该目录下的全部文件。
此时再运行 git status
命令,会看到 README 文件已被跟踪,并处于暂存状态:
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README.MD
在 Changes to be committed
这行下面的,就说明是已暂存状态。 若是此时提交,那么该文件此时此刻的版本将被留存在历史记录中。
如今咱们来修改一个已被跟踪的文件。 若是你修改了一个名为 app01/views.py 的已被跟踪的文件,而后运行 git status
命令,会看到下面内容:
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README.MD Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: app01/tests.py modified: app01/views.py
出如今 Changes not staged for commit
这行下面,说明已跟踪文件的内容发生了变化,但尚未放到暂存区。 要暂存此次更新,须要运行 git add
命令。
git add
是个多功能命令:能够用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。 如今让咱们运行 git add
将"app01/views.py"放到暂存区,而后再看看 git status
的输出:
$ git add app01/views.py $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: README.MD modified: app01/views.py Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: app01/tests.py
如今两个文件都已暂存,下次提交时就会一并记录到仓库。
注意:若是在提交前,又进行了修改,文件将同时出如今暂存区和非暂存区。 这怎么可能呢? 好吧,实际上 Git 只不过暂存了你运行 git add
命令时的版本, 若是你如今提交,文件版本是你最后一次运行 git add
命令时的那个版本,而不是你运行 git commit
时,在工做目录中的当前版本。 因此,运行了 git add
以后又做了修订的文件,须要从新运行 git add
把最新版本从新暂存起来:
git status
命令的输出十分详细,但其用语有些繁琐。 若是你使用 git status -s
命令或 git status --short
命令,你将获得一种更为紧凑的格式输出。 运行 git status -s
,状态报告输出以下:
$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
新添加的未跟踪文件前面有 ??
标记,新添加到暂存区中的文件前面有 A
标记,修改过的文件前面有 M
标记。
你可能注意到了 M
有两个能够出现的位置,出如今右边的 M
表示该文件被修改了可是还没放入暂存区,出如今靠左边的 M
表示该文件被修改了并放入了暂存区。 例如,上面的状态报告显示: README
文件在工做区被修改了可是尚未将修改后的文件放入暂存区,lib/simplegit.rb
文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile
在工做区被修改并提交到暂存区后又在工做区中被修改了,因此在暂存区和工做区都有该文件被修改了的记录。
通常咱们总会有些文件无需归入 Git 的管理,也不但愿它们总出如今未跟踪文件列表。 一般都是些自动生成的文件,好比日志文件,或者编译过程当中建立的临时文件等。 在这种状况下,咱们能够建立一个名为 .gitignore
的文件,列出要忽略的文件模式。
git diff
命令。
git diff
:
$ git diff diff --git a/app01/tests.py b/app01/tests.py index 7ce503c..1636138 100644 --- a/app01/tests.py +++ b/app01/tests.py @@ -1,3 +1,10 @@ from django.test import TestCase # Create your tests here. + +def func(n): + n += 1 + print(n) + +func(3)
此命令比较的是工做目录中当前文件和暂存区域快照之间的差别, 也就是修改以后尚未暂存起来的变化内容。
若要查看已暂存的将要添加到下次提交里的内容,能够用 git diff --cached
命令(--staged 和 --cached 是同义词)。(Git 1.6.1 及更高版本还容许使用 git diff --staged
,效果是相同的,但更好记些。)
$ git diff --staged diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..ef195df --- /dev/null +++ b/README.MD @@ -0,0 +1,44 @@ +# alipay(服务端支付宝)
请注意:git diff 自己只显示还没有暂存的改动,而不是自上次提交以来所作的全部改动。 因此有时候你一会儿暂存了全部更新过的文件后,运行 git diff
后却什么也没有,就是这个缘由。
当暂存区域已经准备稳当,就能够提交了 。在此以前,请必定要确认还有什么修改过的或新建的文件尚未 git add
过,不然提交的时候不会记录这些还没暂存起来的变化。 这些修改过的文件只保留在本地磁盘。 因此,每次准备提交前,先用 git status
看下,是否是都已暂存起来了, 而后再运行提交命令 git commit
:
$ git commit
这种方式会启动文本编辑器以便输入本次提交的说明。 (默认会启用 shell 的环境变量 $EDITOR
所指定的软件,通常都是 vim 或 emacs。固然也能够按照 起步 介绍的方式,使用 git config --global core.editor
命令设定你喜欢的编辑软件。)
编辑器会显示相似下面的文本信息(本例选用 Vim 的屏显方式展现):
# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is up-to-date with 'origin/master'. # # Changes to be committed: # new file: README.MD # modified: app01/views.py
~
默认的提交消息包含最后一次运行 git status
的输出,放在注释行里,另外开头还有一空行,供你输入提交说明。
退出编辑器时,Git 会丢掉注释行,用你输入提交附带信息生成一次提交。
$ git commit [master ad9cae3] git test 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 README.MD
另外,你也能够在 commit
命令后添加 -m
选项,将提交信息与命令放在同一行,以下所示:
$ git commit -m "git test"
Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,Git 就会自动把全部已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: CONTRIBUTING.md no changes added to commit (use "git add" and/or "git commit -a") $ git commit -a -m 'added new benchmarks' [master 83e38c7] added new benchmarks 1 file changed, 5 insertions(+), 0 deletions(-)
这样提交以前再也不须要 git add
文件“CONTRIBUTING.md”了。
要从 Git 中移除某个文件,就必需要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),而后提交。 能够用 git rm
命令完成此项工做,并连带从工做目录中删除指定的文件,这样之后就不会出如今未跟踪文件清单中了。
若是只是简单地从工做目录中手工删除文件,运行 git status
时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到:
$ rm app01/tests.py $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) 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) deleted: app01/tests.py
而后再运行 git rm
记录这次移除文件的操做:
$ git rm app01/tests.py rm 'app01/tests.py' $ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: app01/tests.py
下一次提交时,该文件就再也不归入版本管理了。 若是删除以前修改过而且已经放到暂存区域的话,则必需要用强制删除选项 -f
(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。