Git 版本控制基础+进阶
)
Git-版本控制工具
什么是版本控制?
版本控制是指对软件开发过程中各种程序代码、说明文档等文件的变更进行管理,它将追踪文件变化,记录文件的变更时间、变更内容、甚至变更执行人等进行记录,同时对每一个阶段性变更(不仅仅只是一个文件的变化)添加版本编号,方便将来进行查阅特定阶段的变更信息,甚至是回滚。
Git-基础
git是什么?
Git是目前世界上最先进的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。
- 创建版本库
- 版本迭代
- 版本回滚
- 管理修改
- 创建远程仓库
- 创建分支
版本管理工具的分类
svn (集中式)
集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。
git(分布式)
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
下载git
下载地址:https://git-scm.com/
安装:默认安装(傻瓜式下一步下一步)
安装成功:
1.win+r 调出运行窗口
2.输入cmd 调出命令行工具(终端)
3.输入 git --version 显示git版本号,表示git安装成功
创建版本库
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所以,创建一个版本库非常简单
1.首先,选择一个合适的地方,创建一个空目录:
例如文件名为 first_rep的文件夹
2.通过git init命令把这个目录变成Git可以管理的仓库:
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
配置
当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改
git config user.name "你的姓名"
git config user.email "你的邮箱"
通过 --global
选项可以设置全局配置信息
git config --global user.name "你的姓名"
git config --global user.email "你的邮箱"
检查配置
# 打印所有config
git config --list
# 打印指定config
git config user.name
常规开发项目
创建项目,写代码
一定要放到git仓库目录下,因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。
状态
同时,git 又提供了四种不同的记录状态
- 已修改(modified)
- 已暂存(staged)
- 已提交(committed)
有一个特殊的状态
- 未追踪(Untracked)
区域
git 提供了三个不同的工作区,用来存放不同的内容
- 工作目录
- 暂存区域
提交到本地仓库
第一步,git status 检查版本库的状态
第二步,用命令git add 告诉Git,把文件添加到仓库
git add . 提交全部
git add 1.txt
# 添加多个文件
git add 2.txt 3.txt
# 添加整个目录
git add ./a
# 添加多个目录
git add ./b ./c
# 添加所有文件
git add .
第三步,用命令git commit -m '提交说明’告诉Git,把文件提交到仓库
第四步,提交时,如果没有配置会提示配置用户(以配置请忽略)
git config --global user.name ‘username’ //username是你的git账号
git config --global user.email ‘email ‘ //email是你的git邮箱
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
初始化一个Git仓库,使用git init命令。
添加文件到Git仓库,分两步:
- 使用命令git add ,注意,可反复多次使用,添加多个文件;
- 使用命令git commit -m ,完成。
版本回退
git commit -m "第一次提交"
git commit -m "第一次修改"
git commit -m "第一次提交修改"
你不断对文件进行修改,然后不断提交修改到版本库里,就好比玩RPG游戏时,每通过一关就会自动把游戏状态存盘,如果某一关没过去,你还可以选择读取前一关的状态。有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
在Git中,我们用git log命令查看,提交的历史记录
回退命名
git reset --hard "HEAD^" //加引号
git reset --hard HEAD^^ //加引号
git reset --hard HEAD~ 或者 git reset --hard HEAD~1
//^ 换成~, ~ 后面的数字表示回退几次提交,默认是一次
回退明细(后悔药)
回退的过分了,后悔了。只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个某个版本的commit id是33d9d598d123bb1327ba2abd9b73b725000abd9c
,于是就可以指定回到未来的某个版本:
git reset --hard 33d9d598d (版本号可以只写一部分不用写全)
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
Git提供了一个命令git reflog
用来记录你的每一次命令:
git reflog
远程仓库(GitHub)
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。怎么分布呢?最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
你肯定会想,至少需要两台机器才能玩远程库不是?但是我只有一台电脑,怎么玩?
实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
完全可以自己搭建一台运行Git的服务器,不过现阶段,为了学Git先搭个服务器绝对是小题大作。好在这个世界上有个叫GitHub的神奇的网站,从名字就可以看出,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。
1.自行注册GitHub账号
–新建一个远程仓库
2.本地Git仓库和GitHub仓库之间的传输是通过SSH加密 创建本地的ssh密钥
Git bash 下查看
// 创建一个密钥 在主分支执行一下命令
ssh-keygen -t rsa
执行完此命令之后 去C盘文件 用户 找到.ssh 文件 然后记事本打开
ls -al ~/.ssh 检查ssh keys是否存在
ssh-keygen -t rsa -C ''xxx'' 添加一个ssh
ssh-add ~/.ssh/id_res 生成新的key
-t = The type of the key to generate 密钥的类型
-C = comment to identify the key 用于识别这个密钥的注释 So the Comment is for you only and you can put anything inside. Many sites and software are using this comment as the key name. 所以这个注释你可以输入任何内容,很多网站和软件用这个注释作为密钥的名字
本地管理员目录会出现一个.ssh文件夹
里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
登陆GitHub,点击个人头像 选择settings 打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:
ssh -T git@github.com 检测是否建立连接成功
为什么GitHub需要
SSH Key
呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
最后友情提示,在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。
如果你不想让别人看到Git库,有两个办法,一个是交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。另一个办法是自己动手,搭一个Git服务器,因为是你自己的Git服务器,所以别人也是看不见的。这个方法我们后面会讲到的,相当简单,公司内部开发必备。
添加到远程仓库
1.创建远程仓库
2.本地仓库添加到远程仓库
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
从现在起,只要本地作了提交,就可以通过命令:
git push origin master
GitHub Pages
克隆远程仓库
上面,我们讲了先有本地库,后有远程库的时候,如何关联远程库。
现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。
首先,登陆GitHub,创建一个新的仓库,名字叫xxx:
现在,远程库已经准备好了,下一步是用命令git clone克隆一个本地库:
git clone git@github.com:wanglogn/QY121.git
如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。
小结
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
Git支持多种协议,包括https,但ssh协议速度最快。
Git-多人协作
分支的概念
分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN。
如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!
分支在实际中有什么用呢?
假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作
分支操作
-
查看分支:git branch
-
创建分支:git branch name
-
切换分支:git switch name或者git checkout name
-
创建+切换分支:git switch -c name或者git checkout -b name
-
合并某分支到当前分支:git merge name
-
删除分支:git branch -d name
-
恢复分支 git branch <branch_name> <hash_value>
解决冲突
当多个分支同时修改同一处代码时(同一个文件时),合并时就会出现冲突的情况
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,
git log也可以看到分支的合并情况
git log --graph命令可以看到分支合并图
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master(main)分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了
所以,团队合作的分支看起来就像这样:
多人协作
管理员现在远程仓库创建好仓库,并建立好相关分支,比如master分支,dev分支
当团队成员从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。
git push -u origin master //向远程仓库origin 的master 分支提交代码
git pull origin master //拉取远程仓库origin 的master 分支的代码
要查看远程库的信息,用git remote
用git remote -v显示更详细的信息
当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master(main)分支。不信可以用git branch命令看看
现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:
git checkout -b dev origin/dev
//等同于一下多个命令合并使用 git branch dev //新建分支 git checkout dev //切换分支 //把本地的dev分支与远程的dev分支关联起来,此时是没有拉去数据的
现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:
多人协作时,大家都会往master和dev分支上推送各自的修改。但是一般master是稳定的只是用来发布新版本分支,工作干活的分支是dev分支,一般团队成员只会提交dev分支。
推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
git push origin master
如果要推送其他分支,比如dev,就改成:
git push origin dev
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
- master分支是主分支,因此要时刻与远程同步;
- dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
- bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
- feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:
冲突的文件:
手动解决冲突:再次提交
git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push
如果 git pull失败了,原因可能是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:
git branch --set-upstream-to=origin/dev dev
因此,多人协作的工作模式通常是这样:
- 从远程克隆仓库到本地
- 拉取建立本地开发dev分支并常规开发
- 用git push origin 推送自己的修改;
- 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
- 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。
团队所有成员都需要在上面工作,所以也需要与远程同步;
- bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
- feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
[外链图片转存中…(img-K41DktfC-1663578811653)]
解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:
[外链图片转存中…(img-B0L95Tir-1663578811654)]