今天的主题是git在各种场景下的使用。git是开源的,是目前最主流的分布式版本控制系统,作为程序员,熟练使用git的简单操作是必备技能,因为百分之九十九的软件开发公司都会使用git。
工作区:修改过的文件,会在工作区中展示。
暂存区:修改完代码后,修改过的文件会展示在工作区,执行git add XXX操作后,会将工作区的文件保存到暂存区。
本地仓库:基于本机(此台电脑)的一个git仓库,通常会与远程仓库关联。执行git commit -m?"提交备注"后,会将暂存区的文件保存至本地仓库。
远程仓库:就是用于托管我们代码的服务器(github,gitee,gitlab...),执行git push后,会将本地仓库的文件同步到远程仓库。
拉取远程项目:
# 拉取远程项目到本地电脑 git?clone http://XXX/XXX.git # 拉项目的同时自动初始化并更新项目中的每一个子模块 git?clone?--recursive?http://XXX/XXX.git
上传本地项目到远程仓库:
# 初始化本地 Git 仓库,会生成一个 .git 隐藏文件夹 git?init ? ? ? # 将本地项目关联远程仓库,后面的 https://xxxx 就是复制的远程仓库的链接 git?remote add origin https://xxxx # 上传之前更新一下,确保没有冲突,master 为分支名称 git?pull?--rebase?origin master # 添加目录下所有发生改变的文件 git?add . ? ? # 添加注释信息 git?commit?-m?'xxx'?? ? # 提交到 master 分支 git?push?-u?origin master?? ?
上述命令中 git remote add origin https://xxxx就是往.git/config文件里添加下面一段,也可以手动添加,就是与远程仓库建立关联的意思。
[remote?"origin"] url?=?https://github.com/baomihuaxaiobu/xxxx.git fetch?=?+refs/heads/*:refs/remotes/origin/*
命令里的 origin 其实就是给这个远程仓库取一个名字,没有别的意思,通常大家都取名为origin而已,我们也可以把他换成 baomihua, 后面大家提交的时候涉及到origin相关命令的时候,把origin替换成 baomihua 即可。例如 git push origin master 改为 git push baomihua master。
git是可以关联多个远程仓库的,git remote -v 可以快速查看当前已关联的远程仓库列表
关联多个远程仓库:可以使用git remote add XXX URL 添加多个远程仓库,或者直接手动在 .git/config 文件里添加。比如一个项目同时关联一个github仓库和一个gitee仓,或者一个项目需要将代码同步到A公司的远程仓库,同时也需要将代码同步到B公司的远程仓库。
[remote?"baomihua"] url?=?https://github.com/baomihua/xxxx.git fetch?=?+refs/heads/*:refs/remotes/github/* [remote?"xiaobu"] url?=?https://gitee.com/xiaobu/xxxx.git fetch?=?+refs/heads/*:refs/remotes/gitee/* [remote?"all"] url?=?https://github.com/baomihua/xxxx.git url?=?https://gitee.com/xiaobu/xxxx.git fetch?=?+refs/heads/*:refs/remotes/all/*
经过上述添加远程仓库操作后,当我们想提交代码到baomihua远程仓库时,就用 git push baomihua master,想提交代码到xiaobu远程仓库时,就用git push xiaobu master,如果想要同时提交到baomihua和xiaobu时,仅需 git push all master 既可。那么上面[remote "all"] 下面的第二个url是怎么用命令添加的呢?
git?remote set-url?--add?all https:/gitee.com/xiaobu/xxxx.git
常用命令remote:
# 添加关联远程git地址为 https://XXX.git的连接,并取名为 origin
git?remote add origin https://XXX.git
# 删除关联的名为baomihua的远程仓库
git?remote rm baomihua
# 将关联的名为baomihua的名字改hamigua
git?remote rename?baomihua?hamigua
# 显示所有远程仓库的详细信息,包括名称和URL
git?remote -v
# 给关联名字为 all的仓库添加关联远程仓库URL
git?remote set-url?--add?all http://XXX
# 给关联名字为 all的仓库删除关联远程仓库URL
git?remote set-url?--delete all http://XXX
常用命令add:
# 添加一个文件 xiaobu.js 到暂存区,多个文件以空格隔开 git?add xiaobu.js # 添加多个文件 xiaobu.js baomihua.js 到暂存区,多个文件以空格隔开 git?add xiaobu.js baomihua.js # 添加全部文件到暂存区 git?add .
常用命令commit:
# 会打开 vim 编辑器 git?commit # 提交暂存区的文件到本地仓库,并备注当前 commit 记录 git?commit?-m?'备注信息' # 相当于 git add . 加上 git commit -m '备注信息' git?commit?-am?'备注信息' # 用本地提交替换上次提交,比如不想保留上一次提交或者上一次提交描述信息写错了之类的 # 此操作后会进入vim模式,键入i进入编辑模式,修改第一行的提交信息后 按ESC键退出编辑模式,再键入 :wq 保存并退出vim模式,即可完成对该次commit提交备注的修改 git?commit?--amend
常用命令fetch:
# 更新git remote 中所有的远程仓库(repository) 所包含分支的最新commit-id, 将其记录到.git/FETCH_HEAD文件中 # 将所有远程仓库所有分支的记录都同步到本地仓库来 git?fetch # 获取默认远程仓库所有分支的变更 git?fetch?-a # 获取名为baomihua的远程仓库所有分支的变更 git?fetch baomihua # 获取名为baomihua的远程仓库develop分支的变更 git?fetch baomihua develop # 获取名为baomihua的远程仓库develop分支的变更并在本地新建一个develop本地分支保存远端分支的所有数据, remote_branch_name:local_branch_name git?fetch baomihua develop:develop
常用命令merge:
# 把本地的 test 分支分并到我当前分支 git?merge test # 合并 remote origin 对应远程仓库的 master 分支到当前分支 git?merge origin/master # --on-ff 是 no-fast-forward简写,合并并且会在分支上重新生成一个新的 commit 节点 git?merge?--on-ff?origin/master # 加入 --squash 表示合并,但是不生成 commit 记录,通常用于把本地分支合入远程分支 git?merge test?--squash # 取消合并,用于撤销合并操作并恢复到合并之前的状态 # 如果在合并过程中出现冲突,或者有其他问题导致合并操作未能正常完成,可以使用 git merge --abort来中止合并过程,并尝试重建合并前状态。 # 需要注意的是,如果在合并开始时有未提交的更改,并且在合并开始后进一步修改了这些更改,那么在某些情况下, git merge --abort 可能无法重建原始(合并前)更改。 git?merge?--abort
常用命令pull:git pull的作用是:取回远程主机某个分支的更新,并与本地的指定分支进行合并。
# git pull = git fetch + git merge # git pull 的基础用法 # git pull <远程主机名如:origin> <远程分支如:master>:<本地分支如:localMaster> git?pull origin master:localMaster # 拉取 remote origin 对应的远程仓库的 master 分支合并到本地的 test 分支 git?pull origin master:test # 拉取 remote origin 对应的远程仓库的 master 分支合并到本地的当前分支 git?pull origin master #?git版本大于2.00且小于 2.23 时,拉取 remote origin 对应的远程仓库的与本地的当前分支同名的远程分支合并到当前分支
git?pull
# git版本大于等于?2.23 时,如果未先与远程分支进行关联,直接使用git pull无法拉取,得进行如下命令进行关联
git?branch --set-upstream-to=origin/<branchName>?<localBranchName>
git?pull
# 或者如下命令
git?branch --set-upstream?<localBranchName>?origin/<branchName>?
git?pull
常用命令push:git push的作用是:将本地代码库的修改推送到远程仓库。
# 推送本地 test 分支到 remote origin 对应的远程仓库的 master 分支 git?push origin test:master # 上述命令行的 test 也可以使用 HEAD 代替 git?push origin HEAD:master # 上下面的命令行相当于? git push origin test:test git?push origin test #?上面的推送命令都不会让本地分支与远程分支进行关联,如果无关联的远程分支直接git push将无法推送 git?push #? git版本大于2.00且小于2.23时, 远程无同名分支时可使用如下推送命令, 会在远程仓库同时创建分支并推送上去
git?push origin HEAD
#? git版本大于等于2.23时, 未与远程仓库进行关联时,将无法推送成功,需要先进行关联操作。当前在本地test分支?
git?push --set-upstream origin?test
git push
#? 或者直接一个语句
git?push -u origin?test
# 相当于 git push origin master 加上 git branch --set-upstream master origin/master
# 推送并关联远程分支
git?push?-u?origin master
# 强制推送,就算本地和远程有差异也推上去
git?push?-f?origin master
# 删除远程主机的 master 分支
git?push origin?-d?master
创建分支:
# 创建本地分支 develop,但不切换 git?branch develop # 创建 develop 分支,并切换到 develop 分支 git?branch?-M?develop # 创建 develop 分支,并切换到 develop 分支 git?checkout?-b?develop # 创建 develop 分支,并切换到 develop 分支, switch命令需要 git 版本大于等于 2.23 # git --version 查看git版本 git?switch?-c?develop # 创建本地与远程对应的 develop 分支,并切换到 develop 分支,全称最好一致 git?checkout?-b?develop origin/develop
查看分支:
# 查看所有(远程及本地)分支 git?branch?-a # 查看本地分支 git?branch # 查看远程分支 git?branch?-r
切换分支:
checkout和switch都能切换分支,switch命令需要在git版本大于等于2.23才可使用,siwtch语义上更好,且该命令仅仅用于切换分支或者创建并切换分支。而checkout还能用来还原工作区。
# 切换到 develop 分支 git?checkout develop # 新建 develop 分支,并切换到 develop 分支 git?checkout?-b?develop # 切换到 developdevelop 分支 git?switch develop # 新建 develop 分支,并切换到 develop 分支 git?switch?-c?develop # 新建test分支并切换到develop分支 branch 方式 git?branch?-M?develop
删除分支:
# 删除本地develop分支
git?branch?-d?develop
?
# 强制删除本地develop分支
git?branch?-D?develop
?
# 删除远程主机的develop分支
git?push origin?-d?develop
重命名分支:
# 把本地的 xiaobu 分支重命名为 baomihua
git?branch?-m?xiaobu baomihua
# 远程分支没法直接重命名,只能删了重建,主要分几步
# 1. 删除远程xiaobu分支
git?push origin?--delete?xiaobu
# 2. 将本地的 xiaobu分支重命名为 baomihua
git?branch?-m?xiaobu baomihua
# 3. 创建远程同名分支并将本地仓库代码推送到远程仓库
git push --set-upstream origin?baomihua
合并分支:
# 切换到master本地分支 git?checkout master # 拉取远程代码 git?pull # 合并origin/develop_1.1远程分支的代码到master git?merge origin/develop_1.1 # 有冲突的话先解决冲突,确认没问题再推送到远程仓库 git?push
别名alias:
# 配置全局 branch 命令别名为 bh git?config?--global?alias.bh branch # branch命令即可用 bh代替 branch命令仍可继续使用 git?branch?-a git?bh?-a
检出操作:将已修改的记录撤回,或者将某文件代码重置到某个提交的时候。
# 四个都是:撤销 xiaobu.js在工作区的修改 git?checkout?--?xiaobu.js git?checkout?-?xiaobu.js git?checkout xiaobu.js git?restore xiaobu.js # 只把 xiaobu.js 还原成上一个版本的,HEAD^表示上一个版本,HEAD^^上上一个版本 git?checkout HEAD^?-?xiaobu.js # 只把 xiaobu.js 重置到某个指定版本 git?checkout commitID xiaobu.js # 把 master 分支的 xiaobu.js 拿过来替换当前分支的 xiaobu.js git?checkout master?-?xiaobu.js # 都是撤销工作区中所有文件的修改 git?checkout?--?* git?checkout?--?. git?checkout . git?restore . # 把暂存区的 xiaobu.js 重新放回工作区,和 git reset HEAD xiaobu.js 作用一样 restore在git 版本大于等于 2.23才有该命令 git?restore?--staged?xiaobu.js
回退版本之reset:
# 查看提交记录 会出现提交记录 且进入vim模式 一直回车 继续查看, 键入 q 可退出vim模式 ? git?log # 回退到指定的提交记录 仅本地代码回退 需要强制推送到远程仓库方可覆盖代码,覆盖后被回退的提交记录将不复存在无法找回 git?reset?--hard?[commitId] # 强制推送到远程仓库 谨慎操作,提交记录将不复存在
git?push origin?-f?master
#?取消某次合并
git?reset --merge commitID
git?reset --keep commitID
回退版本之revert:相比reset的暴力回退,revert显得更加温柔,revert不会清除已提交的记录,而是新增一条提交记录。例如:有一、二、三、四,四个提交记录,目前需要回退到一的版本,使用reset回退则二三四的提交记录将全部消失,而revert则是新增一个五的提交记录重置四这个提交,新增一个六的提交记录重置三,新增一个七的提交记录重置二,这样代码就回到了一的版本。revert的作用就是对某次提交进行重做
# 查看提交记录 会出现提交记录 且进入vim模式 一直回车 继续查看, 键入 q 可退出vim模式 ? git?log # 对某次提提交记录的变更进行重做,会进入vim模式,键入:q
git?revert [commitId]
#?HEAD最后一次(上一个)提交,HEAD^ 上上个提交? HEAD^^上上上个提交 键入 :q
git revert HEAD?
# 接下来就是? push操作
从暂存区中撤回:
# 把暂存区所有文件退回到工作区,相当于撤销 git add . git?reset HEAD # 把暂存区所有文件退回到工作区,相当于撤销 git add . 并删除所有修改 git?reset?--hard?HEAD # 把暂存区的 test.js 重新放回工作区,和 git restore --staged test.js 作用一样 restore 需要git 版本大于等于2.23才可使用 git?reset HEAD test.js
撤回已经commit的提交记录:
# --hard 会撤销git commit和git add . 以及删除所有修改 # --mixed 会撤销git commit和git add . 保留编辑器中所有修改 # --soft 撤销 git commit,但不撤销 git add,保留编辑器中所有修改 # HEAD 为 未commit状态 HEAD^ 为最近一个版本commit的 状态 以此类推 # 以此类推 重置到上一个版本 git?reset?--hard?HEAD^ # 重置到上上一个版本,以此类推 git?reset?--hard?HEAD^^ # 重置到指定版本 git?reset?--hard?commitID
stash的使用:代码均已修改,还未提交到暂存区,但是发现当前分支并非实际想要开发的目标分支,此时由于存在修改项,无法切换分支,这时候就可以借助stash来暂存我们的修改代码,再进行切换到目标分支,再检出stash的修改项。
# git stash 常用于把修改储存起来,需要的时候再取出来 # 存储并添加备注方便查找 或者 直接 git stash 无需添加备注 git?stash save?"备注信息" # 此时修改的部分信息将被存储起来,此时可以切换分支 切换到develop分支 git?checkout develop # 查看存储列表 git?stash list # 取出储存中最近一次的修改并删除储存记录, 此时已经完成目的 修改点无需撤回或者提交也可切换分支 git?stash pop ### 以下为其余stash相关操作 # 取出储存中的指定部分修改,stash@{0} 0是默认的不写也行,是啥只要查看储存列表你就知道了 git?stash apply stash@{0} # 删除指定储存 git?stash drop stash@{1} # 删除所有的储存 git?stash?clear # 创建一个新分支 test,并恢复储存工作时所在的提交到该分支上,并扔掉储藏 git?stash branch test stash@{1} # 不储存暂存区的,也就是 git add 了的 git?stash?--keep-index
cherry-pick的使用:他的使用场景就是您在错误的目标分支修改了代码且提交了,此时复制此次commitID,然后切换到目标分支,使用cherry-pick将此次提交的代码合并过来。和merge不同的是,cherry-pick合并的是某次commit提交的文件,merge合并的是整个分支,且merge会额外多一条合并记录,cherry-pick不会。
# 这样就把其他分支的一个 commit 合入当前分支了 git?cherry-pick commitID # 如果需要把多个 commit 合过来如下,这多个 commitID 可以是来自不同分支的
git?cherry-pick commitID1 commitID2 commitID3
git merge 和 git rebase 都是可以合并分支,合并用法也是一样,不同的一个是在 commit 记录的处理上:
git merge
?会新建一条新的 commit,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会保留之前每个分支的 commit 历史。
git rebase
会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,放到目标分的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记录了。
这么说可能不太好理解,看如下示例
# 如下,需要把本地 test 分支合入 dev # 为方便理解,字母表示commit记录,数字表示提交时间顺序,可以理解为1就是1点提交的 dev?-> A1?-> B3?-> ? 这一行是远程 dev 分支的commit记录,A1/B3是你同事提交的 ? ? ↘ X2?-> Y4↗ ? 这一行是拉取了 dev 分支后在本地的 test 分支 commit 记录 # 现在需要把你本地的分支合并到远程的分支去 # 用merge合并后,dev 分支看到的记录是这样的,M为merge记录的commit dev?-> A1?-> X2?-> B3?-> Y4?-> M # 用rebase合并后,dev 分支看到的记录是这样的,注意顺序,且没有合并记录的commit # 简单说就是直接把 test 分支的所有新的 commit 拿出来直接拼到 dev 分支末尾,不管提交时间先后 dev?-> A1?-> B3?-> X2?-> Y4
然后是解决冲突的问题上,merge 是解决一次冲突就行了,rebase 需要一次一次地解决,如上示例的记录顺序也能看出来
再就是?rebase
?可以合并多次 commit。比如本地分支提交了三个 commit,但没有 push 到远程,最后想提交到远程的时候,为了简洁,我们希望把本地的三个 commit 合并成一个 commit 再提交到远程,远程只产生一条 commit 记录,就可以用?git rebase -i
?处理下先,这命令可以删除指定记录,或者合并多个 commit,对 commit 消息编辑等
# 删除某次提交,^表示 commitID 的前一次提交
git?rebase?-i?'commitID'^
# 修改多个提交信息
git?rebase?-i?HEAD~3
# 打附注标签 git?tag?-a?<tagName>?-m?"备注信息" # 打轻量tag git?tag <tagName> # 将tag推送到远程仓库 git?push origin <tagName> # 推送所有远端不存在的tag git?push origin?--tags # 查看tag列表 git?tag?--list # 查看单个tag git?show <tagName> # 删除本地tag git?tag?-d?<tagName> # 删除远程tag 一 git?push origin :refs/tags/<tagName> # 删除远程tag 二 git?push origin?--delete?<tagName> # 在某次提提交后打标签,打附注标签时 没有-m 备注信息的话 会进入 vim模式要求你书写备注信息,键入i进入编辑模式,输入备注消息,键入:wq 保存并退出 git?tag?-a?<tagName> <commitId>?-m?"备注消息"
# :w ? 保存 # :q ? 退出vim模式 # :wq 保存并退出vim模式 # ! ? 强制的意思,不能保存时 :w! 强制保存 不能退出时 :q! 或 :wq! 强制退出 # vim 打开默认是不能输入的,要按 a 或者 i 进入编辑模式,输入完成后,再按 Esc 退出编辑模式,这时左下角会有输入框,输入如下英文字符,注意冒号别打成中文字符,回车即可退出 vim 回到终端
git commit
?提交规范指的就是?git commit -am 'xxxx'
?里的?xxxx
?的书写规范,比如我在工作中开发了一个新功能提交的时候一般这么写:
git commit -am 'feat: 添加扫码登录
git commit -am 'feat(mobile):添加扫码登录
,或者加个范围说明是添加哪方面的功能
feat
?就是添加新功能的时候用,更多说明如下:
feat
:添加新功能
fix
:修复问题/BUG
style
:注意不是指CSS,而是修改了如空格、缩进、逗号等代码风格相关,且不影响运行结果的
perf
:优化相关的,比如功能优化、性能提升、提升体验等
refactor
:代码重构,没有加新功能或者修复 bug
revert
:撤消编辑,回滚到上一个版本、撤销上一次的 commit 之类的
test
:测试相关,比如单元测试、集成测试等
docs
:修改文档/注释,比如?README、CHANGELOG、CONTRIBUTE 等
chore
:依赖更新/脚手架配置修改等,比如有改变构建流程、或者增加依赖库、工具之类的
workflow
:工作流程改进
ci
:持续集成
types
:类型定义文件更改