赞
踩
在前面的实战部分,已经体验过怎么将文件添加到本地的git仓库了。
工作目录(实战中的learngit
文件夹)下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪。
已跟踪:已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 git 已经知道的文件。
未跟踪:除了已跟踪的文件,都是未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 git 刚刚检出了它们, 而你尚未编辑过它们。
编辑过某些文件之后,由于自上次提交后你对它们做了修改,git 将它们标记为已修改文件。在工作时,你可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。下图为文件的状态变化周期
接着往下看,看完还不懂,提上你40米长的大刀来砍我。
这里再次使用learngit
目录,在上面的实践结束后,该目录下只有一个readme.txt
文件,我们使用git status
命令查看一下文件处于什么状态,使用此命令,会看到类似这样的输出:
$ git statusOn branch master # 说明当前所在分支 master 为默认分支名nothing to commit, working tree clean # emmm~ 你细细拼一下这什么意思
这个输出表明自实践结束后,还未对目录里的文件进行过任何修改,也没有出现任何处于未跟踪状态的新文件,否则 git 会在这里列出来,最后,该命令还显示了当前所在分支(之后会介绍分支)。
现在,在learngit
目录下,新建一个test.txt
文件,文件内容为:
this is a test file
此时,使用git status
命令,就能看到一个新的未被跟踪的文件:
$ git statusOn branch masterUntracked files: (use "git add ..." to include in what will be committed) test.txtnothing added to commit but untracked files present (use "git add" to track)
在状态报告中可以看到新建的 test.txt
文件出现在 Untracked files
下面。未跟踪的文件意味着 git 仓库中没有这些文件;git 不会自动将之纳入跟踪范围。现在搞懂未跟踪文件的意思了吧。
如果想要将test.txt
也加入git仓库,让git进行管理,就要先将test.txt
加入暂存区,进行跟踪。
已经提到很多次暂存区了,那么究竟什么是暂存区?
工作区(Working Directory):
就是在电脑里能看到的目录,比如learngit
文件夹就是一个工作区:
版本库(Repository):
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
分支和HEAD
的概念我们以后再讲。
前面有讲过使用git add
命令将文件加入暂存区,实际上是把要提交的文件的所有修改添加到暂存区,然后执行git commit
就可以一次性把暂存区的所有修改提交到本地仓库的分支上。
暂存区(Stage或Index):
一般存放在 .git
目录下的 index 文件(.git/index
)中,所以我们把暂存区有时也叫作索引(index
)。暂存区可以理解为一个虚拟工作区,这个虚拟工作区会跟踪工作区的文件变化(增删改等操作)。这个工作区的位于.git 文件夹下的index
文件中。
需要理解一点:当需要对工作区的修改提交到版本库前,暂存区会与工作区进行差异比较,如果工作区与暂存区的文件不一致,那么需要同步工作区的修改到暂存区,然后才可以提交到版本库。从这个意义讲,暂存区可以说是工作区和版本库的桥梁。好处自然是可以在真正提交到版本库之前做任意的操作,在需要真正提交的时候 commit 到版本库 。当执行完git commit
命令时,暂存区会被清空。
实践出真知,我们来实践一下:
在之前的操作中,添加了一个新的文件test.txt
,之后就没有其他操作了,现在,我们修改一下readme.txt
文件,比如加上一句话:
Git is a version control system.Git is free software.Git has a mutable index called stage.
再用git status
查看一下状态:
$ git statusOn branch masterChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: readme.txtUntracked files: (use "git add ..." to include in what will be committed) test.txtno changes added to commit (use "git add" and/or "git commit -a")
git非常清楚的告诉了我们,readme.txt
被修改了,而test.txt
的状态是未被跟踪的。
现在,使用git add
命令,把readme.txt
和test.txt
都添加到暂存区,使用git status
再次查看一下状态:
# 将readme.txt和test.txt一次性添加到暂存区$ git add readme.txt test.txt$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txt new file: test.txt
此时,暂存区的状态就变成这样了:
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
$ git commit -m 'understand how stage works'[master 8ec32e3] understand how stage works 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 test.txt
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
$ git statusOn branch masternothing to commit, working tree clean
现在版本库变成了这样,暂存区就没有任何内容了:
搞定收工!
使用命令git add
开始跟踪一个文件,这个已经讲过很多次了,就不赘述了,不过要注意的是文件名不能写错:
# 这里要写文件的全名$ git add test.txt# 文件名没有写全,或者写错,会出现下面的信息$ git add testfatal: pathspec 'test' did not match any files$ git add test.txfatal: pathspec 'test.tx' did not match any files
暂存已修改的文件,使用的命令是:
没错,还是git add
,惊不惊喜意不意外?这个前面也已经提到了,就不赘述了。
git add
命令是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目(仓库)中”要更加合适。
这里有一个需要注意的点:同一个文件,同时出现在暂存区和非暂存区。
我们来重现一下这个问题:
首先,修改readme.txt
文件,将内容改为:
Git is a version control system.Git is free software.Git has a mutable index called stage.Git is so good
使用git add
命令将readme.txt
放入暂存区,使用git add
命令查看:
$ git add readme.txt$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txt
再次修改readme.txt
文件:
Git is a version control system.Git is free software.Git has a mutable index called stage.Git is so goodLinus is god
此时再次运行git status
命令看看:
$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txtChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: readme.txt
现在readme.txt
文件同时出现在暂存区和非暂存区。实际上 git 只不过暂存了你最后一次运行 git add
命令时的版本。如果你现在提交,你在git add
命令之后的修改,不会被提交到仓库中。所以,运行了 git add
之后又进行过修改的文件,需要重新运行 git add
把最新版本重新暂存起来:
$ git add readme.txt$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txt
现在把readme.txt
提交到仓库吧
$ git commit -m 'update readme.txt'[master 0086f1a] update readme.txt 1 file changed, 3 insertions(+), 1 deletion(-)
git status
命令的输出十分详细,显得有些繁琐。git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。如果你使用 git status -s
命令或 git status --short
命令,你将得到一种格式更为紧凑的输出。你可能会看到以下输出:
$ git status -s M helloGit.txtMM README.mdM test.txtA testC.c?? testDoc.doc
新添加的未跟踪文件前面有 ??
标记,新添加到暂存区中的文件前面有 A
标记,修改过的文件前面有 M
标记。输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。例如,上面的状态报告显示:helloGit.txt
文件在工作区已修改但尚未暂存,而 test.txt
文件已修改且已暂存。README.md
文件已修改,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分
是不是有点晕?没关系,我们再实践一下,重现上面的输出。
上面的输出涉及了5个文件,我们learngit
目录中已经有两个了,再新建三个文件app.txt
、google.txt
、ali.txt
,文件内容任意就行。
将app.txt
、google.txt
添加到暂存区中
$ git add app.txt google.txt# 单独提交 app.txt文件$ git commit -m 'commit app.txt' app.txt
再修改app.txt
文件内容
修改test.txt
文件,并使用git add
命令将其加入暂存区
修改readme.txt
文件,并使用git add
命令将其加入暂存区,之后再次进行修改
使用git status -s
命令查看状态
$ git status -s M app.txtA google.txtMM readme.txtM test.txt?? ali.txt
如果步骤1中没有单独提交app.txt
文件,那么输出应该是这样的:
$ git status -sAM app.txtA google.txtMM readme.txtM test.txt?? ali.txt
小结:使用git status -s
查看状态,状态会以两列显示,左栏表示暂存区的状态,右栏表示工作区的状态。
完美复现了,现在将他们提交到仓库,以免忘记,影响下次实验:
$ git commit -a -m 'update file content and add app.txt google.txt'[master b9cb70f] update file content and add app.txt google.txt 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 app.txt create mode 100644 google.txt
一般来讲,总有不需要放入git仓库进行管理的文件,也不想看到它出现在未跟踪列表,在这种情况下,我们可以创建一个名为 .gitignore
的文件,列出要忽略的文件的模式。来看一个实际的 .gitignore
例子:
$ cat .gitignore # cat命令可以查看文件内容*.[oa] # 文件内容*~ # 文件内容
第一行告诉 git 忽略所有以 .o
或 .a
结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。第二行告诉 git 忽略所有名字以波浪符~
结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件 .gitignore
的格式规范如下:
所有空行或者以 #
开头的行都会被 Git 忽略。
可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
匹配模式可以以(/
)开头防止递归。
匹配模式可以以(/
)结尾指定目录。
要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!
)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*
)匹配零个或多个任意字符;[abc]
匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?
)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9]
表示匹配所有 0 到 9 的数字)。使用两个星号(**
)表示匹配任意中间目录,比如 a/**/z
可以匹配 a/z
、 a/b/z
或 a/b/c/z
等。
我们再看一个 .gitignore
文件的例子:
# 忽略所有的 .a 文件*.a# 跟踪所有的 lib.a,即便你在前面忽略了 .a 文件!lib.a# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO/TODO# 忽略任何目录下名为 build 的文件夹build/# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txtdoc/*.txt# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件doc/**/*.pdf
在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore
文件,它递归地应用到整个仓库中。然而,子目录下也可以有额外的 .gitignore
文件。子目录中的 .gitignore
文件中的规则只作用于它所在的目录中。
Tip:GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore
文件列表, 你可以在 https://github.com/github/gitignore 找到它。
实践:在做完上一个示例之后,我们使用git status -s
命令查看文件状态
$ git statusOn branch masterUntracked files: (use "git add ..." to include in what will be committed) ali.txtnothing added to commit but untracked files present (use "git add" to track)
git 会一直提示ali.txt
未被跟踪,这是不是很烦人,假如这个文件,就是个临时文件,没有价值的文件,我们不想让git管理它,那么,这个时候,我们可以新建一个.gitignore
文件,将它加入git仓库进行管理。
首先,新建.gitignore
文件。这里说一下,在Windows系统下,是不能直接新建以.
开头的文件,除非你这么命名.gitignore.txt
(这个是可行的),那么假如你新建的是.gitignore.txt
文件,并添加了如下内容:
ali.txt
那看看git是怎么看待这个文件的:
$ git statusOn branch masterUntracked files: (use "git add ..." to include in what will be committed) .gitignore.txt ali.txtnothing added to commit but untracked files present (use "git add" to track)
没错,就是个普通文件,它并没有让git忽略掉ali.txt
文件,那咋办?没错,你可能会想到手动改后缀名呗,那我们来看一下:
坑爹的Windows就是不让你改,想砸电脑啊有木有?那可千万别砸,大好几千呢,总有解决问题的方法的。
之前介绍过Notepad++这款软件,这个软件真的超好用,没装的装一下。打开Notepad++,新建文件(中文界面,都是各界精英肯定会),然后在文件中输入一下内容:
ali.txt
没错,就上面一行,然后Ctrl + S
保存,这个时候,重点来了(敲黑板):
然后去learngit
这个目录下看看,有没有.gitignore
文件,接下来就是见证奇迹的时刻:
.gitignore
诞生了,现在来看看git是怎么看待这个文件的:
$ git statusOn branch masterUntracked files: (use "git add ..." to include in what will be committed) .gitignorenothing added to commit but untracked files present (use "git add" to track)
发现没有,ali.txt
文件不见了,这说明我们的.gitignore
文件生效了,这个时候,我们只需要把.gitignore
文件添加到暂存区,然后commit提交到git仓库就行了。当然你不暂存,不提交,都是可以的,它照样可以生效,只是不暂存不提交,你之后每次使用git status
命令,都能看见它,你说烦不烦,所以还是乖乖暂存提交吧
$ git add .gitignore$ git commit -m 'add file .gitignore '[master f2e4019] add file .gitignore 1 file changed, 1 insertion(+) create mode 100644 .gitignore# 在查看一下文件状态$ git statusOn branch masternothing to commit, working tree clean
我们再来看看ali.txt
是不是还在我们磁盘上:
嗯,还在,说明我真的没有删它,它真的是被git给忽略掉了。OK,示例结束。
这里有一个奇葩的需求:让.gitignore
忽略自己,经典的我忽略我自己,可还行。
但是 .gitignore
作为一个仓库结构的一部分,本身就应该是存在的,如果什么都不想忽略,那么就没必要建一个文件了。真碰到这种需求,总归还是要解决的。如果把.gitignore
加到.gitignore
文件中,是不起作用的。
解决办法:
编辑当前项目下的./git/info/exclude
文件,然后将需要忽略提交的.gitignore
文件路径写入就行了,注意写入文件的路径是相对项目根目录而言的。
查看已暂存和未暂存的修改
如果你想知道某个文件具体修改了什么地方,可以用 git diff
命令。
现在我们再次修改readme.txt
文件后暂存,然后编辑test.txt
文件后先不暂存,运行git status
命令将会看到:
$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txtChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: test.txt
要查看尚未暂存的文件更新了哪些部分,不加参数直接输入 git diff
:
$ git diffdiff --git a/test.txt b/test.txtindex 879fceb..9e431f3 100644--- a/test.txt+++ b/test.txt@@ -1,2 +1,3 @@ this is a test file-add some file # 前面是-说明是删除的内容\ No newline at end of file # 在文件末尾没有换行符,这个是编辑器和系统的问题,我没有乱说,我有图为证,后面上Linux下的图+add some file # 前面是+说明这是新增的内容 至于为什么先删后加,通过和Linux系统的对比,我认为是系统或者编辑器的问题,如果有知道真相的小伙伴,可以告诉我,帮我纠正一下,共同进步,后面上Linux下的图+test git diff # 前面是+说明这是新增的内容\ No newline at end of file
此命令比较的是修改之后还没有暂存起来的变化内容。
想要查看已暂存文件修改了什么内容,可以用git diff --staged
命令。这条命令将比对已暂存文件与最后一次提交的文件差异:
$ git diff --stageddiff --git a/readme.txt b/readme.txtindex 7cc6fe7..67386fd 100644--- a/readme.txt+++ b/readme.txt@@ -4,4 +4,5 @@ Git has a mutable index called stage. Git is so good Linus is god add app.txt file-add google.txt file\ No newline at end of file+add google.txt file+test git diff\ No newline at end of file
Linux系统下,同样这两个文件,同样的内容,同样的操作方式:
可以看到,只是系统和编辑器不同,Windows多出了几行无关的内容(警告信息),并且出现了先删除后添加的情况,所以我猜测是系统和编辑器的不同造成的,如果不是,希望知情的小伙伴可以告诉我真正原因!
回归正题,请注意,git diff
本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。所以有时候你一下子暂存了所有更新过的文件,运行 git diff
后却什么也没有,就是这个原因。
像之前说的,暂存 test.txt
后再修改(自己随便修改一下),可以使用 git status
查看已被暂存的修改或未被暂存的修改。如果我们的环境(终端输出)看起来如下:
$ git add test.txt# 修改test.txt文件$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) modified: readme.txt modified: test.txtChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: test.txt
这里test.txt
出现在了暂存和未暂存的两种状态,现在运行git diff
看暂存前后的变化:
$ git diffwarning: LF will be replaced by CRLF in test.txt.The file will have its original line endings in your working directory # 可能会出现警告信息,请忽略它diff --git a/test.txt b/test.txtindex 117f3a6..940c7b0 100644--- a/test.txt+++ b/test.txt@@ -1,3 +1,4 @@ this is a test file add some file test git diff+# test line
然后用git diff --cached
查看已经暂存起来的变化(--staged
和cached
作用是一样的):
$ git diff --cached# readme.txtdiff --git a/readme.txt b/readme.txtindex 7cc6fe7..bcb9d8f 100644--- a/readme.txt+++ b/readme.txt@@ -4,4 +4,5 @@ Git has a mutable index called stage. Git is so good Linus is god add app.txt file-add google.txt file\ No newline at end of file+add google.txt file+test git diff# test.txt 重点看这里 是不是没有# test line这一行内容diff --git a/test.txt b/test.txtindex 879fceb..117f3a6 100644--- a/test.txt+++ b/test.txt@@ -1,2 +1,3 @@ this is a test file-add some file\ No newline at end of file+add some file+test git diff
这里我们先不提交,因为下面我们就要来讲提交了。
然而并没有!
分析文件差异也可以使用图形化的工具或外部 diff 工具来比较差异,比如DIffMerge,其他工具,自己去找一下。
还可以使用 git difftool
命令来调用 emerge 或 vimdiff 等软件输出 diff 的分析结果。使用 git difftool --tool-help
命令来看你的系统支持哪些 git Diff 插件。git difftool
会依次输出所有文件的分析结果,如果想看某一个文件的diff结果,就加上文件全名,比如:xxx路径下的test.txt,应该写成:git difftool xxx/text.txt
在提交之前,务必确认还有什么已修改或者新建的文件还没有git add
过,否则提交的时候不会记录这些尚未暂存的变化。这些已修改但未暂存的文件只会保留在本地磁盘。所以,每次准备提交前,先用 git status
看下,你所需要的文件是不是都已暂存起来了, 然后再运行提交命令 git commit
:
$ git commit
直接运行该命令,会启动你选择的文本编辑器来输入提交说明,如果不输入提交说明,就会提交失败。
编辑器会显示类似下面的文本信息(默认使用的是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# Changes to be committed:# modified: readme.txt# modified: test.txt## Changes not staged for commit:# modified: test.txt#
可以看到,默认的提交消息包含最后一次运行 git status
的输出,放在注释行里,另外开头还有一个空行,供你输入提交说明。你完全可以去掉这些注释行,不过留着也没关系,多少能帮你回想起这次提交更新的内容有哪些。
更详细的内容修改提示可以用 git commit -v
查看,这会将你所作的更改的 diff 输出呈现在编辑器中,以便让你知道本次提交具体作出哪些修改。
Tip:启动的编辑器是通过 Shell 的环境变量 EDITOR
指定的,一般为 vim 或 emacs。当然也可以 使用 git config --global core.editor
命令设置你喜欢的编辑器。例如:git config --global core.editor vim
另外,你也可以在 git commit
命令后添加 -m
选项,将提交信息与命令放在同一行,如下所示:
$ git commit -m 'commit by xxx'[master c8731ea] commit by xxx 2 files changed, 4 insertions(+), 2 deletions(-)
现在已经进行了一次提交!可以看到,提交后它会告诉你,当前是在哪个分支(master
)提交的,本次提交的完整 SHA-1 校验和(c8731ea
)是什么,以及在本次提交中,有多少文件修订过,多少行添加和删改过。
git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
$ git status # 查看文件状态 ,可以看到test.txt未被暂存On branch masterChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: test.txtno changes added to commit (use "git add" and/or "git commit -a")# 提交未被暂存的文件$ git commit -a -m 'use commit -a -m command to commit'warning: LF will be replaced by CRLF in test.txt.The file will have its original line endings in your working directory[master d1e9096] use commit -a -m command to commit 1 file changed, 1 insertion(+)# 再次查看文件状态$ git statusOn branch masternothing to commit, working tree clean
提交之前不再需要 git add
文件了。这是因为 -a
选项使本次提交包含了所有修改过的文件。这很方便,但是要小心,有时这个选项会将不需要的文件添加到提交中。
要从 git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用 git rm
命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status
时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到:
$ rm test.txt # 从硬盘中删除test.txt文件,见图$ git statusOn branch masterChanges not staged for commit: (use "git add/rm ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) deleted: test.txtno changes added to commit (use "git add" and/or "git commit -a")
然后再运行 git rm
记录此次移除文件的操作:
$ git rm test.txt # 从暂存区和硬盘中删除test.txtrm 'test.txt'$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) deleted: test.txt# 提交,提交之后,上面 deleted 信息就不见了$ git commit -m 'delete test.txt'[master a8de87f] delete test.txt 1 file changed, 4 deletions(-) delete mode 100644 test.txt
提交之后,test.txt
文件就不在纳入版本管理,也就是从仓库删除了。如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f
(译注:即 force 的首字母),否则会报错。这是一种安全特性,用于防止误删尚未添加到快照的数据,强制删除的数据不能被 git 恢复。
另外一种情况是,我们想把文件从 git 仓库中删除(或从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,你想让文件保留在磁盘,但是并不想让 git 继续跟踪。当你忘记添加 .gitignore
文件,不小心把一个很大的日志文件或一堆 .a
这样的编译生成文件添加到暂存区时,这一做法尤其有用。为达到这一目的,使用 --cached
选项:
$ git rm --cached readme.txtrm 'readme.txt'$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) deleted: readme.txtUntracked files: (use "git add ..." to include in what will be committed) readme.txt# 提交$ git commit -m 'delete readme.txt from repository and stage'[master cfef1ea] delete readme.txt from repository and stage 1 file changed, 8 deletions(-) delete mode 100644 readme.txt# 查看文件状态,readme.txt为未跟踪状态,并没有从本地硬盘删除$ git statusOn branch masterUntracked files: (use "git add ..." to include in what will be committed) readme.txtnothing added to commit but untracked files present (use "git add" to track)
git rm
命令后面可以列出文件或者目录的名字,也可以使用 glob
模式(正则表达式)。比如:
$ git rm log/\*.log
此命令删除 log/
目录下扩展名为 .log
的所有文件。类似的比如:
$ git rm \*~
该命令会删除所有名字以 ~
结尾的文件。
要在 git 中对文件改名,可以这么做:
$ git mv file_from file_to
此时查看文件状态信息
# 先修改文件名,比如:把app.txt改为application.txt$ git mv app.txt application.txt$ git statusOn branch masterChanges to be committed: (use "git restore --staged ..." to unstage) renamed: app.txt -> application.txtUntracked files: (use "git add ..." to include in what will be committed) readme.txt# 记得提交一下$ git commit -m 'rename app.txt -> application.txt'
其实,运行 git mv
就相当于运行了下面三条命令:
$ mv app.txt application.txt$ git rm app.txt$ git add application.txt
分开操作,git 也会意识到这是一次重命名,所以不管何种方式结果都一样。两者唯一的区别是,mv
是一条命令而非三条命令,直接用 git mv
方便得多。不过有时候用其他工具批处理重命名的话,要记得在提交前删除旧的文件名,再添加新的文件名。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。