前言
git的基础操作比较简单,之前我也有过基础操作的记录git操作笔记,但是实际使用时会发现,如果只会最基础的使用,就会有很多需求场景都不能满足,甚至会出错了也不知道为什么,因此在基础使用的基础上,还需要更进一步的理解。
关于工作区、暂存区、版本库和远程仓库的理解
git的版本管理,除了branch
和tag
这些外,实际还有工作区、暂存区、本地版本库、远程版本库等概念(有的地方也把我这里说的本地版本库叫对象区,然后对象区加暂存区一起叫版本库,具体这种概念的理解和差异暂时还无法辨别哪种对,但不影响暂时使用上的理解)。
工作区就是当前可以直接编辑的,比如在idea或者什么工具里编辑文件,保存后就是先保存在工作区。
工作区的改动,通过git add
操作可以同步到暂存区。
暂存区的内容,通过git commit
提交到本地版本库。(如果不是第一次提交,可以把add和commit合并操作,即git commit -am "message"
)
本地版本库的内容,通过git push
推送到远程版本库。
工作区
例如我有一个文件tzx.txt
,在文件所在目录使用git init
后,这个文件就会被git管理,在文件所在目录会出现.git
目录,里边存放相关信息。
这时候使用git status
查看,结果如下:
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
tzx.txt
nothing added to commit but untracked files present (use "git add" to track)
上边内容中,On branch master
说明当前所在分支是master
,No commits yet
是说有未提交的内容。Untracked files
说明了当前未提交内容的状态,是存在未跟踪的文件,后边的tzx.txt
列出了这个文件名。同时,在文件名上边也说了可以进行的git操作git add
。
最后一句则类似一个总结,意思是没有可以直接commit
的内容,但是存在没有被跟踪的文件。
结合上边的理解,其实就是说tzx.txt
这个文件现在仅仅存在于工作区,可以使用git add
增加到暂存区中。
暂存区
那么使用git add tzx.txt
操作后再使用git status
查看,结果如下:
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: tzx.txt
那么这里,主要是后边一段,Changes to be committed
意思是存在需要提交的更改,new file: tzx.txt
意思是有新的文件tzx.txt
可以被commit
。use "git rm --cached <file>..." to unstage
这一句,则是指除了commit
之外还可以进行的操作,实际就是从暂存区回到工作区。
本地版本库(对象区)
接下来在进行git commit
操作,例如git commit -m "git init"
,再使用git status
查看结果如下:
On branch master
nothing to commit, working tree clean
nothing to commit, working tree clean
,当前没有可以再被提交的内容,即暂存区的内容也提交到了本地版本库,当前状态是工作区、暂存区、本地版本库的信息一致。
远程版本库
至于从本地版本库推送到远程版本库,在开篇链接的git基础操作
中已有记录。
关于git log
git log
对于上边的commit,使用git log
查看日志,结果如下:
commit e84e73795add11ea1c1cc4bce9bf0788bed4981e (HEAD -> master)
Author: tuzongxun <1160569243@qq.com>
Date: Wed Sep 14 20:29:46 2021 +0800
git init
为了更好的演示一些效果,这里多加几个提交,例如:
Author: tuzongxun <1160569243@qq.com>
Date: Wed Sep 14 20:52:01 2021 +0800
git2
commit 891480792069a8168d8fe59032cfbff4156804a0
Author: tuzongxun <1160569243@qq.com>
Date: Wed Sep 14 20:51:30 2021 +0800
git1
commit e84e73795add11ea1c1cc4bce9bf0788bed4981e
Author: tuzongxun <1160569243@qq.com>
Date: Wed Sep 14 20:29:46 2021 +0800
git init
上边的内容,显示了每次commit的id,或者说sha1值,sha1是一种加密算法,这里实际就是为了生成分布式的唯一id。
除了id,还展示了提交人和时间。
pretty
和abbrev-commit
上边的信息很多,但是有时候可能并不需要这么多的信息,就可以指定一些参数来简化输出,例如执行git log --pretty=oneline --abbrev-commit
,输出如下:
d5238e6 (HEAD -> master) git2
8914807 git1
e84e737 git init
上边信息就只展示了id值的前几位和提交时的注释等信息,比没有参数时简洁很多。
git log --graph
和merge --no-ff
除了简化输出,有时候可能需要更直观的展示分支之间的关系,也会常用graph,例如git log --graph
输出如下:
* commit d5238e64666acdec89120603a58238a5ed46a2a7 (HEAD -> master)
| Author: tuzongxun <1160569243@qq.com>
| Date: Wed Sep 14 20:52:01 2021 +0800
|
| git2
|
* commit 891480792069a8168d8fe59032cfbff4156804a0
| Author: tuzongxun <1160569243@qq.com>
| Date: Wed Sep 14 20:51:30 2021 +0800
|
| git1
|
* commit e84e73795add11ea1c1cc4bce9bf0788bed4981e
Author: tuzongxun <1160569243@qq.com>
Date: Wed Sep 14 20:29:46 2021 +0800
git init
这里会看到在git log
的基础上,最左边增加了一条线,由于我这里目前只有master
分支,所以可能看不出效果,那么,这里再创建一个新的分支dev
,然后修改代码后合并到master,步骤如下:
- 在master分支使用
git checkout -b dev
创建并切换到dev
分支; - 修改内容后,
git commit -am “add dev branch”
提交修改; - 使用
git checkout master
切换到master; - 使用
git merge --no-ff dev
合并dev到master。(–no-ff见下文)
然后查看日志,为了信息更简洁,这里采用git log --graph --pretty=oneline --abbrev-commit
,输出如下:
* 6209d36 (HEAD -> master) Merge branch 'dev' no fast forward
|\
| * 3e6801b (dev) add dev branch
|/
* d5238e6 git2
* 8914807 git1
* e84e737 git init
从上边的内容中可以很明显的看到,在master
上先有三个提交,分别是e84e737
、8914807
、d5238e6
。
然后在d5238e6
这个点创建了dev
分支,然后在dev
上有了新的提交3e6801b
。
然后在3e6801b
之后,dev
合并到了master
上,并且有了一个新的id值6209d36
。
那么这里其实需要着重说一下merge
的--no-ff
,为了进一步说明,这里回到dev
分支修改文件内容后再做一次提交,然后再合并到master
,不同的是,这一次不要--no-ff
参数,步骤如下:
- 使用
git checkout dev
切换回dev
; - 修改
tzx.txt
文件后,使用git commit -am "update dev content"
提交; - 使用
git checkout master
切换回master
; - 使用
git merge dev
合并dev
到master
。
然后查看日志,结果如下:
* d553853 (HEAD -> master) ierge branch 'dev'
|\
| * ca381cd (dev) update dev content
* | 6209d36 Merge branch 'dev' no fast forward
|\|
| * 3e6801b add dev branch
|/
* d5238e6 git2
* 8914807 git1
* e84e737 git init
上边的内容中,也可以看到,在6209d36
之后,dev
分支上有了一个新的提交ca381cd
,然后把dev
又合并到了master
。
但是这里依然不能说明--no-ff
的作用,因此我这里回到master
再创建一个新的分支sit
,然后修改提交后,再把sit
合并到master
,不使用--no-ff
参数,步骤如下:
- 在master上使用
git checkout -b sit
创建并切换到sit
分支; - 修改
tzx.txt
的内容后,使用git commit -am "add sit branch"
提交; - 使用
git checkout master
切换回master
; - 使用
git merge sit
合并sit
到master
.
然后再查看日志,结果如下:
* ef5b082 (HEAD -> master, sit) add sit branch
* d553853 ierge branch 'dev'
|\
| * ca381cd (dev) update dev content
* | 6209d36 Merge branch 'dev' no fast forward
|\|
| * 3e6801b add dev branch
|/
* d5238e6 git2
* 8914807 git1
* e84e737 git init
这个时候就会看到,ef5b082
这一次的提交,明明是在sit
分支上提交的,但是现在却显示在master
上。
同时,之前dev
合并到master
时,会生成一个新的id,而这里没有生成。
那么这里其实一定程度上展示了--no-ff
的作用,也就是当我们使用过--no-ff
,后续相应分支的合并后就会在合并后的分支保留被合并分支相关的信息,同时会在合并后有一个新的记录。
而如果没有用过这个参数,合并后就不会在合并后的分支中保留原来的分支信息,并且合并后也不会生成新的id记录。
这里的ff
实际上是fast forward
的意思,翻译过来就是快进。
也就是说,git merge
默认情况下是fast forward
的,不会在合并后的分支中保留被合并的分支信息,如果要保留,就需要使用或者使用过--no-ff
参数。