# git入门教程
作为一名程序员,学会使用git不论是在工作中还是在学习中都是一个重要的技能,这里学习使用git不止是在工作中当作版本工具来管理项目,还要学会如何去使用github, 如何在上面进行学习和技术分享。
# 一、基本原理
作为一个代码托管平台,其核心思想就是版本控制和团队协作,它有四大框架,分别为远程仓库、本地仓库、工作区、暂存区。
当我们把代码从远程仓库克隆到本地,我们本地仓库就与远程仓库建立了连接,当然也可以手动进行关联。
在本地仓库可以创建多个分支工作区,在工作区进行代码修改,修改后通过 git add添加到缓存区,告诉git我们修改了哪些文件,接着通过 git commit 把修改的文件提交本地仓库,每次commit都会记录一个修改的记录,这对我们版本回退很有作用,所以要多commit记录修改了哪些东西。
提交到本地仓库后,我们就可以和远程仓库分支进行比较有没有冲突,没有就可以推送到远程仓库,这样远程仓库就和本地保持版本一致。
# 二、基础配置
# 1、安装Git
下载git安装包 https://gitforwindows.org/ (opens new window) 进行安装,默认安装就行。安装好后鼠标右键打开看到git bash here就说明安装好了。
# 2、全局配置
当我们第一次使用git时,需要配置一下git提交的账号和邮箱,告诉git我是谁。全局配置只需配置一次就可以了,个别项目也可以进行单独配置。
# 只需配置一次
git config --global user.name "$gitName" # $gitName 注册的git账户名
git config --global user.email "$gitEmail" # $gitEmail 注册的git邮箱
# 查看config配置
git config --global -l
# 重置配置
git config --global --unset user.name
git config --global --unset user.email
# 编辑配置
git config --global --edit
# 生成本地密码记录,解决每次重新输入秘密
git config --global credential.helper store
# 3、配置秘钥
配置秘钥,添加到git中,这样我们电脑本地就和远程github建立了桥梁,就不用每次拉取和提交进行输入密码了。我们以github的使用当做示例,其他平台操作也都是一样。
github地址:https://github.com (opens new window)
1、打开git bash here,输入以下命令建立ssh连接
ssh-keygen -t rsa -b 4096 -C "$gitEmail" # $gitEmail 注册的git邮箱
输入后一直回车,直到出现下面结果秘钥就生成好了,注意第三行的地址,根据这个地址找到.ssh文件夹下的id_rsa.pub文件,以记事本打开,里面就是秘钥,复制内容到github上去添加。这里不论是github还是其他平台生成秘钥方法都一样,生成后到平台设置里去添加就可以了。
2、针对不同账户配置多个SSH Key
执行1生成密钥命令,输入不同的邮箱,在第一步不要直接回车输入自定义文件名
在~/.ssh/文件夹里创建config文件,没有后缀,用记事本打开输入:
# 配置对应的地址使用对应的公钥文件
# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
# gitee
Host gitee.com
HostName gitee.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/gitee_id_rsa
3、github添加秘钥
点击设置
点击SSH and GPG keys -> New SSH key
把复制的秘钥添加进去
这样秘钥添加好后,就可以轻松的拉取和提交代码了。
参考链接:生成SSH秘钥 (opens new window)
# 三、项目初始化
# 1、创建远程仓库
登录github点击New创建一个仓库,输入仓库名和描述,选择公共还是私有项目,完成创建。
# 2、关联远程仓库
新建项目,初始化本地仓库后关联远程仓库,一般新建项目通过remote来进行连接远程仓库,remote可以关联多个远程仓库,进行多个仓库提交推送。如果是已有项目则直接克隆就会自动关联。
git init # 初始化本地仓库
git remote add $name $url # 关联远程仓库
# $name 自定义,关联远程仓库别名,以后拉取和提交都用这个名字
# $url 远程仓库地址https地址
git remote # 查看关联的远程仓库
git add . # 提交要提交的文件
git commit -am "xxx" # 提交到本地仓库
git push -u $name master # 提交到远程仓库master主分支 -u参数第一次提交使用
# 3、分支创建
创建分支,我们要知道根据哪个分支衍生新的分支,这样有利于版本控制。初始化项目,我们来创建项目需要的基础分支,如我们项目经常用的正式环境分支master,测试环境分支dev,和dev下各个开发分支。
git branch -a # 查看远程和本地所有分支
#基于master上创建分支
git checkout master
git checkout -b dev # 创建并切换到dev分支
git push $name dev # 提交到远程dev分支上
#基于dev创建分支
git checkout dev
git checkout -b dev_cz # 创建开发分支
git push $name dev_cz # 提交到远程dev_cz分支上
#这样我们每个分支就和远程分支保持同步了,然后在我们自己的分支上进行开发和提交
# 4、克隆同步
在项目初始化时我们可以一个一个去创建分支来提交远程,进行远程分支同步,但当我们克隆时,本地只默认克隆同步master主分支,其他远程分支我们并没有同步过来,如果这时我们克隆了别人的项目要基于dev分支来进行开发该怎么办呢?我们要直接切到远程分支,然后根据远程分支创建本地分支,这样就可以和远程dev保持同步。
git clone # 克隆远程仓库
git branch -a # 查看远程和本地所有分支
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/dev_cz
git checkout remotes/origin/dev # 切换到远程dev分支
git checkout -b dev # 根据远程dev分支创建并切换到本地dev分支
# 简单方法
git checkout dev # 直接基于远程分支创建本地dev
#基于dev创建分支
git checkout dev
git checkout -b dev_jcc # 创建开发分支
git push $name dev_jcc # 提交到远程dev_jcc分支上
# 四、git开发规范
团队多人协作开发一个项目,最重要的就是版本控制,一个合理的版本控制规范可以让成员之间高效率的协作开发,稳定的迭代版本。习惯使用版本控制工具,对以后不论在哪个团队都能更快的融入开发中。
# 1、分支规范
一般,我们新建一个远程仓库,规定主分支master作为线上正式版本发布分支,dev分支用来作为测试分支,然后创建一个bug分支,专门用来解决线上问题。基础分支创建好后,团队各个成员基于dev创建自己的开发分支,每个成员只允许一个分支进行提交,开发人员在自己的分支上进行开发,在本地仓库创建可以多个分支,用于多个任务开发,然后统一合并到自己的开发分支进行提交远程分支。
我们规定,主分支只能用于线上发布,只允许发布时从dev分支进行提交合并,除了解决线上bug分支外,其他开发分支禁止直接合并到主分支上,并且不允许开发人员有合并权限,只能管理员才能进行合并。
对于dev分支,也只允许开发人员自己的分支进行提交合并,不允许成员自己创建的本地分支进行合并,防止污染dev和master分支。对于项目管控严一点的,dev也不允许开发分支有直接合并权限,在对代码进行审核后才能进行合并,也是防止污染测试环境,当然这需要整个研发团队有着完整的规范和约束执行力。
# 2、commit提交规范
每次commit提交代码时我们都是要描述清楚本次修改了什么,并且有专门的提交格式,这里我们推荐使用 type: description 格式进行提交。
type 是 commit 的类别,只允许如下几种标识:
init:项目初始化
feat:新功能
fix:修复bug
to:多次修复bug
docs:文档
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
style:代码格式改变
merge:代码合并
revert:撤销
update:更新
test:增加测试代码
build:构建工具或构建过程等的变动
perf:性能优化
version:版本迭代
description 是对本次提交的简短描述,推荐以动词开头,如: 设置、修改、增加、删减、撤销
git commit -am "feat:新增用户模块"
git commit -am "style:修改某某样式"
# 3、多人协作
现在我们开始基于创建好master和dev分支的项目进行团队开发,假如有团队成员cz和jcc。
cz和jcc同志领到任务后,分别在自己电脑拉取代码进行开发。
git clone <remote-url> # 克隆项目
这时查看我们拉下来的项目,发现本地只有master分支。
git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
这时我们要根据远程dev分支创建本地分支,不能直接从本地创建,要不然会造成本地和远程不同步。
git checkout remotes/origin/dev
git checkout -b dev
然后cz和jcc就可以创建本地开发分支进行愉快的开发了。
git checkout -b dev_cz # cz本地分支
git checkout -b dev_jcc # jcc本地分支
当各自的任务开发完成后,就可以把代码提交到远程,然后打包测试。 我们在每次提交代码到远程时,都要先拉取最新的dev分支,进行代码对比,没有冲突后才能提交到自己的远程分支。
cz同学:
git add .
git commit -am "feat:新增某某模块"
git pull origin dev # 拉取远程,解决冲突
git push origin dev_cz # 推到自己的远程分支
cz同学提交到远程后,把代码合并到dev分支后jcc再提交进行合并,这里合并远程分支可以在远程仓库上进行合并,也可以本地使用merge进行远程分支合并。 jcc同学:
git add .
git commit -am "feat:新增某某模块"
git pull origin dev # 拉取远程,解决冲突
git push origin dev_jcc # 推到自己的远程分支
当两个人开发完成后把代码合并都合并到dev远程,dev上就是最新的代码,这时切到dev拉取最新代码,打包发布测试版本,进行测试,测试完成后,把dev合并到master分支,然后基于master分支发布版本。
# 五、常见操作问题
我们在开发任务时,要多进行commit,每个相关小功能都要提交记录,这样如果出现临时版本回退或者某个功能的回退,我们都可以尽量避免代码的二次改动。否则当我们改了很多代码,结果这时只需要临时更新某个几个小功能,回退不是不回退也不是,都要改动很大。
# 1、多任务开发
当我们同时需要执行多个任务,一般都是在自己的开发分支上一个一个任务接着开发,都在一个分支上写,最后写好再进行提交,这种流程是不对的,最好每个大的任务我们都创建新的分支进行开发,当我们把所有任务都开发完成后,分别把各个任务分支合并到我们自己的开发分支上,然后提交远程开发分支进行合并。
git checkout dev_cz # 切到dev_cz
git pull origin dev # 拉取最新代码
git checkout -b dev_cz_1 # 任务一分支
git checkout -b dev_cz_2 # 任务二分支
# 开发完合并分支
git checkout dev_cz # 先切到开发分支,再合并其他分支
git merge dev_cz_1 # 合并分支,解决冲突
git merge dev_cz_2 # 合并分支,解决冲突
# 提交代码
git pull origin dev # 拉取最新代码
git push origin dev_cz # 提交远程合并分支
# 2、临时任务开发
当我们在开发过程中临时增加一个紧急任务需要开发,这时正常进行的任务已经开发了一半,我们要先把本地开发进行commit保存,然后再切换到dev新建分支开发,最后提交到远程。
# 当前分支 dev_cz
git add .
git commit -am "xxx" # 提交当前分支更改
git checkout dev # 切到dev
git pull origin dev # 拉取最新代码
git checkout -b dev_term # 临时分支
# 开发好提交远程分支进行合并
...
git push origin dev_trem
# 3、临时回退
开发中经常遇到当我们开发了很多功能后,需要临时回退到某一个功能,然后根据这个功能进行其他任务开发,而这个功能后的开发后面也是需要,两边都不能删除,这时就体现了经常commit的好处了,我们可以通过reset版本回退回退到我们想要的版本,然后根据这个版本创建新的分支开发新任务,开发完后切到当前分支,通过reset回到后面开发的功能点,最后合并另一个分支。
1、版本回退到某个分支
# 当前开发分支 dev_cz
git reflog # 查看所有操作记录
# 记住我们最新commit提交的操作记录,后面还要回来
git reset --hard 4807146 # 回到某个commit
git checkout -b dev_back # 创建新分支开发
# 保留前后代码,切换到原分支最新代码进行合并
git checkout dev_cz # 回到原分支,这时代码还不是最新,
git reset --hard 982b341 # 回到最新commit,此时是回退前的代码
git merge dev_back # 合并分支,解决冲突保留双发代码
...
git push origin dev_cz
# 4、线上bug修改
需要添加release发布分支进行测试。dev分支只用来开发。每次发布版本或者修改bug后先把代码提交到release分支上进行测试,然后在推送到master分支进行打包上线。
当线上出现bug,如果是重大bug无法立即修复,则直接回滚版本,代码回滚到上一个正式版本,先恢复线上正常访问,然后再慢慢排查问题,等到问题排查出后再测试打包发版上线。
如果是线上出现某些不会影响正常使用的bug,需要立即解决,我们就需要在主分支上直接创建bug分支进行修改,然后合并到主分支测试打包发布bug版本。
发布好后,我们开发分支也要同步该代码,一级一级的去同步远程版本,否则我们开发分支就无法和主分支保持版本同步,导致无法提交。
git checkout master
git pull origin master
git checkout -b fix_bug # 创建bug分支
...
git push origin fix_bug # 解决问题提交远程合并到主分支
# 同步其他分支代码
git checkout dev
git pull origin dev # 拉取dev最新代码
git merge fix_bug # 合并bug分支/或者直接拉master/或者远程合并到dev
git push origin dev # dev分支保持同步
git checkout dev_cz
git pull origin dev # 现在开发分支就是同步了最新版本
git push origin dev_cz
# 5、打包发布
代码开发完成合并到master分支,我们要发布版本所对应的更新信息和代码包,一般都是借助git工具的 releases 功能进行发布。
github发布:
进入仓库,右侧介绍下面点击releases发布
添加版本发布信息然后发布
gitlab发布:
进入仓库,左侧项目概述点击发布
点击发布,新建发布,填写发布信息
# 六、其他问题
# 1、gitignore忽略提交文件
有时,项目中有些文件不想添加到git进行提交,比如打包的dist文件,依赖包node_modules等杂项文件。我们可以在项目中创建.gitignore文件设置忽略。
忽略规则:
*.a # 忽略所有 .a 结尾的文件
!lib.a # lib.a除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/目录下的所有文件,过滤整个build文件夹;
doc/*.txt # 会忽略doc/notes.txt但不包括 doc/server/arch.txt
bin/: # 忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin: # 忽略根目录下的bin文件
/*.c: # 忽略cat.c,不忽略 build/cat.c
debug/*.obj: # 忽略debug/io.obj,不忽略 debug/common/io.obj和tools/debug/io.obj
**/foo: # 忽略/foo,a/foo,a/b/foo等
a/**/b: # 忽略a/b, a/x/b,a/x/y/b等
!/bin/run.sh # 不忽略bin目录下的run.sh文件
*.log: # 忽略所有 .log 文件
config.php: # 忽略当前路径的 config.php 文件
/mtk/ # 过滤整个文件夹
*.zip # 过滤所有.zip文件
/mtk/do.c # 过滤某个具体文件
需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中,如下:
!*.zip
!/mtk/one.txt
.gitignore常见示例:
# file
node_modules
dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
# Package files
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# 2、git pull 和git fetch的区别
git fetch和git pull 都是从远程上拉取最新代码,git fetch从远程拉取代码不会自动和本地仓库代码进行合并,需要手动进行合并。而git pull就会自动和本地仓库代码进行合并,有冲突时才会显示出来。
git pull = git fetch + git merge
git fetch origin dev
git merge dev # 这个待实验
# 3、撤销操作
一般,我们修改好代码后,进行了commit提交,这时想撤回提交,之前一直使用reset版本回退来撤销,但是会把我们的修改也会给撤销掉,我们想保留修改的文件,又想撤销commit提交该如何操作。
git log # 查看提交记录
git reset --soft HEAD^ # 撤销到某个提交记录,并保留之前的修改
# 七、常见命令
# 1、远程关联
# origin 为自定义仓库名
# 初始化本地仓库
git init
# 连接远程仓库
git remote add origin <remote-url>
# 查看远程仓库名
git remote
# 查看远程仓库地址
git remote -v
# 修改远程仓库
git remote set-url origin <remote-url>
# 删除远程仓库
git remote rm origin
# 更新远程分支到本地
git remote update origin --prune
# 2、克隆操作
git clone <remote-url>
# 克隆指定分支
git clone -b dev <remote-url>
# 只克隆最近一次commit提交的内容
# 浅克隆
git clone --depth 1 <remote-url>
# 指定分支
git clone --depth 1 --branch dev <remote-url>
# 3、分支操作
#查看分支
git branch -v
#查看远程分支
git branch -a
# 本地新建分支
git branch dev
# 切换分支
git checkout dev
# 新建并切换分支
git checkout -b dev
# 重命名分支
git branch -m oldBranch newBranch
# 删除分支
git branch --delete dev
# 删除远程分支
git push origin --delete oldBranch
git push origin newBranch # 将重命名后的分支推到远端
git branch --set-upstream-to origin/newBranch #把修改后的本地分支与远程分支关联
# 4、分支合并
# 查看分支
git branch -a
* dev
dev_cz
master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/dev_cz
# 合并分支
git merge <branch name>
# 中断合并
git merge --abort
# 5、提交远程
# 查看状态
git status
# 查看修改前后对比
git diff
# 提交要提交的文件
git add .
# 提交到本地仓库
git commit -am "xxx"
# 拉取远程,初始化不需要
git pull origin master
# 提交到远程仓库master主分支 -u参数第一次提交使用
git push -u origin master
# 本地分支dev推到远程对应分支并新建该分支
git push origin dev:newbranch
# 6、版本回退
# HEAD^ 版本号
# 查看所有操作记录
git reflog
# 查看版本提交记录
git log
# 不删除工作空间改动代码,撤销commit,并且撤销git add . 操作
git reset HEAD^
# 不删除工作空间改动代码,只撤销commit,不撤销git add .
git reset --soft HEAD^
# 和git reset一样 撤销commit和add
git reset --mixed HEAD^
# 删除工作空间改动代码,撤销commit,撤销git add .
git reset --hard HEAD^
git checkout HEAD^ # git checkout 和 git reset --hard 一样
# 修改commit注释
git commit --amend
# 7、其他命令
# 取消git忽略文件大小写
git config core.ignorecase false
# 八、github使用和理解
github是一个很好的代码托管平台,里面有很多优秀的开源项目、学习资料等,是全球最大的程序员聚集地,我们可以在上面学习新的技术,学习优秀项目的编码经验,我们也可以参与开源项目的维护,贡献自己一份力量。
当我们要学习某个新技术时,我们第一反应应该是去github找这个技术的官方仓库,官方仓库记录着这个技术如何迭代和遇到问题。查看官方文档能帮我们解决大部分问题,如遇其他问题,可以去仓库的Issues进行查看和提问,上面有很多相似的问题,最后解决不了我们可以再去百度,这就是学习技术的一个大概流程。
# 1、如何使用
注册并登录github账号。
github地址:https://github.com (opens new window)
git文档:https://docs.github.com/cn (opens new window)
1、项目和代码搜索,想要查找什么技术或相关项目都可以在这搜索。
2、该项目的分支和提交版本。
3、该项目的代码地址。
4、该项目的介绍和官方文档,当然在代码下面也有文档。
5、对该项目进行收藏
6、该项目的提问,一些bug和建议都可以在这进行提交给项目管理者,项目管理者会很大程度上根据这对项目进行优化和升级。
7、Fork 把开源项目复制一份镜像到自己账号下,这样我们就可以在我们自己的仓库里进行任意修改,然后再提交到源项目,源项目审核后进行合并。
8、提交我们自己账号下的镜像到源项目上请求合并。
# 2、开源项目协作
github可以创建公共项目和私有项目,公共项目就是大家都可以访问和搜索到,私有项目只有指定的人员或者团队内部才能成为访问。如果想参与其他开源项目代码贡献该如何做呢,那我们首先来区分私有项目和开源项目的协作方式。
私有项目可以邀请指定开发者参与贡献,也可以创建团队空间然后共同开发项目,和我们工作中常用的协作开发一样。开源项目如果想参与开发,你就不能像私人项目那样直接关联人家仓库,把自己修改的代码直接提交人家仓库上去了,那样就完全乱套了。所以就有了Fork概念,我们先从源仓库那里拷贝一份镜像到我们自己远程上,然后把自己的远程上克隆到本地进行修改,这里从远程到本地就是正常git提交流程了,把修改后提交到自己的远程上,这样你修改的东西就不会影响到源仓库的代码,当我们修改好后,我们就可以提出请求合并申请,源项目管理者审核后就可以合并申请了。
下图是私有项目和开源项目的区别,Fork不属于我们日常的git提交流程,它只适用于开源协作跨项目合并请求。
# 3、Fork开发流程
1、fork源项目
我们以arco-design-vue (opens new window)开源项目来说,进行项目,点击右上角Fork按钮。
fork后,就拷贝了一份镜像到自己的账号下了,可以看出我们账号里的镜像是来自arco-design
2、克隆到本地
fork好后,就可以像我们自己创建的项目一样就行开发了,执行流程和我们正常的git流程一样,克隆、修改、合并、提交都是一样的。
3、修改代码
克隆下来,修改代码,提交到自己账号的远程上。进入自己账号下的远程仓库,可以看到有一条提交记录,点击去看我们修改的内容。
4、提交申请
我们经过一顿修改后,现在终于可以要把代码合并到开源项目上了,点击 Create pull request按钮
或者点击Pull requests 进入,再点击 New pull request 进入也行
5、填写提交信息
填好提交信息后,点击Create pull request 按钮进行提交,然后就等着开发者审批通过就行了,这期间可能还会回炉重造。
6、提交审核
如果你是源项目拥有者,那么你可以审核那些提交过来的申请,点击 Pull requests 里面有很多条提交记录,点进去,查看提交信息和代码,点击 Merge pull request 合并就可以了。
7、同步源仓库
源项目可能一直在更新,我们自己的仓库就会落后版本,我们要手动进行更新,和我们拉取代码一样。
1、在远程仓库上更新
直接点击 Sync fork 进行同步,同步时注意自己提交的代码和已有代码的冲突。
2、本地仓库更新
在我们本地克隆的仓库更新,我们直接在本地仓库关联源项目仓库的地址,然后拉取源仓库代码,和本地仓库代码进行合并,最后在推到自己账号的远程仓库,远程就同步了。
查看当前远程仓库
git remote -v # 查看远程仓库地址
origin https://github.com/changzhengithub/arco-design-vue.git (fetch)
origin https://github.com/changzhengithub/arco-design-vue.git (push)
关联源项目仓库地址
git remote add upstream https://github.com/arco-design/arco-design-vue.git
git remote -v
origin https://github.com/changzhengithub/arco-design-vue.git (fetch)
origin https://github.com/changzhengithub/arco-design-vue.git (push)
upstream https://github.com/arco-design/arco-design-vue.git (fetch)
upstream https://github.com/arco-design/arco-design-vue.git (push)
拉去源仓库代码
# 全部更新
git fetch upstream
# 拉取某个分支
git pull upstream master
然后和本地分支修改进行合并冲突,提交到自己的远程上
git push origin master
...
git push origin master
其实到这里,就可以看出Fork其实也是和git流程概念一样,就是把我们本地同远程的关系变为本地同远程,远程同源项目的步骤,两步的基本概念都是一样的。
# 参考链接:
https://github.com (opens new window)