3.提交你的修改¶
上一章告诉你如何克隆远程仓库到你的本地系统。在这一点上,你已经准备好开始对你的版本库进行修改了。这很好!
但是,很明显,仅仅对本地文件进行修改并不是你需要做的全部。你还需要对你的文件进行修改,让Git
知道这些修改。一旦你完成了修改,你就需要告诉Git
你想把这些修改提交到仓库。
什么是提交?¶
你现在可能已经猜到了,Git repo
不仅仅是一个文件的集合;在它的表面之下,有很多东西在追踪你的改动的各种状态,更重要的是,要对这些改动做什么。
首先,回到你的分叉仓库的主页https://github.com/[your-username]/ideas
,然后在仓库页面的顶部找到12 commits
链接:
Note
如果你没有完成上一章的挑战,那么就去创建一个https://github.com/raywenderlich/ideas
的分叉,并将其克隆到你的本地工作站。
点击这个链接,你会看到这个资源库的一些历史:
每个条目都是一个commit
,本质上是版本库中的文件集在某个时间点的特定状态的快照。
一般来说,一个提交代表了对文件集的一些逻辑更新。想象一下,你正在为你的想法列表添加新的项目,而且你已经添加了很多你能想到的项目。你想把这部分工作以提交的方式记录到你的版本库中。
在你开始这些更新之前,版本库的状态--实际上是你的起点--是parent
的提交。在你提交你的修改后,也就是diff
,下一次提交就是child
提交。下图对此有更多解释:
在这个例子中,我在两次提交之间给一个文件添加了新的文本。父提交是左边的文件,子提交是右边的文件。它们之间的差异是我对一个文件所做的修改:
而且,diff
不仅仅是对文件的添加,创建新内容、修改内容和删除内容也是你对仓库中的文件所做的其他常见改动。
在Git
中,改变文件和创建提交之间有几个步骤。起初,这可能是一个有点沉重的方法,但是,当你通过建立你的提交,你会看到每个步骤是如何帮助创建一个工作流程,使你与你的仓库中的文件和它们发生了什么保持一致。
要理解建立提交的过程,最简单的方法是实际创建一个提交。你将创建一个文件的修改,看看Git
是如何确认这个修改的,如何将这个修改分阶段,最后,如何将这个修改提交给仓库。
从改变开始¶
打开你的终端程序,导航到ideas
仓库;在我的例子中,我把它放在GitApprentice
目录中。这应该是你在前一章创建的分叉版本库的克隆。
Note
如果你错过了完成第二章末尾的挑战,现在回去按照挑战方案做,这样你就有一个本地克隆的分叉ideas
库可以使用。
假设你想在books
文件中添加更多的想法。在任何纯文本编辑器中打开books/book_ideas.md
。我喜欢用nano
,因为它快速而简单,而且我不需要记住任何晦涩的命令来使用它。
在文件的末尾添加一行,以捕捉一个新书的想法:"开发者的护理和喂养"。注意遵循与其他条目相同的格式。你的文件应该看起来像这样:
# Ideas for new book projects
- [ ] Hotubbing by tutorials
- [x] Advanced debugging and reverse engineering
- [ ] Animal husbandry by tutorials
- [ ] Beginning tree surgery
- [ ] CVS by tutorials
- [ ] Fortran for fun and profit
- [x] RxSwift by tutorials
- [ ] Mastering git
- [ ] Care and feeding of developers
完成后,保存你的工作,并返回到终端程序。
在后台,Git
正在观察你所做的事情。不相信我?在ideas
目录下执行以下命令,看看Git
知道你做了什么,在这里:
git status
git status
显示你的工作树的当前状态 - 也就是你正在工作的目录中的文件集合。在你的例子中,工作树是你的ideas
目录下的所有文件。
你应该看到下面的输出:
~/GitApprentice/ideas $ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: books/book_ideas.md
no changes added to commit (use "git add" and/or "git commit -a")
啊,这就是你刚刚修改的文件:books/book_ideas.md
。Git
知道你已经修改了它......但当Git
说Changes not staged for commit
时是什么意思?
现在是时候转移一下注意力,看看你的文件在Git
中的各种状态。建立Git
各种状态的心理模型,对理解Git
在做什么有很大帮助...特别是当Git
做了一些你不太理解的事情时。
工作树和暂存区¶
working copy
或working tree
或working directory
(语言很好,总是有不止一个名字)是你磁盘上的项目文件的集合,你可以直接使用和修改,就像你在上面的books/book_ideas.md
中做的那样。
Git
认为你的工作树中的文件处于三种不同的状态:
- 未修改的
- 修改过的
- 阶段性的
Unmodified
意味着你在上次提交后没有修改过这个文件。Modified
则与此相反。Git
认为你在上次提交后以某种方式修改了这个文件。但这个staged
状态是什么?
如果你来自其他版本控制系统的背景,比如Subversion
,你可能会认为commit
只是把你所有的修改保存到仓库的当前状态。但Git
是不同的,而且更优雅。相反,Git
通过使用staging area
的概念,让你在工作中逐步建立你的下一个提交。
Note
如果你曾经搬过家,你就会理解这个范式。当你为搬家打包时,你不会把你所有的东西都松散地扔到搬家车的后面(好吧,也许你会这么做,但你不应该,真的)。 相反,你拿一个纸板箱(中转区),把类似的东西装进去,摆弄一下,让所有东西都正确地装在箱子里,取出一些不完全属于自己的东西,再加上一些你忘记的东西。 当你对箱子的尺寸感到满意时,你就用包装胶带把箱子封起来,然后把箱子放到货车的后面。在这种情况下,你已经把箱子当作了你的中转区,把箱子贴起来,放在货车上,就像做了一个承诺。
基本上,当你在项目的各个部分工作时,你可以把一个或一组修改标记为staged
,也就是告诉Git
,"嘿,我想把这些修改放到我的下一次提交中...但我可能还有一些修改要给你,所以先把这些修改保留一下吧。"你可以在工作过程中从这个暂存区域添加和删除修改,只有在你准备好的时候才提交这组精心策划的修改到仓库中。
注意上面我说的是,"从暂存区添加和删除变化",而不是"从暂存区添加和删除文件"。这里有一个明显的区别,在你进行最初的几次修改时,你会看到这个区别。
暂存你的改动¶
Git
非常有用,它(通常)会在命令的输出中告诉你该怎么做。回顾一下上面git status
的输出,Changes not staged for commit
部分给了你一些建议,让你知道该怎么做。
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
所以,既然你想让这个改动最终提交到版本库,你会尝试第一个建议:git add
。
执行下面的命令:
git add books/book_ideas.md
然后,执行git status
来查看你所做的结果:
~/GitApprentice/ideas $ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: books/book_ideas.md
啊,这似乎好了一点。Git
认识到你现在已经把这个改动放在了暂存区。
但你还需要对这个文件做另一个修改,而你却忘记了。既然你在读这本书,你也许应该在其中的Mastering git
条目上打勾,标记为完成。
在你的文本编辑器中打开books/book_ideas.md
,在方框中打上小写的x
,标记该项目为完成:
- [x] Mastering git
保存你的改动并退出编辑器。现在,再次执行git status
(是的,你会经常使用这个命令来确定你的方向),看看Git
告诉你什么:
~/GitApprentice/ideas $ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: books/book_ideas.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: books/book_ideas.md
怎么了?Git
现在告诉你,books/book_ideas.md
既是*阶段性的,又是非阶段性的?这怎么可能呢?
记住,你在这里暂存的是变化,而不是文件。Git
理解这一点,并告诉你有一个变化已经被暂存提交("关心和喂养开发者"的变化),还有一个变化尚未被暂存--将Mastering git
标记为完成。
要看到这个细节,你可以告诉Git显示它所看到的变化。还记得我们之前说过的`diff'吗?是的,那是你的下一个新命令。
执行下面的命令:
git diff
你会看到与下面类似的东西:
diff --git a/books/book_ideas.md b/books/book_ideas.md
index 76dfa82..5086b1f 100644
--- a/books/book_ideas.md
+++ b/books/book_ideas.md
@@ -7,5 +7,5 @@
- [ ] CVS by tutorials
- [ ] Fortran for fun and profit
- [x] RxSwift by tutorials
-- [ ] Mastering git
+- [x] Mastering git
- [ ] Care and feeding of developers
这看起来很晦涩,但diff
只是一种显示两个文件之间变化的简洁方式。在这个例子中,Git
告诉你,你正在比较同一个文件的两个版本--你工作目录中的文件版本,以及你之前用git add
命令告诉Git
的文件版本:
--- a/books/book_ideas.md
+++ b/books/book_ideas.md
而且它还显示了这两个版本之间的变化:
-- [ ] Mastering git
+- [x] Mastering git
-
前缀意味着删除了一行(或该行的一部分),+
前缀意味着增加了一行(或该行的一部分)。在这个例子中,你删除了空格,增加了一个x
字符。
你会在接下来的学习中了解到更多关于git diff
的知识,但现在这些已经足够你使用了。是时候把你的最新改动分阶段了。
总是用git add
键入你想分阶段的文件的全名是有点乏味的。而且,老实说,大多数时候你真的只想把你所做的所有改动分到阶段。Git
为你提供了一个很好的快捷方式。
按键盘上的Q
键退出差异视图,然后执行以下命令:
git add .
句号(或句号)告诉Git
将所有的修改添加到暂存区域,包括这个目录和所有其他子目录。这很方便,你会在你的工作流程中经常用到它。
同样,执行git status
可以看到你的暂存区有什么准备好了:
~/GitApprentice/ideas $ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: books/book_ideas.md
这看起来不错。没有任何未缓存的内容,你将看到对books/book_ideas.md
的修改,这些修改已经准备好提交。
有趣的是,再执行一次git diff
,看看有什么变化:
~/GitApprentice/ideas $ git diff
~/GitApprentice/ideas $
呃,这很有趣。git diff
报告说没有变化。但如果你想一想,这是有道理的。git diff
比较了你的工作树和暂存区。用git add .
,你把工作树上的所有东西都放到暂存区,所以你的工作树和暂存区之间应该没有差异。
如果你想做得彻底(或者你还不相信Git
),你可以要求Git
在git diff
的末尾增加一个选项来显示它缓存提交的差异。
执行下面的命令,注意是两个--
字符,而不是一个:
git diff --staged
你会看到一个类似于以下的差异:
diff --git a/books/book_ideas.md b/books/book_ideas.md
index 1a92ca4..5086b1f 100644
--- a/books/book_ideas.md
+++ b/books/book_ideas.md
@@ -7,4 +7,5 @@
- [ ] CVS by tutorials
- [ ] Fortran for fun and profit
- [x] RxSwift by tutorials
-- [ ] Mastering git
+- [x] Mastering git
+- [ ] Care and feeding of developers
下面是已经改变的线路:
-- [ ] Mastering git
+- [x] Mastering git
+- [ ] Care and feeding of developers
你从Mastering git
一行中删除了一些东西,在Mastering git
一行中增加了一些东西,并增加了Care and feeding of developers
一行。这似乎就是一切了。看来是时候把你的修改提交到仓库了。
提交你的改动¶
你已经做了所有的修改,你准备提交到版本库。只要执行下面的命令就可以进行第一次提交:
git commit
Git
会带你进入一个相当混乱的状态。下面是我在终端程序中看到的情况:
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Your branch is up to date with 'origin/main'.
#
# Changes to be committed:
# modified: books/book_ideas.md
#
如果你以前没有被介绍过vim
,欢迎你! Vim
是Git
在需要你输入自由文本时使用的默认文本编辑器。
如果你读了Git
在那里提供的第一条小指令,就会发现Git
在要求什么:
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
啊--Git
需要为你的提交提供一条信息。如果你回想一下本章前面看到的提交列表,你会发现每个条目都有一个小消息:
在Vim
中工作并不十分直观,但是一旦您知道了命令,就不难了。
按键盘上的I
键进入Insert
模式,您将看到屏幕底部的状态行更改为-- INSERT--
以指示这一点。您可以在此随意键入内容,但请保持简单,并将消息限制在一行开始。
为提交消息键入以下内容:
Added new book entry and marked Git book complete
完成后,需要告诉Vim保存文件并退出。先按Escape
键退出插入模式。
现在,键入冒号(Shift
+ ;
在我的美式键盘上)进入Ex
模式,该模式允许您执行命令。
要保存您的工作并一次性退出,请按顺序键入wq
- 表示“write”
和“quit”
,然后按Enter
:
:wq
你将被带回到命令行,并显示提交的结果:
~/GitApprentice/ideas $ git commit
[main 57f31b3] Added new book entry and marked Git book complete
1 file changed, 2 insertions(+), 1 deletion(-)
就是这样! 这是你的第一次提交。更改了一个文件,插入了两个,删除了一个。这与本章前面的git diff
中的内容相吻合。
现在您已经了解了如何提交对文件的更改,接下来将了解如何向存储库添加新文件和目录。
添加目录¶
您的项目中有目录来保存书籍、视频和文章的想法。但是如果有一个目录来存储编写教程的想法就好了。因此,您将创建一个目录和一个创意文件,并将它们添加到存储库中。
回到终端程序中,执行以下命令创建一个名为tutorials
的新目录:
mkdir tutorials
然后,使用ls
命令确认目录是否存在:
~/GitApprentice/ideas $ ls
LICENSE articles tutorials
README.md books videos
目录就在那里;现在你可以看到Git
是如何识别新目录的。执行以下命令:
git status
您将看到以下内容:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
呃,好像不太对。为什么Git
看不到你的新目录? 这是Git
的设计,它反映了Git
看待文件和目录的方式。
Git
如何查看工作树¶
在它的核心,Git
实际上只知道files
,而对目录一无所知。Git
认为文件是“指向Git
可以跟踪的实体的字符串”。如果你想一想,这是有道理的:如果一个文件可以被唯一地引用为该文件的完整路径,那么单独跟踪目录是非常多余的。
例如,下面是项目中当前所有文件的列表(不包括隐藏文件、隐藏目录和空目录):
ideas/LICENSE
ideas/README.md
ideas/articles/clickbait_ideas.md
ideas/articles/live_streaming_ideas.md
ideas/articles/ios_article_ideas.md
ideas/books/book_ideas.md
ideas/videos/content_ideas.md
ideas/videos/platform_ideas.md
这是Git
如何查看项目的简化版本:存储库中跟踪的文件的路径列表。这样,Git
在将仓库克隆到本地系统时,可以轻松快速地重新创建目录和文件结构。
在本书的中间部分,你会学到更多关于Git
内部工作原理的知识,但现在,你只需要弄清楚如何让Git
拾取一个你想要添加到仓库中的新目录。
.keep
文件¶
让Git
识别目录的解决方案显然是在目录中放入一个文件,但如果你还没有任何东西要放进去,或者你想让每个人克隆这个项目时都看到一个空目录,该怎么办?
解决方案是使用占位符文件。通常的约定是在你想让Git
“看到”的目录中创建一个隐藏的、零字节的.keep
文件。
为此,首先使用以下命令导航到刚刚创建的tutorials
目录:
cd tutorials
然后创建一个名为.keep
的空文件,使用touch
命令以方便使用:
touch .keep
Note
touch
命令最初是用来设置和修改现有文件的“modified”
和“accessed”
时间的。但是touch
的一个很好的特性是,如果指定的文件不存在,touch
会自动为你创建一个文件。
touch
是打开文本编辑器创建和保存空文件的一个很好的替代方法。有经验的命令行用户大多数时候都使用此快捷方式。
执行以下命令查看此目录的内容,包括隐藏的点文件:
ls -a
您应看到以下内容:
~/GitApprentice/ideas/tutorials $ ls -a
. .. .keep
这是你的隐藏文件。让我们看看Git
现在对这个目录的看法。执行以下命令以移回主项目目录:
cd ..
现在,执行git status
来看看Git
对当前情况的理解:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Untracked files:
(use "git add <file>..." to include in what will be committed)
tutorials/
nothing added to commit but untracked files present (use "git add" to track)
Git
现在知道那个目录里有东西,但是它是untracked
,这意味着你还没有把那个目录里的东西添加到仓库里。使用git add
命令可以很容易地添加该目录的内容。
执行下面的命令,它与git add
的形式略有不同:
git add tutorials/\*
Note
上面两个斜杠的奇怪格式在bash shell
或zsh shell
中应该是等效的,这是较新的macOS
系统上的默认设置。
而你可以只用git add
。和前面一样,添加所有文件,这种形式的git add
是一种很好的方式,可以只添加特定目录或子目录中的文件。在本例中,您要告诉Git
暂存tutorials
目录下的所有文件。
Git
现在告诉你它正在跟踪这个文件,并且它在暂存区:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: tutorials/.keep
现在可以将此添加提交到存储库。但是,与使用Vim
和文本编辑器调用整个业务不同,有一种快捷方式可以一次性将文件提交到存储库并添加消息。
执行以下命令将暂存的更改提交到存储库:
git commit -m "Adding empty tutorials directory"
您将看到以下内容,确认已提交更改:
~/GitApprentice/ideas $ git commit -m "Adding empty tutorials directory"
[main ce6971f] Adding empty tutorials directory
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 tutorials/.keep
Note
根据您所工作的项目或组织,您经常会发现在Git
提交消息中包含哪些内容是有标准的。
本书的前几部分使用了一行提交消息,使事情变得简单,但是随着你在Git
职业生涯中的发展,你会明白为什么遵循一些标准,比如Tim Pope
在www.example.com上提出的50/72
规则https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.htmlhttps://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html,会让你在更深入地研究Git时变得更容易。
再次使用git status
查看是否没有需要提交的内容:
~/GitApprentice/ideas $ git status
On branch main
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
你可能已经意识到,所有这些小提交都能给予你看到Git
对你的文件做了什么。而且,当你继续你的项目时,你可能想看到你所做的事情的历史视图。Git
提供了一种查看文件历史记录的方式,也称为log
。
查看git
日志¶
你在前几章做了很多事情。要查看您所做的操作,请执行以下命令:
git log
你会得到一堆输出下面是我的日志的前几部分:
commit 7f6c00a4e8aaac251f66244d7d685cefce899868 (HEAD -> main)
Author: Bhagat Singh <bhagatsingh2297@gmail.com>
Date: Tue Oct 26 08:48:20 2021 +0530
Adding empty tutorials directory
commit ba67184b4a934d56a1c0c3cc493ff5b3bf8cc062
Author: Bhagat Singh <bhagatsingh2297@gmail.com>
Date: Tue Oct 26 08:38:31 2021 +0530
Added new book entry and marked Git book complete
commit f65a79061758a3e52667d5bd6ba12efb4e7158c5 (origin/main, origin/HEAD)
Author: Bhagat Singh <bhagatsingh2297@gmail.com>
Date: Thu Sep 9 12:17:55 2021 +0530
Updated README.md to reflect current working book title.
commit c47084959448d2e0b6877832b6bd3ae70f70b187 (origin/master)
Author: Chris Belanger <chris@razeware.com>
Date: Thu Jan 10 10:32:55 2019 -0400
Going to try this livestreaming thing
:
.
.
.
你会看到你所有的提交,按时间倒序排列。
Note
根据您在终端程序中一次可以看到的行数,您的输出可能会被分页,使用类似less
的读取器。如果您在终端屏幕的最后一行看到冒号,则可能是这种情况。只需按空格键即可阅读后面的文本。
当您到达文件末尾时,您将看到(END)
。在任何时候,您都可以按Q
键退出到命令提示符。
上面的输出显示了您自己的提交消息,在某种程度上,它们是有用的。因为Git
知道你的文件的所有信息,你可以使用git log
来查看提交的每一个细节,比如每次提交的实际更改或diff
。
要查看这一点,请执行以下命令:
git log -p
这会向您显示提交的实际差异,以帮助您查看具体更改了什么。以下是我的结果示例:
commit 7f6c00a4e8aaac251f66244d7d685cefce899868 (HEAD -> main)
Author: Bhagat Singh <bhagatsingh2297@gmail.com>
Date: Tue Oct 26 08:48:20 2021 +0530
Adding empty tutorials directory
diff --git a/tutorials/.keep b/tutorials/.keep
new file mode 100644
index 0000000..e69de29
commit ba67184b4a934d56a1c0c3cc493ff5b3bf8cc062
Author: Bhagat Singh <bhagatsingh2297@gmail.com>
Date: Tue Oct 26 08:38:31 2021 +0530
Added new book entry and marked Git book complete
diff --git a/books/book_ideas.md b/books/book_ideas.md
index 1a92ca4..5086b1f 100644
--- a/books/book_ideas.md
+++ b/books/book_ideas.md
@@ -7,4 +7,5 @@
- [ ] CVS by tutorials
- [ ] Fortran for fun and profit
- [x] RxSwift by tutorials
-- [ ] Mastering git
+- [x] Mastering git
+- [ ] Care and feeding of developers
.
.
.
按照时间倒序,我将.keep
文件添加到了tutorials
目录中,并对book_ideas.md
文件做了一些修改。
Note
第6章,“Git Log & History”,将深入研究git log
的各个方面,并向您展示如何使用git log
的各种选项来获得一些关于仓库活动的有趣信息。
既然您已经很好地理解了如何暂存变更并将其提交到存储库中,那么是时候迎接本章的挑战了!
挑战¶
挑战:添加一些教程想法¶
您已经有了一个很好的目录来存储教程的想法,所以现在是时候添加这些伟大的想法了。 您在本次挑战中的任务是:
- 在
tutorials
目录中创建一个名为tutorials_ideas. md
的新文件。 - 向文件添加标题:
# Tutorial Ideas
。 - 按照其他文件的格式,用一些想法填充该文件,例如
[] Mastering PalmOS
。 - 保存您的更改。
- 将这些更改添加到临时区域。
- 使用适当的消息提交这些临时更改。
如果你遇到了困难,你可以在本章的projects/challenge
文件夹中找到解决这个挑战的方法。
同样,如果您希望将您的存储库或目录的状态与我的进行比较,您还会发现我的ideas
目录压缩在同一个文件夹中。
要点¶
commit
本质上是存储库中的文件集在某个时间点的特定状态的快照。working tree
是您直接使用的项目文件的集合。git status
显示工作树的当前状态。Git
认为工作树中的文件处于三种不同的状态:未修改的、修改的和分段的。git add<filename>
允许您将工作树中的更改添加到临时区域。git add .
添加当前目录及其子目录中的所有更改。git add <directoryname>/\*
允许您添加指定目录中的所有更改。git diff
显示工作树和暂存区之间的差异。git diff --staged
显示了暂存区和上次提交到仓库之间的差异。git commit
提交暂存区中的所有更改,并打开Vim
以便添加提交消息。git commit -m "<your message here>"
提交您的阶段性更改并包含一条消息,而无需通过Vim
。git log
显示仓库的基本提交历史。git log -p
显示仓库的提交历史以及相应的差异。
从这里去哪里?¶
现在你已经学会了如何在Git
中创建提交,请继续阅读下一章,在那里你会学到更多关于暂存修改的技巧,包括Git
如何理解文件的移动和删除,如何撤销你不想做的暂存修改,以及接下来的新命令:git reset
、git mv
和git rm
。