0.留影-打tag
$ git tag -m "say goodbye to all previous practice" ol_practice
$ ls ./git/refs/tags/ol_practice
ls: cannot access './git/refs/tags/ol_practice': No such file or directory
$ ls .git/refs/tags/ol_practice
.git/refs/tags/ol_practice
$ git rev-parse refs/tags/ol_practice
c972a74532c1ef9827473139b0fc8550eb74ee02
$ git describe
ol_practice
1.删除文件
查看版本库的状态,暂存区和工作区都包含修改
$ git status -s
A hack-1.txt
M welcome.txt
为了介绍不同的删除方法,先保存下进度git stash,恢复进度不要使用git stash pop,而是使用git stash apply,因为这个保存的进度要被多次用到
$ git stash
Saved working directory and index state WIP on master: 19d2c13 welcome txt
HEAD is now at 19d2c13 welcome txt
$ git stash apply
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: hack-1.txt
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: welcome.txt
1.1本地删除不是真的删除
当前工作区的文件有:
$ ls
abc.txt detached-commit.txt hack-1.txt new-commit.txt welcome.txt
直接在工作区删除这些文件
$ rm *.txt
通过以下命令,可以看到在暂存区(版本库)中的文件仍然存在,并未删除
$ git ls-files
abc.txt
detached-commit.txt
hack-1.txt
new-commit.txt
welcome.txt
从文件的状态来看,文件只是在本地删除了,尚未添加到暂存区(提交任务)中
直接在工作区删除,对暂存区和版本库没有任何影响
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: hack-1.txt
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: abc.txt
deleted: detached-commit.txt
deleted: hack-1.txt
deleted: new-commit.txt
deleted: welcome.txt
本地删除 如果想反映在暂存区中应该使用git rm命令,对不想删除的文件执行 git checkout -- <file>,可以让文件在工作区重现
1.2 执行git rm 命令删除文件
$ git rm detached-commit.txt detached-commit.txt abc.txt hack-1.txt new-commit.txt welcome.txt
rm 'abc.txt'
rm 'detached-commit.txt'
rm 'hack-1.txt'
rm 'new-commit.txt'
rm 'welcome.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: abc.txt
deleted: detached-commit.txt
deleted: new-commit.txt
deleted: welcome.txt
$ git commit -m "delete trash files.(useing:git rm)"
[master fbd915b] delete trash files.(useing:git rm)
4 files changed, 1 deletion(-)
delete mode 100644 abc.txt
delete mode 100644 detached-commit.txt
delete mode 100644 new-commit.txt
delete mode 100644 welcome.txt
可以通过下面命令查看历史版本的文件列表
$ git ls-files --with-tree=HEAD^
abc.txt
detached-commit.txt
new-commit.txt
welcome.txt
也可以查看在历史版本中尚在的删除文件的内容
$ git cat-file -p HEAD^:abc.txt
111
1.3命令git add -u快速标记删除
1)丢弃之前测试删除的实验性提交
$ git reset --hard HEAD^
HEAD is now at 19d2c13 welcome txt
2)恢复保存的进度(参数 -q 使得命令进去安静模式)
$ git stash apply -q
3)然后删除本地文件,状态显示出依然只是在本地删除了文件,暂存区中的文件仍在
$ rm *.txt
$ git status -s
D abc.txt
D detached-commit.txt
AD hack-1.txt
D new-commit.txt
D welcome.txt
4)执行 git add -u 命令可以将(被版本库追踪的)本地文件的变更(修改、删除)全部记录到暂存区中
$ git add -u
5)查看状态,工作区删除的文件全部被标记为下次提交时删除
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: abc.txt
deleted: detached-commit.txt
deleted: new-commit.txt
deleted: welcome.txt
6)执行提交,删除文件
$ git commit -m "delete trashj file.(using: git add -u)"
[master 4107309] delete trashj file.(using: git add -u)
4 files changed, 1 deletion(-)
delete mode 100644 abc.txt
delete mode 100644 detached-commit.txt
delete mode 100644 new-commit.txt
delete mode 100644 welcome.txt
2.恢复删除的文件
为了说明文件移动,现在恢复一个删除的文件。执行了文件删除并提交,只是在最新的提交中删除了文件,历史提交中仍然保留,可以从历史提交中提取文件。
从历史(前一次提交)中恢复welcome.txt,如下三条命令等价:
$ git cat-file -p HEAD~1:welcome.txt>welcome.txt
$ git show HEAD~1:welcome.txt>welcome.txt
$ git checkout HEAD~1 -- welcome.txt
执行 git add -A 命令会将工作区中的所有改动以及新增文件添加到暂存区,
执行下面的命令,将恢复过来的welcome.txt文件添加回暂存区
$ git add -A
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: welcome.txt
执行提交操作,文件welocme.txt又回来了
$ git commit -m "restore file:welcome.txt"
[master 2c5da85] restore file:welcome.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 welcome.txt
但Subversion如果这样操作会有严重的副作用-文件变更历史被认为的割裂,而且还会造成服务器存储空间的浪费。
Git通过添加方式反删除文件没有副作用,因为在git版本库中相同内容的文件保存在一个blob对象中,即便是内容不同的blob对象通过对象库打包也会进行存储优化。
3.移动文件
通过将welcome.txt改名为README文件来测试一下在git中如何移动文件
git提供了 git mv 命令完成改名操作
$ git mv welcome.txt README
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: welcome.txt -> README
提交改名操作,在提交输出中可以看到改名前后两个文件的相似度(百分比)
$ git commit -m "改名测试"
[master a9904c2] 改名测试
1 file changed, 0 insertions(+), 0 deletions(-)
rename welcome.txt => README (100%)
从提交日志中出现的文件相似度可以看出,git改名操作得益于git对文件追踪的强大支持(文件内容作为blob对象保存在对象库中)
改名操作相当于对旧文件执行删除,对新文件执行添加。
可以用git rm 和 git add 代替git mv
撤销之前测试文件移动的提交
$ git reset --hard HEAD^
HEAD is now at 2c5da85 restore file:welcome.txt
$ git status
On branch master
nothing to commit, working directory clean
$ git ls-files
welcome.txt
新的改名操作不使用git mv命令,而是直接在本地改名(文件移动),将welcome.txt改名为README
$ mv welcome.txt README
$ git status -s
D welcome.txt
?? README
再修改一下改名后的README文件
$ echo "bye-bye">>README
可以使用前面介绍的 git add -A命令,相当于对修改文件执行 git add,对删除文件执行 git rm,对本地新增文件执行 git add
$ git add -A
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
deleted: welcome.txt
$ git commit -m "README is from welcome.txt"
[master 631d7aa] README is from welcome.txt
2 files changed, 1 insertion(+)
create mode 100644 README
delete mode 100644 welcome.txt
4.一个显示版本号的hello world
$ git describe
ol_practice-3-g631d7aa
当前工作区的版本是“留影”后的第三个版本,提交ID是 g631d7aa在提交日志中显示提交对应的里程碑(tag),参数 --decorate 可以在提交ID的旁边显示该提交关联的引用(里程碑或分支)
$ git log --oneline --decorate -4
631d7aa (HEAD -> master) README is from welcome.txt
2c5da85 restore file:welcome.txt
4107309 delete trashj file.(using: git add -u)
19d2c13 (tag: ol_practice) welcome txt
4.使用 git add -i 选择性添加
执行 git add -i 命令,进入一个交互式界面,显示了命令列表,可以使用数字或者加亮显示的命令首字母,选择相应的功能
$ git add -i
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
需要将新文件加入到版本库,所以选择4
What now> 4
1: src/Makefile
2: src/main.c
3: src/version.h.in
Add untracked>>
Add untracked>> 2
1: src/Makefile
* 2: src/main.c
3: src/version.h.in
Add untracked>> 3
1: src/Makefile
* 2: src/main.c
* 3: src/version.h.in
Add untracked>>
在"add untracked'处按回车键,完成文件添加,返回主界面
Add untracked>>
added 2 paths
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
此时输入1查看状态,可以看到两个文件添加到暂存区中。
输入7退出交互界面
What now> 1
staged unstaged path
1: +9/-0 nothing src/main.c
2: +5/-0 nothing src/version.h.in
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 7
Bye.
查看文件状态,可以发现两个文件被添加到暂存区中
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: main.c
new file: version.h.in
Untracked files:
(use "git add <file>..." to include in what will be committed)
Makefile
$ git commit -m "hello world initiallized"
[master 0642531] hello world initiallized
2 files changed, 14 insertions(+)
create mode 100644 src/main.c
create mode 100644 src/version.h.in
$ git tag -m "set tag hello_1.0" hello_1.0
5.文件忽略
$ git status -s
?? Makefile
执行下面的命令可以在这个目录下创建一个名为.gitignore的文件,把这些需要忽略的文件写在其中,文件名可以使用通配符
$ cat > .gitignore<<EOF
> Makefile
> EOF
看看写好的.gitignore文件,每个要忽略的文件显示在一行(可以在忽略中忽略自己)
$ cat .gitignore
Makefile
.gitignore
再来看看当前工作区的状态
$ git status -s
5.1文件.gitignore可以放在任何目录中,作用范围是其所处的目录及其子目录(仍位于工作区中)
5.2 忽略文件有错误,后果很严重
$ cat .gitignore
.gitignore
*.do
$ echo "ababab" > yin.do
$ ls
aa.do main.c Makefile.do Makefile1.do version.h.in yin.do
在工作区状态显示中看不到yin.do文件
$ git status
On branch master
nothing to commit, working directory clean
$ git status --ignored
On branch master
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
../.gitignore
Makefile.do
Makefile1.do
aa.do
yin.do
要添加yin.do 文件,使用 git add -A和 git add .都失效,无法用这两个命令将yin.do添加到暂存区中
$ git add .
$ git add -A
$ git status
On branch master
nothing to commit, working directory clean
只有在添加操作的命令中明确写入文件名,并且提供 -f 参数才能真正添加
$ git add -f yin.do
$ git commit -m "add yin.do"
[master a1158c1] add yin.do
1 file changed, 1 insertion(+)
create mode 100644 src/yin.do
5.3忽略只对未跟踪文件有效,对于已加入版本库中的文件无效
文件yin.do添加到版本库中,就不再受到.gitignore设置的文件忽略所影响了,对于该文件的修改立刻被跟踪到
$ echo "/* end */" >> yin.do
$ 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: yin.do
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m "偷懒了,直接使用-a参数直接提交"
[master fece0be] 偷懒了,直接使用-a参数直接提交
1 file changed, 1 insertion(+)
5.4本地独享式忽略文件
文件.gitignore设置的文件忽略是共享式的,.gitignore被添加到版本库后成为版本库的一部分,当版本库共享给他人,或把版本库推送给(push)到服务器时,
这个忽略文件就会出现在他人的工作区中,文件忽略在他人的工作区中同样生效
独享式忽略不会因为版本库共享,或者版本库之间的推送传递给他人的文件忽略,有两种方式:
1)针对具体版本库的,在.git/info/exclude来设置文件忽略
2)全局式的忽略,通过配置变量core.excludesfile指定一个忽略文件,其设置的忽略对所有本地版本库均有效
5.4git忽略语法
1.忽略文件中的空行或以#开始的行会被忽略
2.可以使用通配符
3.如果名称的最前面是一个路径分隔符(/),表明要忽略的文件在此目录下,而非子目录的文件
4.如果名称的最后面是一个路径分隔符(/),表明要忽略的是整个目录,同名文件不忽略,否则同名的文件和目录都忽略
5.通过在名称的最前面添加一个!,代表不忽略
# 这是注释行 --被忽略
*.a #忽略所有以.a为扩展名的文件
!lib.a #但是lib.a文件或者目录不要忽略,即使前面设置了对*.a的忽略
/TODO #只是忽略此目录下的TODO文件,子目录的TODO文件不忽略
build/ #忽略所有build/目录下的文件
doc/*.txt #忽略文件如 doc/nortes.txt,但是文件如doc/server/arch.txt不被忽略
6.文件归档
如果使用压缩工具(tar、zip、rar等)将工作区文件归档,一不小心会把版本库(.git目录)包含其中,甚至将工作区中的忽略文件/临时文件也包含其中
git提供了一个归档命令
1.基于最新提交建立归档文件lastest.zip
$ git archive -o lastest.zip HEAD
2.只将src 和 doc建立到归档 partical.tar中
$ git archive -o partical.tar HEAD src doc