目录
Git
原文参考:Git教程 - 廖雪峰的官方网站 (liaoxuefeng.com)
安装
官网下载并安装:Git (git-scm.com)
初始化
配置
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
创建版本库
$ git init
添加文件
$ git add readme.txt
提交文件
$ git commit -m "wrote a readme file"
[master (root-commit) fe7b7c8] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
表示1个文件改动,插入了两行内容。
时光穿梭
修改 readme.txt 文件内容。
查看状态:
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
查看修改内容:
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 0065b6f..0a30af0 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is a free software.
\ No newline at end of file
提交修改和提交新文件:
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt
$ git commit -m "add distributed"
[master 6acc42c] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
再次查看状态:
$ git status
On branch master
nothing to commit, working tree clean
版本回退
修改 readme.txt 文件内容。然后提交:
$ git add readme.txt
$ git commit -m "append GPL"
[master 44b82d4] append GPL
1 file changed, 1 insertion(+), 1 deletion(-)
查看历史修改记录:
$ git log
commit 44b82d4e6b1e2e933502f5ee678a0d4ee43082ce (HEAD -> master)
Author: meyok <[email protected]>
Date: Thu Aug 17 10:07:40 2023 +0800
append GPL
commit 6acc42c05900a665eef1c83c39daa578a1e68425
Author: meyok <[email protected]>
Date: Thu Aug 17 09:56:22 2023 +0800
add distributed
commit fe7b7c802c3e5a5f9490df0b7cab2b5978fb96ec
Author: meyok <[email protected]>
Date: Thu Aug 17 09:46:48 2023 +0800
wrote a readme file
简化输出信息可以添加参数--pretty=oneline
:
$ git log --pretty=oneline
44b82d4e6b1e2e933502f5ee678a0d4ee43082ce (HEAD -> master) append GPL
6acc42c05900a665eef1c83c39daa578a1e68425 add distributed
fe7b7c802c3e5a5f9490df0b7cab2b5978fb96ec wrote a readme file
在 Git 中,HEAD 表示当前版本,HEAD^、HEAD^^……表示上个版本、上上个版本……。更早的版本可以使用~
连接,如 HEAD~100 表示往上100个版本。
回退版本:
$ git reset --hard HEAD^
HEAD is now at 6acc42c add distributed
注意:windows 下 cmd 中,^会被作为换行符,直接使用以上命令会询问 more,可在 HEAD^打引号解决。
再次查看信息:
$ git log
commit 6acc42c05900a665eef1c83c39daa578a1e68425 (HEAD -> master)
Author: meyok <[email protected]>
Date: Thu Aug 17 09:56:22 2023 +0800
add distributed
commit fe7b7c802c3e5a5f9490df0b7cab2b5978fb96ec
Author: meyok <[email protected]>
Date: Thu Aug 17 09:46:48 2023 +0800
wrote a readme file
回到最新的版本:
$ git reset --hard 44b82
HEAD is now at 44b82d4 append GPL
版本号不用写全。
查看使用的命令:
$ git reflog
44b82d4 (HEAD -> master) HEAD@{0}: reset: moving to 44b82
6acc42c HEAD@{1}: reset: moving to HEAD^
44b82d4 (HEAD -> master) HEAD@{2}: commit: append GPL
6acc42c HEAD@{3}: commit: add distributed
fe7b7c8 HEAD@{4}: commit (initial): wrote a readme file
使用该命令可查看遗忘的新版本号。
工作区与版本库
- 工作区(Working Directory):就是除.git 外的文件。
- 版本库(Repository):即.git。
- 暂存区(stage/index)
- 自动创建的第一个分支(master)
- 指向 master 的分支(HEAD)
git add
就是把文件添加到暂存区,git commit
就是把暂存区的所有内容添加到当前分支。
现在添加 readme.txt 内容,新增 LINCENSE 文件。查看状态:
$ git status
On branch master
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: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LISENCE
no changes added to commit (use "git add" and/or "git commit -a")
add 后再次查看状态:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: LISENCE
modified: readme.txt
提交:
$ git commit -m "understand how stage works"
[master 4720a4e] understand how stage works
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 LISENCE
管理修改
修改 readme.txt 文件内容并添加到暂存区,查看状态:
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt
再次修改 readme.txt 文件内容并提交,查看状态:
$ git commit -m "git tracks changes"
[master f283c62] git tracks changes
1 file changed, 2 insertions(+), 1 deletion(-)
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
文件里内容修改,与暂存区中的不一致时,对应行会显示。
文件与当前分支不一样时,文件名旁边会显示。
- A:add,新增文件并add。
- M:modified,修改。
- U:untracked,未add。
- D:delete,删除文件。
查看工作区和版本库中最新版本区别:
$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 2b2efac..aec053b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
Git is a distributed version control system.
Git is a free software under the GPL.
Git has a mutable index called stage.
-Git tracks change.
\ No newline at end of file
+Git tracks changes of files.
\ No newline at end of file
现在提交新修改。
撤销修改
修改 readme.txt 文件内容。
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
撤销修改:
$ git checkout -- readme.txt
该命令把该文件在工作区的修改全部撤销,有两种情况:
- 工作区修改后未放到暂存区,撤销回版本库。
- 工作区修改后已放到暂存区,然后又有修改,撤销回暂存区。
修改 readme.txt 文件内容并提交到暂存区。
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt
撤销暂存区修改:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
$ git status
On branch master
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: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout -- readme.txt
$ git status
On branch master
nothing to commit, working tree clean
删除文件
新建文件 test.txt 并添加到版本库,随后删除,查看状态:
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
现在有两个选择:
-
从版本库中删除该文件并提交:
$ git rm test.txt
rm 'test.txt'
$ git commmit -m "remove test.txt"
[master f3f9d12] remove test file 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test.txt
-
撤销删除:
$ git checkout -- test.txt
远程仓库
Git 是分布式的,每个仓库都可作为中心仓库。但现在实现模式是有一个仓库充当服务器,其他的都从其上拉取、提交。
本地仓库与Github之间传输通过 SSH 加密,本地需要创建 SSH key:
$ ssh-keygen -t rsa -C "youremail"
添加远程库
在 Github 上创建远程库 learngit。
链接远程库:
git remote add origin [email protected]:MeYokYang/learngit.git
origin 是远程库的名字,可以换成别的。
推送本地库内容到远程库上:
git push -u origin master
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 8 threads
Compressing objects: 100% (18/18), done.
Writing objects: 100% (22/22), 1.84 KiB | 940.00 KiB/s, done.
Total 22 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
To github.com:MeYokYang/learngit.git
* [new branch] master -> master
branch 'master' set up to track 'origin/master'.
由于远程库是空的,第一次推送 master 分支时,加上了 -u 参数,git 不仅会把本地 master 分支内容推送到远程库 master 分支上,还会把本地 master 分支与远程库 master 分支关联,以后推送或拉取时就可以简化命令。
从现在起,只要本地做了提交,就可以通过以下命令将 master 分支内容推送到远程库上:
$ git push origin master
查看远程库信息:
$ git remote -v
origin [email protected]:MeYokYang/learngit.git (fetch)
origin [email protected]:MeYokYang/learngit.git (push)
删除远程库关联:
$ git remote rm origin
从远程库克隆
在 Github 上创建远程库 gitskills,选择创建 README 文件。现在从远程库克隆一个本地库:
$ git clone [email protected]:MeYokYang/gitskills.git
除了使用 ssh,也可以使用 https,除了速度慢,每次推送也必须输入口令。
分支管理
每次提交,Git 都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在 Git 里,这个分支叫主分支(master)。HEAD 严格不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当期分支。
一开始的时候,master 分支是一条线,Git 用 master 指向最新的提交,再用 HEAD 指向 master,就能确定当前分支,以及当前分支的提交点:
每次提交,master 分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当我们创建新的分支,例如 dev 是,Git 新建了一个指针叫 dev,指向 master 相同的提交,再把 HEAD 指向 dev,就表示当前分支在 dev 上:
从现在开始,对工作区的修改和提交就是针对 dev 分支了,比如新提交一次后,dev 指针往前移动一步,而 master 指针不变:
假如我们在 dev 上的工作完成了,就可以把 dev 合并到 master 上:
合并完分支后,甚至可以删除 dev 分支:
创建 dev 分支并切换:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout
加上-b
参数表示创建并切换,相当于以下两条命令:$ git branch dev $ git checkout dev
查看当前分支:
$ git branch
* dev
master
在 dev 分支上修改 readme.txt 文件并提交:
$ git add readme.txt
$ git commmit -m "branch test"
[dev d5a0924] branch test
1 file changed, 2 insertions(+), 1 deletion(-)
切换回 master 分支:
$ git checkout master
把 dev 分支的工作成果合并到 master 分支上:
$ git merge dev
Updating f3f9d12..d5a0924
Fast-forward
readme.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
该合并属于快速合并(Fast-forward),是直接把 master 指向 dev 的当前提交。
删除 dev 分支:
$ git branch -d dev
Deleted branch dev (was d5a0924).
$ git branch
* master
解决冲突
创建新的分支 feature1 并修改 readme.txt 文件提交。转回 master 分支修改 readme.txt 文件提交。
这种情况下,Git 无法执行快速合并:
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD
Creating a new branch is quick and simple.
=======
Creating a new branch is quick & simple.
>>>>>>> feature1
修改冲突内容,然后重新提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master a781606] conflict fixed
现在,分支变成了这样:
查看分支情况:
$ git log --graph --pretty=oneline --abbrev-commit
* a781606 (HEAD -> master) conflict fixed
|\
| * 9d31729 (feature1) add & simple
* | cee82ab add and simple
|/
* d5a0924 branch test
* f3f9d12 (origin/master) remove test file
* aefaa32 add test file
* bb3ccbd modified twice commit
* f283c62 git tracks changes
* 4720a4e understand how stage works
* 44b82d4 append GPL
* 6acc42c add distributed
* fe7b7c8 wrote a readme file
最后删除 feature1分支。
分支管理策略
禁用 Fast-forward 模式合并,Git 就会在 merge 时生成一个新的 commit,通过使用--no-ff
参数。
$ git merge --no-ff -m "merge with no-ff" dev
比如新建 dev 分支后,修改内容提交,切回 master 分支并合并,分支就会像以下这样:
分支策略
- master:应该是稳定的,用来发布新版本,平时不能在上面干活。
- dev:在此上干活,完成后合并到 master 上。
- 个人:每个人都有个人的分支,时不时向 dev 上合并。
使用--no-ff
可以看出有过合并历史。
Bug分支
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
假如接到一个修复一个代号101的bug的任务时,需要创建一个 issue-101 分支来修复它。
如果当前分支上的工作没有提交但又不想提交,可使用 stash 功能:
$ git stash
Saved working directory and index state WIP on master: a781606 conflict fixed
随后,在有 bug 的分支上创建 issue-101 分支,修复完成后,切换到原来有 bug 的分支并合并,删除 issue-101 分支。回到原来工作的分支,使用以下命令查看原来的工作现场:
$ git stash list
stash@{0}: WIP on master: a781606 conflict fixed
恢复工作现场有以下两种命令:
-
git stash apply
恢复后,stash内容并不删除,你需要用
git stash drop
来删除。可使用git stash apply stash@{0}
指定恢复那个工作现场 -
git stash pop
恢复的同时把stash内容也删了
如果有 bug 的分支和工作分支上有同样的 bug,可以将在有 bug 的分支上做的修复提交在工作分支上进行一次就行,使用git cherry-pick
:
$ git cherry-pick 4c805e2
Feature分支
与 bug 分支相似,只是用于开发新功能的分支,代码类似。
多人协作
推送分支:
$ git push origin dev
但是,并不是一定要把本地分支往远程推送:
- master 分支是主分支,因此要时刻与远程同步。
- dev 分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步。
- bug 分支只用于在本地修复 bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个 bug。
- feature 分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
Rebase
pull 下来有冲突的分支,解决后,合并提交会变成分支,再 push 会乱,可通过 rebase 重新修改分支路线。例如
本地分支:
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello
pull 下来后,解决冲突后的分支:
* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/
* d1be385 init hello
再输入git rebase
,分支变为:
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
标签管理
tag 也是版本库的快照,其实它就是指向某个commit的指针,与分支不同的是,他不可移动。
创建标签
在对应 master 分支上,使用git tag <name>
:
$ git tag v1.0
查看所有标签:
$ git tag
在某个对应版本号上打标签:
$ git tag v0.9 f52c633
标签不是按时间顺序列出,而是字母。
可以用git show <tagname>
查看标签信息。
还可以创建带有说明的标签,用-a
指定标签名,-m
指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
操作标签
删除标签:
$ git tag -d v0.1
推送某个标签到远程:
$ git push origin v1.0
或者,一次性推送全部尚未推送到远程的本地标签:
$ git push origin --tags
如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除,然后,从远程删除:
$ git tag -d v0.9
$ git push origin :refs/tags/v0.9
自定义 Git
让Git显示颜色,会让命令输出看起来更醒目:
git config --global color.ui
忽略特殊文件
在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如 Java 编译产生的
.class
文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
有时想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore
忽略了,可添加参数-f
:
$ git add -f App.class
或者你发现,可能是.gitignore
写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore
命令检查:
$ git check-ignore -v App.class
把指定文件排除在.gitignore
规则外的写法就是!
+文件名,所以,只需把例外文件添加进去即可:
# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class
# 不排除.gitignore和App.class:
!.gitignore
!App.class
配置别名
我们只需要敲一行命令,告诉Git,以后st
就表示status
:
$ git config --global alias.st status
好了,现在敲git st
看看效果。
甚至还有人丧心病狂地把lg
配置成了:
$ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
来看看git lg
的效果:
配置 Git 的时候,加上--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。每个仓库的 Git 配置文件都放在.git/config
文件中。而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中。
搭建 Git 服务器
在远程仓库一节中,我们讲了远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。
GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。
搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt
命令就可以完成安装。
假设你已经有sudo
权限的用户账号,下面,正式开始安装。
第一步,安装git
:
$ sudo apt-get install git
第二步,创建一个git
用户,用来运行git
服务:
$ sudo adduser git
第三步,创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub
文件,把所有公钥导入到/home/git/.ssh/authorized_keys
文件里,一行一个。
第四步,初始化Git仓库:
先选定一个目录作为Git仓库,假定是/srv/sample.git
,在/srv
目录下输入命令:
$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git
结尾。然后,把owner改为git
:
$ sudo chown -R git:git sample.git
第五步,禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd
文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git
用户可以正常通过ssh使用git,但无法登录shell,因为我们为git
用户指定的git-shell
每次一登录就自动退出。
第六步,克隆远程仓库:
现在,可以通过git clone
命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.
剩下的推送就简单了。
如果团队很小,把每个人的公钥收集起来放到服务的/home/git/.ssh/authorized_keys
文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。
这里我们不介绍怎么玩Gitosis了,几百号人的团队基本都在500强了,相信找个高水平的Linux管理员问题不大。
有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。
这里我们也不介绍Gitolite了,不要把有限的生命浪费到权限斗争中。
其他
刷新.gitignore
$ git rm -r --cache .
$ git add .
$ git commit -m "update .gitignore"
git commit 书写规范
commit message 格式:
<type>(<scope>): <subject>
type(必须):用于说明git commit的类别,只允许使用下面的标识。
- feat:新功能(feature)。
- fix/to:修复bug,可以是QA发现的BUG,也可以是研发自己发现的BUG。
- fix:产生diff并自动修复此问题。适合于一次提交直接修复问题
- to:只产生diff不自动修复此问题。适合于多次提交。最终修复问题提交时使用fix
- docs:文档(documentation)。
- style:格式(不影响代码运行的变动)。
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)。
- perf:优化相关,比如提升性能、体验。
- test:增加测试。
- chore:构建过程或辅助工具的变动。
- revert:回滚到上一个版本。
- merge:代码合并。
- sync:同步主线或分支的Bug。
scope(可选):scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。例如在Angular,可以是location,browser,compile,compile,rootScope, ngHref,ngClick,ngView等。如果你的修改影响了不止一个scope,你可以使用*代替。
subject(必须):subject是commit目的的简短描述,不超过50个字符。建议使用中文(感觉中国人用中文描述问题能更清楚一些)。结尾不加句号或其他标点符号。
根据以上规范git commit message将是如下的格式:
fix(DAO):用户查询缺少username属性
feat(Controller):用户查询接口开发
以上就是我们梳理的git commit规范,这样规范git commit到底有哪些好处:
- 便于程序员对提交历史进行追溯,了解发生了什么情况。
- 一旦约束了commit message,意味着我们将慎重的进行每一次提交,不能再一股脑的把各种各样的改动都放在一个git commit里面,这样一来整个代码改动的历史也将更加清晰。
- 格式化的commit message才可以用于自动化输出Change log。