题引:
既为了总结自己在Git使用上的实践经验,也为了给有同样Git使用需求的伙伴们提供借鉴。
本文Git使用方式为命令行。相信对Git有所了解的朋友,一定清楚,命令行在Git的使用中是最原子化的,也是最容易在使用过程中加深对Git原理理解的方式。任何Git的GUI操作工具,都是Git相关操作命令的子集。
什么是Git?Git和SVN的区别?使用Git有哪些好处?Git的冲突原理?怎么生成Git公钥私钥?这些问题不在本文讨论范围之内,有如上需求,请Google或者百度。
现在,我默认你已经拥有了Git的命令行终端工具(无论是Mac自带的终端,Windows下的git-bash终端,还是其它包含Linux使用方式的终端),并且已经配置好了Git的使用环境(账号及公钥私钥等问题)。
为了下文理解方便,这里简单普及Git中的三个概念:工作区、暂存区、版本库。
如何简单粗暴理解工作区、暂存区与版本库?
工作区:对克隆的项目中任何文件进行的任何改动,全部在工作区,无论你新增文件还是修改了文件
暂存区:凡是使用git add命令操作后的相关文件全部在暂存区(凡是能git commit的内容都在暂存区)
版本库:凡是经过git commit命令操作后的相关文件全部都在版本库,这里是本地版本库
远程版本库:凡是经过git push命令操作后的相关文件全部都在远程版本库
如何在命令行模式下轻易区分文件处于工作区、暂存区还是版本库?
绝大多数命令行终端工具(本文以windows下git-bash终端为例),对文件状态的显示有不同颜色:
工作区内容:无论修改还是新增的文件,呈现红色
暂存区内容:显示绿色
版本库内容:对不起,版本库内容默认没有显示,即使用git status看不到的文件都在版本库中
git status命令下文会有介绍
接下来介绍常用的Git命令及作用:
(1)Git特殊命令集(该特殊仅仅为了与下文中Git命令作用功能范围进行区分)
// 将某个文件夹初始化为Git版本库,无论该文件夹是否为空
git init
// 查看工作区、暂存区、版本库文件状态
git status
// 查看工作区中所有文件的修改内容
git diff
// 查看工作区中某个文件的修改内容,fileName可通过git status命令得到
git diff fileName
// 查看Git某个命令的帮助文档,直接在该命令后加--help参数即可,注意空格
git log --help 查看git log命令的帮助文档
git commit --help 查看git commit命令的帮助文档
git diff --help 查看git diff命令的帮助文档
// 暂存工作区中所有修改或新增的内容,使工作区清空(切换分支和pull代码时常用)
git stash
// 查看被暂存的内容
git stash show
// 将暂存的内容恢复至工作区
git stash pop
// 将a分支上的某次提交commitId应用到当前分支(挑选合并)
git cherry-pick commitId
(2)拉取远程代码相关
// 克隆远程版本库,https:xxx和ssh:xxx为远程Git仓库地址,https和ssh代表不同的通讯协议
git clone https:xxx 或者 git clone ssh:xxx
// 从远程版本库更新所有文件到本地版本库,并完成远程与本地对应分支的merge操作
git pull
(3)提交代码相关
添加工作区内容到暂存区:
// 添加工作区所有修改或新增的文件到暂存区
git add .
// 添加工作区某个新增或修改的文件到暂存区,fileName可通过git status命令得到
git add fileName
// 添加工作区多个新增或修改的文件到暂存区,多个文件之间用空格隔开
git add fileName1 fileName2 fileName3
提交暂存区内容到版本库:
// 提交暂存区所有文件到版本库,"."代表所有文件,-m代表添加注释,这是方法一
git commit . -m "提交注释"
// 提交暂存区所有文件到版本库,"."代表所有文件,该命令会进入vi界面,可添加注释,这是方法二
git commit .
// 提交暂存区某个文件到版本库,fileName可通过git status命令得到,这是方法一
git commit fileName -m "提交注释"
// 提交暂存区某个文件到版本库,该命令会进入vi界面,可添加注释,这是方法二
git commit fileName
// 提交暂存区多个文件到版本库,多个文件之间用空格隔开,这是方法一
git commit fileName1 fileName2 fileName3 -m "提交注释"
// 提交暂存区多个文件到版本库,该命令会进入vi界面,可添加注释,这是方法二
git commit fileName1 fileName2 fileName3
将本地版本库推送到远程版本库:
// 将本地版本库推送到远程版本库,该命令会将本地分支推送到与本地对应的远程分支中
git push
(4)查看提交日志相关
// 查看全部提交日志
git log
// 以一行的形式显示log的title
git log --oneline
// 查看提交修改了哪些内容
git log -p
// 查看某次提交修改了哪些内容
git show commitId
// 查看指定用户的提交, str可以是git中的用户名,也可以是正则表达式
git log --author=str
// 根据log中的一些关键词进行过滤,str可以是提交信息中的某些关键词,也可以是正则表达式
git log -grep=str
// 类似GUI工具显示方式查看日志及更改内容
gitk
(5)Git文件状态回退相关
工作区内容回退(该操作不可逆,无法找回,谨慎操作):
// 工作区中修改的所有文件回退(放弃所有修改)
git checkout .
// 工作区中修改的某个文件回退,fileName可通过git status命令得到(放弃某个文件修改)
git checkout fileName
// 工作区中修改的多个文件回退,多个文件之间用空格隔开(放弃多个文件修改)
git checkout fileName1 fileName2 fileName3
// 工作区中新增的文件回退(删除新增的内容)
直接使用linux中的删除文件相关命令:rm -f 或者 rm -rf
暂存区回退到工作区:
// 所有文件:状态从暂存区回退到工作区
git reset .
// 某个文件:状态从暂存区回退到工作区,fileName可通过git status命令得到
git reset fileName
// 多个文件:状态从暂存区回退到工作区,多个文件之间用空格隔开
git reset fileName1 fileName2 fileName3
本地版本库回退到工作区:
// 放弃本次提交,lastCommitId为本次提交前的上一次提交的commitId
git reset lastCommitId
远程版本库回退:
// 放弃本次提交,commitId为本次提交的commitId,该方式为反转提交
git revert commitId --> 进入vi界面,可添加注释,也可直接保存退出
--> git push
(6)解决冲突相关
// 出现了冲突,解决方式,该命令会打开比对工具进行冲突处理
git mergetool
(7)分支管理相关
// 合并a分支到当前分支
git merge a
// 变基a分支到当前分支(该命令可更改真实提交历史,不建议使用)
git rebase a
// 当前分支为a,想切换到分支b(切换分支时,工作区必须无修改或新增)
git checkout b
// 列出本地所有分支
git branch
// 列出远程所有分支
git branch -r
// 基于当前分支创建本地新分支
git branch newBranchName
// 基于当前分支创建本地新分支,并切换到新分支
git checkout -b newBranchName
// 删除本地存在的a分支,-D代表强制删除
git branch -D a
// 推送本地新分支到远程,建立远程对应新分支,一般情况localBranchName与remoteBranchName相同
git push origin localBranchName:remoteBranchName
// 建立本地分支与远程分支的关联映射关系,一般loalBranch与remoteBranch名称相同
git branch --set-upstream localBranch origin/remoteBranch
// 删除远程分支,把上一个命令中的localBranchName置为空即可,方法一
git push origin :remoteBranchName
// 删除远程分支,方法二
git push origin -d remoteBranchName
了解了常用的Git命令包,接下来介绍常用工作场景中如何使用这些命令:
工作场景一——克隆项目,拉取最新代码
1.克隆项目到本地仓库
git clone https:xxx 或者 git clone ssh:xxxx
2.克隆完成后,一般为服务器此时最新内容,如若又有人提交了新内容
git pull
工作场景二——提交代码
1.提交代码时,先更新
git pull
如果命令顺利结束,则更新结束并完成与本地对应分支的merge操作
如果命令未顺利结束(git pull时提示错误),说明远程与本地可能存在冲突,可以:
git stash // 将工作区的所有修改或新增暂存起来,保证工作区clean
git pull // 此时一定可以将远程内容pull下来,因为工作区已经clean了
git stash pop // 将暂存起来的内容应用到工作区,此时可能会发生冲突
git mergetool // 进行冲突解决,如果没有冲突,则该命令会顺利结束,更新完成
2.提交代码(这里以某个文件为例,全部文件或多个文件的提交请参考上文的命令包)
// 添加工作区待提交内容到暂存区
git add fileName
// 提交暂存区内容到本地版本库
git commit fileName -m "提交注释"
// 推送本地版本库到远程版本库,git push会默认推送到与本地关联的远程分支上
git push
如果git push命令顺利结束,则提交代码完成
如果git push命令未顺利结束,出现错误提示,说明在你更新之后又有人推送了新内容到远程,此时可以:
git pull // 将远程最新内容拉取下来
git push // 再将自己的提交推送到远程,但此时git log上会包含一次merge提交记录,如果你想保证git log提交历史的整洁,可以:
git log // 找到你此次提交的上一次提交lastCommitId
git reset lastCommitId // 将本地版本库重置回你提交前的状态,工作空间依然会保留你所有的修改或新增
重新执行提交代码流程(步骤2),此时会保证你的提交历史是干净的,不包含merge提交记录
工作场景三——挑选合并
假设你有两个分支,开发分支dev和测试分支test,你在dev分支上有几个提交想应用到test分支上,但又
不想进行分支的merge操作,你此时可以如此操作:
1.使用git log命令将dev分支上的这几次提交commitId按照时间先后顺序记录下来,假如为c1,c2,c3
2.使用git checkout test命令切换到test分支
3.在test分支使用git cherry-pick命令,按照时间先后顺序将c1,c2,c3合并进来
git cherry-pick c1
git cherry-pick c2
git cherry-pick c3
4.然后将合并进来的提交推送到远程
git push
5.注意:git cherry-pick 命令只针对正常的提交commitId有效,merge提交记录的commitId无效
工作场景四——创建新分支
假设你由于新需求,需要拉取新分支,并且想把本地新分支备份到远程,你可以:
1.更新当前分支的最新内容
git pull
2.基于当前分支拉取新工作分支,并切换到新工作分支(你也可以先拉取新分支,再切换过去)
git checkout -b newWorkBranch
3.推送新分支到远程上备份,remoteBranchName为你在远程的分支名
git push origin localBranchName:remoteBranchName
工作场景五——分支合并
假如你因为新需求拉取了单独的开发分支dev1,现在新需求开发完毕,想将代码合并回主开发分支dev上,
此时你可以:
1.将dev1单独开发分支的代码拉取到最新
git pull
2.将dev主开发分支代码拉取到最新,因为待会要进行提交操作
git pull
3.将当前分支切换到主开发分支上,如果当前分支已在主开发分支上,忽略该操作
git checkout dev
4.将dev1分支的内容合并到当前分支上
git merge dev1
5.分支合并的过程是最容易产生冲突的地方,假设此时有冲突,需要解决冲突
git mergetool
6.冲突解决完后,进行提交,git commit后会进入vi界面,可以添加合并注释信息也可保存退出
git commit
7.将分支合并记录推送到远程
git push
结束语
本文中,还有一些场景没有覆盖到,比如多团队协作分支的管控,变基git rebase命令的使用场景等。但绝大部分使用命令行可以完成的工作,在本文中都可以找到借鉴之处。如果大家有补充,欢迎留言进行交流,我会一一回复。