git commit命令详解:优雅的提交
- 一、git commit 的基础
- 1.1、git commit命令详解
- 1.2、git commit的格式
- 1.3、git的commitizen
- 1.4、推送到远程分支
- 1.5、git push和冲突解决
- 二、git commit合并
- 三、修改commit的内容
- 3.1、修改自己的提交
- 3.2、修改任意提交的message
- 四、查看commit的内容
- 五、总结
一、git commit 的基础
在 Git 中,"提交"是一个指代对文件更改进行记录的操作。每次提交都为当前项目的状态创建一个新的快照。提交的主要目的是让开发者可以在需要时查看、恢复或比较项目的历史版本。
Git 将每次提交视为项目在某一时刻的完整快照,而不是差异。每次提交保存的是当前项目的所有文件的状态,当你查看历史提交时,你可以看到当时的文件内容。快照使 Git 能够高效地管理各个版本的文件。
版本控制是管理文件变更的一种系统。在软件开发中,版本控制允许团队协作,追踪和记录每一次的更改。使用 Git 进行版本控制,可以实现以下目标:
- 协作:多位开发者可以同时对代码进行更改,并通过合并提交来整合这些更改。
- 历史记录:可以随时查看项目的变更历史,了解每次提交的内容、时间和作者。
- 恢复:在出现问题时,可以快速恢复到先前的某个版本。
- 分支管理:Git 允许创建分支并在不同的分支上进行开发,后续再将更改合并回主干。
通过这些特性,Git commit 成为代码管理和版本控制中不可或缺的一部分。每次提交都带有唯一的标识符(SHA-1 哈希值),可以确保每个快照的唯一性和可追踪性。
1.1、git commit命令详解
git commit file1.name file2.name file3.name .. –m "commit messages"
commit
指提交修改到本地的仓库里,file*.name
指的是带commit
的文件 –m
后面的内容指提交的信息,即备注。
git commit –a –m "commit messeages"
添加的-a
参数会把当前暂存区里所有的修改(包括删除操作)都提交,但是那些尚未添加到暂存区的内容是不会提交的,网上有很多人说-a
参数会把尚未add
的文件也提交了,这个说法是错误的。
git commit
可能有时候手抖忘记输入-m
参数,直接输入了git commit
,于是出现了下面这个界面,即打开了一个vim
编辑界面,敲入i
键后保存,输入要添加的message
后,输入“ESC
”按键退出编辑界面,然后再敲入“:wqa
”后会保存message
内容,并且提交此次修改,如果敲入“:q
”会取消这次提交。
git commit --amend
这也是我们经常用的命令,他会把此次提交追加到上一次的commit
内容里。
1.2、git commit的格式
参考Angular 团队的规范。
message
的格式:
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer>
标题行: 必填, 描述主要修改类型和内容。
主题内容: 描述为什么修改, 做了什么样的修改, 以及开发的思路等等。
页脚注释: 放 Breaking Changes 或 Closed Issues。
type
是指:
feat
: 新特性。fix
: 修改问题。refactor
: 代码重构。docs
: 文档修改。style
: 代码格式修改,注意不是 css 修改。test
: 测试用例修改。chore
: 其他修改,比如构建流程,依赖管理。
scope
:commit
影响的范围,即影响的模块或者组件,比如: route, component, utils, build...
。
subject
:commit
的概述, 建议符合 50/72 formatting。
body
:commit
具体修改内容, 可以分为多行, 建议符合 50/72 formatting 。
footer
: 一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接,或者feature等等其余的信息.
使用git commit
模板来规范提交:
-
在
~/.gitconfig
文件里添加:[commit] template=~/.gitmessage
-
添加
~/.gitmessage
文件。
1.3、git的commitizen
-
下载对应版本的
nodejs
包(https://nodejs.org/en/download/),并安装。 -
使用
npm
工具进行全局安装:npm install commitizen -g
-
然后在项目目录里,运行下面命令,使其支持 Angular 的 Commit message 格式:
commitizen init cz-conventional-changelog --save --save-exact
以后,凡是用到
git commit
命令,一律改用git cz
,这时候就会出现选项,来生成符合规范的commit message
。 -
如果希望每个使用
git
的项目都遵循这个标准,可以使用下面命令进行全局设置安装cz-conventional-changelog
:npm install -g cz-conventional-changelog
-
创建一个
.czrc
文件在你的home
目录,并将path
指向上面所安装的commitizen
适配器,echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
-
现在可以在每个 git 项目中使用
git cz
提交我们的 commit message 了,当然我们还可以配置Commitlint
做自动检测,检查不通过的可以拒绝提交,比较绝吧。 -
如果所有的commit信息都是按照这个格式填写的,在发布版本时就可以使用以下命令生成
changelog
了。conventional-changelog -p angular -i CHANGELOG.md -s
1.4、推送到远程分支
git push
命令用于将本地分支的更新,推送到远程主机。它的格式与git pull
命令相仿。
git push <远程主机名> <本地分支名>:<远程分支名>
注意,分支推送顺序的写法是<来源地>:<目的地>
,所以git pull
是<远程分支>:<本地分支>
,而git push
是<本地分支>:<远程分支>
。例如:
git push origin master:refs/for/master
如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
git push origin master
上面命令表示,将本地的master
分支推送到origin
主机的master
分支。如果后者不存在,则会被新建。
如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。
git push origin :master # 等同于 git push origin --delete master
上面命令表示删除origin
主机的master
分支。
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。
git push origin
上面命令表示,将当前分支推送到origin
主机的对应分支。
如果当前分支只有一个追踪分支,那么主机名都可以省略。
git push
1.5、git push和冲突解决
git push
的时候如果有冲突,会显示如下,此时必须去修复这个冲突。
首先调用git pull
去拉取分支下来,然后会在冲突的文件里记录冲突的内容,手动去解决冲突,然后
再git commit
和 git push
。
二、git commit合并
在使用git的时候,可能针对同一个任务由多次提交,比如针对同一个feature
可能由多个同事修改了不同部分,但是多个提交让我们的版本管理显得比较凌乱,此时我们可以合并多个commit
为一个。
首先假设我们有三个commit
,如左下所示:我们想把最近的三个commit
合并为一个commit
,那么此时我们可以使用git rebase
命令了,即git rebase –i 4cbeb4248f7
,-i
后面的参数表示不要合并的commit
的hash
值。
可以看到其中分为两个部分,上方未注释的部分是填写要执行的指令,而下方注释的部分则是指令的提示说明。指令部分中由前方的命令名称、commit hash
和 commit message
组成。
pick
和 squash
的意思如下:
pick
的意思是要会执行这个commit
。squash
的意思是这个commit
会被合并到前一个commit
。
将 ad777ea
和a271901
这两个commit
前方的命令改成 squash
或 s
,然后输入:wq
以保存并退出。
退出后会弹出如下界面,即需要重新编辑合并后的commit
信息,未注释掉的是会包含在commit message
里的,按”wqa
”保存后即完成了此次commit
的合并。
三、修改commit的内容
3.1、修改自己的提交
有时候,提交一个commit
后,发现有些部分漏掉了,尤其是有的内容忘记添加到暂存区了,导致这些内容没有commit
,那如果我们把这些“漏掉”内容作为一个新的commit
提交总不太好,其实我们可以把“漏掉”的内容提交到上一个commit
里。
还有时候,我们刚刚最近的一次提交的commit message
写的内容不够严谨,需要重新整理下。
那上面的两种场景,我们怎么处理呢? 答案是git commit –amend
。比如最近的一次提交的内容少提交了一个README.md
文件了,而且“Merge branch ‘master’ of 47.106.79.26:/srv /nginx-docs
”的内容也不够严谨,需要规范化提交内容。此时我们可以先调用git add README.md
文件到暂存区,然后调用git commit –-amend
把当前暂存区里的内容合并到上一次commit
里,而且还可以修改上一次提交的message
信息。
git commit --amend
跳出一个VIM编辑框(如左下图),此时我们可以修改提交内容格式(如右图)。
3.2、修改任意提交的message
如果我们想要修改比较久远的commit message
的格式不太符合规范,怎么去修改呢?比如我想修改从bed58d54e
之后所有的commit message
的内容?
# 打算从bed58d54e(不包含bed58d54e)之后所有的commit的messagegit rebase –i bed58d54e
输入上面一条命令后,会弹出下文这个窗口,上半部分是一些pick
命令,下半部分是一些提示内容,不过有意思的是此时的commit
内容的排列和git log
里的排列是反的,也就是倒序的。如果我们仅仅修改commit message
,需要把打算修改的commit
的对应pick
命令修改为reword
,然后保存。
之后会弹出编辑commit message
的内容,如果我们有多处commit
需要被修改的话会多次弹出vim
编辑窗口。如果在修改前所有的commit
都已经push
到远程仓库的话,我们需要使用git push --force
强制推送到远程仓库。
上文仅仅说明了修改历史提交的message
,但是如果在某个历史提交中少提交内容,比如上文某个源码文件里的内容修改不完整,提交很多天经过严格测试才发现,那么我们就可以使用git rebase
的edit
命令修改提交内容了。
git rebase –i bdc6778948a
上面的命令后我们可以使用edit
命令替换pick
命令。保存后,此时git rebase
会停止工作,以便我们可以编辑文件和commit message
,修改并提交后,可以继续其它的edit
命令。在这个过程中我们会使用到以下这两条命令:
$ git commit –-amend$ git rebse --continue
如果在修改前所有的commit
都已经push
到远程仓库的话,需要使用git push --force
强制推送到远程仓库。
四、查看commit的内容
(1)git log
不带任何参数。
git log
输出示例:
commit ac75ee8505774336c3f28a539d6371f1147939ab (HEAD -> master)Author: long-xu <ntf_work@163.com>Date: Sat Aug 10 20:42:46 2024 +0800 Optimize log and print.commit 53cc38f9d2999182b7b5825ab35d90882b341271 (origin/master, origin/HEAD)Author: long-xu <ntf_work@163.com>Date: Sat Aug 10 18:15:46 2024 +0800 Add Configures class and modify makeFile.commit a60663fad8bc9d6b063051addd8b4551dee02346Author: long-xu <ntf_work@163.com>Date: Sun Aug 4 19:49:07 2024 +0800
(2)每条日志显示一行
git log --oneline
输出示例:
ac75ee8 (HEAD -> master) Optimize log and print.53cc38f (origin/master, origin/HEAD) Add Configures class and modify makeFile.a60663f feat: add test0 algorithm3235113 optimized code71d5555 optimize code1be415f Add os class and update src66f95bb feat: add asynLogger class5a29202 feat:update JsonValue and JsonParser909a271 feat:add src file(JsonValue,JsonParser)c310237 Initial commit
(3)只显示前面的length
条日志。
git log –[length]
输出示例:
$ git log -2commit ac75ee8505774336c3f28a539d6371f1147939ab (HEAD -> master)Author: long-xu <ntf_work@163.com>Date: Sat Aug 10 20:42:46 2024 +0800 Optimize log and print.commit 53cc38f9d2999182b7b5825ab35d90882b341271 (origin/master, origin/HEAD)Author: long-xu <ntf_work@163.com>Date: Sat Aug 10 18:15:46 2024 +0800 Add Configures class and modify makeFile.
(4)跳过前面的skip
条日志。
git log --skip=[skip] -3
输出示例:
$ git log --skip=2 -3commit a60663fad8bc9d6b063051addd8b4551dee02346Author: long-xu <ntf_work@163.com>Date: Sun Aug 4 19:49:07 2024 +0800 feat: add test0 algorithmcommit 323511332f090810978032e7270fc88f8ac851e9Author: long-xu <ntf_work@163.com>Date: Wed Jun 26 22:36:32 2024 +0800 optimized codecommit 71d55551a0d6a9302da028468571e2fee7f0ac5dAuthor: long-xu <ntf_work@163.com>Date: Sun May 26 22:57:27 2024 +0800
(5)显示一些统计信息以及文件的改动内容和行信息。
git log -p
(6)显示提交的作者 日期 message 和文件内容统计信息。
git log --stat
(7)显示每个author
提交commit
和多少条commit
。
git shortlog
输出示例:
$ git shortlogLong_xu (1): Initial commitlong-xu (6): Add os class and update src optimize code optimized code feat: add test0 algorithm Add Configures class and modify makeFile. Optimize log and print.nongtengfei (3): feat:add src file(JsonValue,JsonParser) feat:update JsonValue and JsonParser feat: add asynLogger class
(8)过滤。
-
按日期:
git log --after="2018-7-1" # 2018年7月1好之后的所有日志git log –-before="2014-7-1"
-
按作者:
git log --author="Dounin"
-
按照提交信息:
git log --grep=“issue” # 按照提交本中是否包含issue的日志
-
按文件:
git log -- ./src/http/modules/ngx_http_xslt_filter_module.c
-
按照内容:
git log -S “ngx_free” # 即所有文件中包含了 ngx_free字符串的修改
-
按照范围 :
git log <since>..<until> # 比如 git log master..feature这可以显示出自从master分支fork之后,feature分支上所有的提交
(9)显示commit-id
的提交内容,包括所有文件的修改信息。
git show commit-id
五、总结
在本篇关于 git commit
的详解中,我们深入探讨了 Git 提交的基本概念、命令格式、日志查看以及合并和修改提交的过程。通过系统化地理解 git commit
,开发者可以更有效地管理项目的版本控制,提高团队协作的效率,并确保代码的整洁和可追溯性。
-
Git 提交的本质:每次
git commit
都是对当前项目状态的快照,允许开发者查看和恢复历史版本,从而提供了庞大的变更记录。 -
命令的灵活性:命令格式多样,如直接提交、批量提交、以及带注释的提交,提供了丰富的功能,以适应不同的使用场景。
-
标准化的提交信息:使用规范化的提交信息(如 Angular 的消息格式)可以帮助团队交流代码变更的意图,提高代码的可维护性。
-
历史记录的掌控:通过
git log
等命令,可以便捷地查看和过滤提交记录,为代码审查和故障排查提供了便利。 -
合并和修改的能力:Git 允许开发者合并多个提交或修改历史提交的内容,使得版本管理更加灵活,适应开发过程中可能发生的多种情况。
-
推送和冲突解决:理解
git push
的操作及其潜在冲突,使开发者能够更好地维护远程仓库的健康,处理冲突而不丢失重要改动。
熟悉 git commit
及其相关技巧,将帮助开发者在团队协作中更加游刃有余。版本控制不仅是一个工具,更是一种思维方式,通过精确的记录和合理的管理,推动软件开发的高效与质量的提升。希望本文能够助力你在 Git 版本管理的道路上取得更大的进步。