工作向git使用指南
背景
集中式和分布式
- 集中式版本控制系统:所有的版本都保存在一个中心服务器中,修改文件时需要先从中心服务器中获取,修改结束后再上传回服务器。这样的版本管理方式存在很多问题,比如服务器宕机导致版本文件丢失、对服务器的访问依赖于网速、协同工作不便等。
- 分布式版本控制系统:每台本地计算机都可以保存一个完整的版本库,不同计算机之间的版本共享通过推送实现。对于分布式管理系统,中心服务器的职能不再是存储版本,而是管理交换,充当不同计算机之间共享版本的中介。
工作原理
-
本地仓库和远程仓库
git通过本地的git仓库来保存和管理版本,因此绝大多数git操作都是无需联网的。如果需要中心服务器提供的中介和托管功能,则可以和远程仓库建立连接,比如github、gitee等。
-
保存快照而不是diff
传统的版本控制系统是通过保存文件的diff来进行版本控制的,但是git选择直接记录项目版本文件的快照,使得每一个版本都具备完整性,并且版本的更迭看起来像是一个快照流。
起步和配置
配置用户信息
- 在多人协作的项目里,不要忘记首先要给本地计算机的git配置用户信息,方便团队进行代码检查
--global
意思是全局配置,也可以只配置某个本地仓库的(默认--local
)-
# 可以查看config文件的所有变量键值对 git config --list | -l # 配置全局用户名 git config --global user.name <user-name> # 配置全局用户邮箱 git config --global user.email <user-email>
配置命令的alias
- 声明某个command的alias,配置成功后只要输入别名就等同于输入命令
git config --global alias.<alias> <command>
- 示例:
# 给status命令配置一个st别名
git config --global alias.st status
git st # 等同于git status
- 配置alias能提高使用git的效率,但是降低了可读性,在一开始对某些git命令不熟悉的时候不建议配置。
克隆远程仓库
- 通过cd或者直接在某个目录下
shift + 右键
,切换git bash的工作目录。
如果需要把本地项目交给git做版本管理,就在项目文件夹下通过git init
命令创建本地仓库,但是一般操作都是先在远程创建仓库再clone到本地。
- 克隆远程仓库:
# 将url为<url>的远程仓库克隆到本地
git clone <url>
# clone仓库时会默认在指定目录下生成一个和项目同名的项目文件夹,可以指定项目文件夹的名字
git clone <url> <name>
- url的传输协议可以是Https或者SSH:
- Https协议:任何人都可以clone该仓库,但是在对远程仓库推送时需要权限认证,则需要验证用户名和密码
- SSH协议:在clone仓库之前就已经通过SSH Key和远端建立连接,保证clone时用户就已经有一定的仓库权限,因此可以免密推送
工作流程
创建新分支
# 1. 创建一个本地新分支但不切换
git branch <branch-name>
# 也可以创建一个跟踪远程分支的本地分支
git branch <branch-name> --track <remote>/<branch-name>
# 2. 创建一个本地新分支并切换
git branch <branch-name>
git switch <branch-name>
# *或者直接检出新分支
git checkout -b <branch-name>
# 3*. 创建一个追踪远程分支的本地新分支并检出
git checkout -b <branch-name> --track <remote>/<branch-name>
示例:
# 拉取项目时默认拉取的是master分支,如果想在本地新建一个追踪到远端develop分支的分支,可以直接用checkout命令
git co -b dev --track origin/develop
开发工作流
1. 拉取主分支最新代码
# 每天打开电脑第一步,pull一下远端master分支的代码,及时获取更新
# master分支
git pull
- 注意pull和fetch的区别,pull会把更新和本地分支合并,而fetch不会
2. 处理自己的工作分支
有时候master分支更新了一些比较重要的feature时,工作分支需要和主分支同步更新,有两种方式:
- 方式一:合并到master分支
git merge master
合并到master分支可能会产生冲突,如果产生冲突,要到IDE手动处理完冲突的文件后,提交一个merge commit才能完成合并。
- 方式二:变基到master分支
git rebase master
# 或者
git pull --rebase origin master
变基的意思是把工作分支的基点变成master分支的最新commit,再依次提交原本工作分支上的commit,使得工作分支的commit历史更清晰明了。但是要注意远程工作分支的commit历史是不会变基的,需要本地分支强行push到远程。
-
merge和rebase的区别:
-
rebase抹去了分支的“合并”这一操作,使得分支的commit历史是更加线性的。这也是rebase和merge的最大区别,merge保留了“合并”这一过程。
-
rebase更适合feat分支使用,则用于新增项目功能特性的分支。因为一旦master和工作分支产生冲突,rebase会直接生成一个detached head,即当前head指向的工作环境是和之前的分支分离的,此时如果需要再合并的话会很麻烦,不如直接使用merge方便。
-
3. 工作中的git使用
-
普通流程
# 1. 添加文件到暂存区 # 添加所有修改后的文件 git add . # 添加部分文件,以空格隔开 git add <file> # 2. 将暂存区的更改提交到本地git仓库 # commit必须要带上commit message git commit -m "some messages" # 如果需要合并add和commit操作,可以用-am git commit -am <file> -m "some messages"
commit message规范
- feat(feature):新增功能
- fix(fix bugs):修改代码
- style:样式,不涉及代码
- perf(performance):性能优化
- test:单元测试
- refactor:重构
- docs:文档
-
回退
# 1. commit的回退 # 用于撤销某个commit,并且会留下一条新的commit git revert <commit> # 2. 版本的回退 # soft模式:被修改文件回到暂存区(即文件被add但是未commit的状态),改动最小 git reset --soft <version> # mixed模式:默认模式,被修改文件回到未提交状态 git reset --mixed <version> # hard模式:丢弃所有修改,强行回退 git reset --mixed <version>
-
暂存文件
当需要切换分支进行工作,但是不想提交当前修改的内容时,可以暂存已完成的修改。
# 要注意stash是一个栈 git stash --save "save messages" git stash pop # 应用栈顶的stash并弹出栈(从stash中删除) git stash apply # 应用某个stash,不会删除
-
合并多个commit记录
有时候多个commit合起来才是一个完整的任务,为了保证远端commit历史的流畅性,可以通过rebase命令来合并多个commit。
# 1. 选取某个历史commit为基点,该基点之后提交的commit都将被合并成一个新的commit # -i后面紧跟的就是基点commit,比如当选取HEAD~2为基点时,则合并HEAD和HEAD~1两个commit git rebase -i HEAD~2 # 2. 跳出vim界面后,输入-i进入INSERT模式,把除第一个以外的pick改为s,意为合并 # 3. 按下ESC键退出INSERT模式,输入:wq保存并退出,git将开始执行rebase操作 # 4. 操作结束后,会再次跳出一个要求输入commit message的vim界面,把旧的message删除,输入一条新的commit message后保存退出 # 如果只是合并本地的commit的话,那么到这一步已经结束了 # 如果远程的分支也需要合并,切记千万不要直接merge,否则远程的commit历史依然是没有改变的!!! # 5. 为了改变远程分支的commit历史,还需要强制push,完成commit合并操作 git push -f
如果是想在Source Tree上完成合并commit的话,只需要选择软合并,回退到某个基点commit上,再进行commit即可,一样要注意强制push的问题。
-
合并指定commit的修改
有时候需要把某个分支上的某个指定commit合并进自己的分支,而无需和整条分支合并,就可以使用cherry-pick命令。
git cherry-pick <commit> # cherry-pick不局限于自己的分支,可以合并其他分支上的commit,合并成功后,当前分支会直接多一个commit记录
4. 团队协作
# git blame命令可以看到某行代码的作者,在团队协作中有很大作用
# -L指的是定位某一行
git blame -L <start>,<end>
但是在实际工作中,可以使用插件更加直观地看到某一行代码的作者,比如VS Code的Gitlens插件。
5. 比对历史版本
git diff
可以看到不同版本之间的改动,方便我们定位和再次修改,但是缺乏更加友好的可视化,因此工作中一般都是使用插件或者直接用git的可视化软件查看。
6. 合并到master
在实际工作中,master作为最重要的主干分支,并不可以随意merge其他工作分支。
我们在自己的工作分支完成开发后,如果已经通过自测,则需要提一个merge request,经过Code Review和测试后,才能正式上线。
提mr可以自己手动提;在IDE中commit时,gitlab会自动根据commit message生成一个mr连接,点进去也可以提交mr。
转载自:https://juejin.cn/post/7074240926175985700