文章目录
- 1 版本控制系统的分类
- 1.1 集中式
- 1.2 分布式
- 2 Git的介绍
- 3 Git工作流程图
- 4 Git的安装与配置
- 4.1 Git下载与安装
- 4.2 Git基础配置
- 5 Git本地仓库常用命令
- 5.1 基础命令
- 5.1.1 初始化本地仓库
- 5.1.2 查看仓库状态
- 5.1.3 添加到暂存区
- 5.1.4 提交到本地仓库
- 5.1.5 查看日志
- 5.1.6 版本重置
- 5.1.7 忽略列表
- 5.1.8 为常用命令配置别名
- 5.2 分支命令
- 5.2.1 查看本地分支
- 5.2.2 创建本地分支
- 5.2.3 切换分支
- 5.2.4 合并分支
- 5.2.5 删除分支
- 5.2.6 解决冲突
- 5.3 标记命令
- 5.3.1 查看标记
- 5.3.2 创建标记
- 5.3.3 推送标记到远程仓库
- 5.3.4 切换标记
- 5.3.5 删除标记
- 5.3.6 拉取标记
- 6 Git远程仓库
- 6.1 注册码云账号
- 6.2 创建远程仓库
- 6.3 配置SSH公钥
- 6.4 操作远程仓库
- 6.4.1 添加远程仓库
- 6.4.2 查看远程仓库
- 6.4.3 推送到远程仓库
- 6.4.4 从远程仓库克隆
- 6.4.5 抓取和拉取
- 6.4.6 解决冲突
- 6.4.7 与远程仓库同步分支(2023-05-26补充)
身为一名程序员,我们除了自己单人开发项目,更多的情况需要多人协同开发。如果你使用硬盘拷贝或者发送压缩包之类的方式(虽然我们公司常用),那肯定是不如版本控制系统来的安全与高效。不考虑硬盘丢失或文件损坏等意外情况,拷贝的代码合并就很令人头疼,本文就来带大家快速上手分布式版本控制系统Git。
1 版本控制系统的分类
1.1 集中式
集中式版本控制系统的版本库是集中存放在“中央服务器”的,所有操作都需要联网,局域网或互联网。比如你修改了某个bug,但是你的电脑无法联网或者“中央服务器”宕机了,此时你就无法提交到“中央服务器”,就会影响到你版本管理。代表工具:SVN。
1.2 分布式
分布式版本控制是没有“中央服务器”的,每一台电脑都有完整的版本库,你可以在本地分支上提交代码、合并分支、解决冲突等操作。多人协作时只需要把各自的修改推送给对方,就能看到对方的操作记录了。代表工具:Git。
2 Git的介绍
Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。先看下面的示意图:
Git有本地仓库和远程仓库,它们俩都有完整的版本库,远程仓库的作用是方便开发人员之间代码的推送与拉取。
3 Git工作流程图
Git命令:
- clone(克隆):从远程仓库中克隆代码到本地仓库
- checkout(检出):从本地仓库中检出一个仓库分支然后进行修订
- add(添加):在提交前先将代码保存到暂存区
- commit(提交):提交到本地仓库
- fetch(抓取):从远程仓库更新版本库到本地仓库,不进行合并
- pull(拉取):从远程仓库更新版本库到本地仓库,并自动进行合并
- push(推送):将本地仓库的修改内容推送到远程仓库
4 Git的安装与配置
4.1 Git下载与安装
官网:Git官网
当前最新版是2.37.3,下载后运行程序,全部默认即可。安装完成后,在桌面或任何文件夹内右键,出现下面两个则表示成功:
Git GUI:Git提供的图形界面工具
Git Bash:Git提供的命令行工具
本文只介绍Git Bash中的命令,了解了命令后界面工具也很容易上手。
4.2 Git基础配置
安装完成后首先必须要设置用户信息,因为Git每次提交版本时都会使用该用户
- 打开Git Bash
- 设置用户信息(邮箱可以不是真实邮箱)
git config--global user.name'你的用户名'git config--global user.email'你的邮箱'- 查看配置信息
git config--global user.name git config--global user.email5 Git本地仓库常用命令
5.1 基础命令
5.1.1 初始化本地仓库
命令形式:
git init新建一个文件夹git_test,进入目录后打开Git Bash,输入上述命令,出现以下内容则表示初始化成功
此时在目录中会生成一个隐藏的.git文件夹,里面就是你的版本库信息,含.git文件夹的目录称为工作目录。
5.1.2 查看仓库状态
在工作目录中所有文件都有状态,新建文件是未跟踪(untracked),修改已有文件是未暂存(unstaged),添加到暂存区是已暂存(staged),提交到仓库是已提交(committed)。
命令形式:
git status输入以上命令,可以查看仓库当前状态
命令行提示说:在master分支上没有任何内容可以提交(创建或复制文件,然后使用“git add”命令来跟踪)
5.1.3 添加到暂存区
命令形式:
git add 文件名|通配符上述命令可以将工作区一个或多个文件添加到暂存区
添加单个文件:git add 文件名或目录名
添加所有修改的文件:git add .
举例说明:
在我们的工作目录git_test中新建一个txt文件叫file01(可以鼠标右键新建,也可以使用命令touch file01.txt),此时再执行git status命令会得到另一种提示:
命令行提示说:file01.txt是未被跟踪的文件,使用“git add 文件名”来包含要提交的内容 。
那我们这里就执行git add file01.txt命令,然后再执行git status命令,可以发现它的状态发生了改变:
命令行提示:file01.txt文件等待提交,使用“git rm --cached ” 可以退回未暂存状态。
上面的操作是新增一个文件,如果修改已提交的文件,则会更改状态为未暂存(unstaged)。假设你已完成5.1.4 提交到仓库的操作,然后修改file01.txt内容,添加count=1,然后再执行git status命令:
命令行提示:你的修改还没有暂存,不能提交!可以使用"git add "来更新要提交的内容,或者使用“git restore ”来丢弃工作目录中的更改。
那我们这里可以执行git add file01.txt或者git add .命令,然后再执行git status命令,可以发现它的状态发生了改变:
可以看到修改后的file01.txt文件被成功添加
5.1.4 提交到本地仓库
命令形式:
git commit[-m"注释内容"]通过该命令可以将已暂存的文件提交到本地仓库,[]中的部分表示可选,推荐必填。因为注释内容本身是必须的,如果在此处不填,下一步会打开其他编辑器(比如vim编辑器或其他)让你填写。
此时再执行git status查看状态
可以看到已经成功提交了,之前的No commits yet也消失了。注意:提交步骤需要先添加到暂存区再提交,下文说的提交到仓库指的这连续两步。
5.1.5 查看日志
命令形式:
git log[option]选项:
- –all 显示所有分支
- –oneline 将提交信息显示为一行
- –graph 以图的形式显示
通过该命令可以查看仓库的所以操作记录
此处commit后面的一长串字符串是版本号(commitID),后面括号内的HEAD表示当前所在分支,这里的意思是当前分支是master分支。Author表示作者,Date则表示提交时间,add file01就是我们填写的提交信息。
我们可以把上面几个常用选项全部加上,同时输出不加选项的日志进行比较:
commitID缩短了,用户信息和日期被省略了,只留下了关键的分支和注释,这样我们看日志会更加清楚明了。同时,缩略的commitID使用时效果是一样的,因为它是唯一的。
5.1.6 版本重置
命令形式:
git reset--hard commitID比如上面已经提交过两次,第一次新建file01文件,第二次在file01文件修改内容,所以有两次提交记录,执行上述命令后当前版本就会重置到第一次提交记录上
此时你在日志中已经查看不到第二次提交的记录了,那我们是否可以通过本条命令重置当前版本到第二次提交记录上?答案是可以的,我们可以通过上面第二次提交的commitID来执行命令。
可以看到日志中又出现了第二次提交的记录,但是如果我们清除了命令行工具的内容拿不到commitID,那还能重置回去吗?答案是可以的,这里需要使用另一条命令:git reflog。这条命令可以理解为显示所有引用日志,它可以查看所有的版本操作记录,包含提交与重置,而git log只显示当前版本(HEAD指针)及其之前的版本信息。
这里我们对比一下两条命令的输出,在git log下面只有两次的提交记录,而在git reflog下面有四条记录,从上到下是最新到最旧的记录,分别是:1. 重置到第二次提交,2. 重置到第一次提交,3. 提交更新文件file01.txt,4. 提交新建文件file01.txt。所以我们可以在这拿到想要的commitID。
5.1.7 忽略列表
我们新增了一个file02.txt文件,但是我们不想提交它,同时又希望使用git add .来一键全部提交,此时可以新建一个.gitignore文件,在里面写上file02.txt保存,下面我在保存前后分别执行git status查看了文件的状态
可以看到保存前未跟踪的文件里包含file02.txt文件,保存后则被忽略了。
5.1.8 为常用命令配置别名
有些命令加上选项会很长,但是又经常使用,比如git log --oneline --graph,此时我们可以给它配置别名。
- 打开用户目录,创建
.bashrc文件
打开【C盘】-【用户】,我这里用户目录是【Administrator】,打开目录后新建.bashrc文件。部分windows系统不支持创建点开头的文件,可以打开Git Bash执行touch ~/.bashrc。 - 在
.bashrc文件中输入以下内容
alias git-log='git log --all --oneline --graph'这样别名就设置成功了,我们可以执行git-log试试效果
发现确实和执行git log --oneline --graph是一样的,注意,.bashrc的内容修改后Git Bash需要重启才会生效。
5.2 分支命令
顾名思义,分支就是从主体上分出去的一部分。分支可以把开发环境和生产环境分离开来,避免开发影响到生产环境。最常用的分支有两个:master(生产)分支和dev(开发)分支。其他更细致的分支可以自行百度,这里举个例子, 比如leader让你开发一个新功能,应该在dev分支上创建一个新的分支feature/xxx,等到功能完成并且测试通过后先合并到dev分支上,然后leader审核通过后再合并到master分支上,这样可以在开发新功能的同时保证生产环境的稳定与安全。
5.2.1 查看本地分支
命令形式:
git branch
初始化仓库时默认创建master分支,可以看到当前只有master分支,并且当前所在分支就是master分支(颜色标绿且前面带有星号)
5.2.2 创建本地分支
命令形式:
git branch 分支名
可以看到已经成功创建了dev分支,但是当前所在分支还是master分支。
5.2.3 切换分支
命令形式:
git checkout[-b]分支名不加参数-b只能切换已创建的分支,添加参数-b可以在分支不存在时创建并切换。
5.2.4 合并分支
一个分支上的提交可以合并到另一个分支。比如前面提到的,master作为生产分支,我们新增功能模块是不该在上面开发的,可以新建一个dev分支,开发完成后再合并到master分支。
命令形式:
git merge 分支名举例说明:继续使用前面的例子,我们切换到dev分支然后创建一个file03.txt文件,按顺序执行git add .,git commit -m 'add file03',git-log。
此时可以看到最新的版本记录,分支是dev(HEAD指针指向的就是当前分支),注释内容是add file03,正是我们刚刚提交的。然后切换回master分支
可以看到master分支的版本记录只到update count=1这一步,这时我们想把dev分支的改动合并到master分支上来,就可以执行git merge dev。注意,我们要合并到master分支那就要切换到master分支,不能在dev分支上执行,那就没有效果了。
可以看到,dev分支上的改动已经成功合并到master分支上。
5.2.5 删除分支
命令形式:
git branch -d 分支名 // 通常情况使用
git branch -D 分支名 // 强制删除,在被删除分支比当前分支的版本更新时使用,比如dev比master多了一次提交,想要删除dev就必须使用该命令
5.2.6 解决冲突
当我们在两个分支上改动同一个文件,就会产生冲突。比如上面的例子,master和dev都有file01.txt文件,内容都是count=1,我们切换到dev分支,把内容改为count=2然后提交,再切换到master分支,把内容改为count=3然后提交,然后我们把dev合并到master上,
此时命令行提示:自动合并file01.txt失败,需要解决冲突然后提交结果。我们可以使用记事本打开file01.txt:
两条分支都修改了同一个文件的同一行,合并时Git不知如何取舍,所以干脆交给执行合并命令的人处理。从HEAD到虚线的是当前分支的内容,从虚线到dev的就是dev分支的内容。解决冲突很简单也很暴力,那就是留下你需要提交的内容,比如这里我要留下count=3那就删掉其他内容,
然后再重新提交一遍就行了
5.3 标记命令
标记(tag)用来标记提交(commit)历史中的某个特定节点,通常用来标记版本发布节点(v1.0,v2.0),它不会随着 commit 命令自动更新。
Git 分为两种标记:
1.轻量标记 lightweight tag:类似一个不会移动的分支,只是一个指向 commit 的指针,没有额外元数据。
2.附注标记 annotated tag(推荐生产发布使用):作为完整对象存放在 Git 对象库,带作者、日期、备注信息。
5.3.1 查看标记
# 列出所有本地 taggittag# 模糊查找 tag,例如查找 v1 开头gittag-l"v1.*"# 查找某个 tag 的详情(附注标记才能看到完整信息)gitshow v1.0.05.3.2 创建标记
# 创建轻量标记gittag v1.0.0-light# 创建附注标记gittag-av1.0.0-m"版本v1.0.0,正式上线"# 在指定 commit 上打附注标记gittag-av0.9.0 7a82bc3-m"历史版本v0.9.0"5.3.3 推送标记到远程仓库
注意:默认git push不会把 tag 推到远程仓库,需要单独推送 tag
# 推送单个taggitpush origin v1.0.0# 推送所有本地taggitpush origin--tags5.3.4 切换标记
tag 本质是 commit 的别名,可以直接检出
gitcheckout v1.0.05.3.5 删除标记
# 本地删除gittag-dv1.0.0# 远程删除gitpush origin-dv1.0.05.3.6 拉取标记
# 拉取远程所有tag到本地gitfetch--tags6 Git远程仓库
前面我们讲的都是本地仓库的操作命令,只有将远程仓库关联进来才是完整的Git工作流程。那么我们如何搭建Git远程仓库呢?其实可以通过互联网上提供的一些代码托管服务来实现,比如Github,码云(Gitee)等等。Github因为某些原因需要科学上网,我们这边就选择码云。
6.1 注册码云账号
码云是国内的一个代码托管平台,想要使用它的服务自然要先注册账号,注册流程直接略过。
6.2 创建远程仓库
在码云右上角有个加号,展开后点击【新建仓库】
然后填写仓库名称,系统会自动填充路径
其他都可以不用改动,然后立即创建
创建后的样子如上图所示
6.3 配置SSH公钥
现在远程仓库已经创建好了,我们想要把本地仓库推送到远程仓库,远程仓库需要验证我们的身份,有两种方式,一种是输入Git的账号和密码,一种是SSH公钥,推荐使用第二种。
首先打开Git Bash执行以下命令来生成公钥:
ssh-keygen-t rsa然后一直回车即可,如果公钥已经存在,则会自动覆盖。已经生成过的公钥,可以执行以下命令来查看:
cat~/.ssh/id_rsa.pub
这样我们就拿到需要的公钥了,然后要把它填到哪呢?打开码云,展开右上角头像菜单
根据上图点击【设置】,然后左侧菜单栏点击【SSH公钥】,把拿到的公钥填到公钥一栏里
标题一栏有时会自动填充,你也可以随便改,点击确定就添加成功了。那么如何验证公钥生效了呢?打开Git Bash执行ssh -T git@gitee.com,出现以下内容则表示成功
注意:如果你是第一次访问它,会询问你是否继续访问,这里输入 yes 然后回车,然后就能看到上图的内容了。
6.4 操作远程仓库
6.4.1 添加远程仓库
命令形式:
git remote add 远端名称 仓库路径- 远端名称,默认是origin
- 仓库路径,从远端服务器获取
我们打开码云上新建的仓库,从上面获取仓库的SSH地址
然后就能在Git Bash中执行命令
6.4.2 查看远程仓库
命令形式:
git remote[-v]-v/--verbose: 详细模式,不加-v只会列出远程仓库名字(比如origin),加-v额外显示远程仓库的地址,并且区分拉取(fetch)和推送(push)地址。
6.4.3 推送到远程仓库
命令形式:
git push[-u][<远程主机名><本地分支名>[:<远程分支名>]]如果直接执行git push,会提示当前分支和远程分支没有关联,需要我们推送当前分支并绑定关联。
方法有两种,第一种是:
git push origin masterorigin是通用的远程主机名,本地分支名和远程分支名相同时可省略,所以可以只有一个master。这种写法有一个弊端,就是每次都要写全。第二种方法是:
git push-u origin master参数-u是--set-upstream的缩写,作用是将当前本地分支(即master)和远程分支(也叫master)建立关联,之后的推送可以直接执行git push。
此时就成功推送到了远程仓库,并且创建了master分支,origin/master就是远程分支。我们打开码云上的仓库,可以看到文件全都推送成功了,历史提交的版本也都能查看。
我们也可以执行git branch -vv来查看本地分支和远程分支的关联关系,下图看到master后面跟着origin/master就说明关联成功了。
其他:git push命令除了-u还有其他参数,此处不做展开,有兴趣的可以执行git push -h查看自行研究。
回滚远程仓库:git push到远程仓库,正常推送会被拒绝,需要使用强制命令git push -f到远程仓库,完成回滚。
6.4.4 从远程仓库克隆
我们已经成功将本地仓库推送到远程仓库,假如我们的同事要协同开发,他就可以从远程仓库进行克隆。
命令形式:
git clone[远程仓库路径][本地目录名称]远程仓库路径就是仓库的url,可以使SSH或其他,如下图
这样就成功克隆了仓库。本地目录名称作用是修改本地项目名称,如果不加,本地项目的目录名称就是远程仓库的名称。比如上面,远程仓库名是git_test,Cloning into 'git_test'就表示在当前目录下创建了一个git_test目录,把远程仓库的内容克隆到该目录,我们可以加上git_testf_01,那么目录名就自动变了。
这里我们可以执行ls命令,它可以查看当前目录下所有文件
可以看到,确实是创建了git_test_01目录
6.4.5 抓取和拉取
抓取命令形式:
git fetch[<远程仓库名>[<分支名>]]提示:如果不指定远程仓库名和分支名,则抓取对应的分支。
继续使用上面的例子,在git_test目录下新增file04.txt文件并提交到仓库,然后推送到远程仓库。打开git_test_01目录,执行抓取命令
执行git-log可以看到最新的版本库是origin/master远程分支,但是本地master分支并不是最新版本库,因此需要执行git merge origin/master合并分支
此时本地master分支也是最新版本库了
拉取命令形式:
git pull[<远程仓库名>[<分支名>]]提示:如果不指定远程仓库名和分支名,则抓取对应的分支。
抓取和拉取的区别就在于,抓取不会自动合并,而拉取会在抓取后执行合并。我们可以在git_test目录下新增file05.txt文件并提交到仓库,然后推送到远程仓库。打开git_test_01目录,执行拉取命令
可以看到,拉取成功后本地master分支就是最新版本库了。
6.4.6 解决冲突
**本地仓库更改后,在推送到远程仓库前,应该先执行抓取,再执行推送。**假如用户A修改了file01文件并且推送到了远程仓库,用户B也在本地修改了file01文件,此时他想推送到远程仓库就会失败。
提示说远程仓库有你本地没有的工作,建议你先集成远程仓库的更改。这就是先执行抓取的原因。我们执行抓取后(通常执行拉取,此处抓取是为了),输出日志查看。
远程更改了count为8,本地更改了count为9,此时执行合并分支就会产生冲突。
如果觉得抓取+合并太麻烦,你也可以直接执行拉取(pull),效果是一样的。
图中HEAD表示本地,最后面的版本号表示远程。
出现冲突不用怕,解决冲突和前面本地仓库是一样的,就是把需要提交的内容留下,其余删除,然后提交到本地,再推送到远程。这里我们就把这段内容删除,留下count=10,然后提交。
这样我们就解决了冲突,最后一步就是把解决冲突后的文件推送到远程仓库。
6.4.7 与远程仓库同步分支(2023-05-26补充)
远程仓库新增一条分支,本地可以通过fetch命令同步分支
git fetch然后就能通过checkout命令切换到新的分支上
git checkout 分支名在vscode中可以在左下角切换分支
到这里,Git的入门知识就讲完了,希望这篇文章能对入门的伙伴有一点帮助。