大家好,我是中国码农摘星人。
欢迎分享/收藏/赞/在看!
作为一名人类高质量程序员,进厂的首要任务就是熟悉项目,而熟悉项目的第一步就是拉取同事的代码!作为进厂的第一行代码,熟悉 Git 等版本控制工具的相关操作能极大地方便我们在团队中进行协同项目的开发!
一、Git 简介
Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。与常用的版本控制工具 CVS,Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
二、版本控制
版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。简单讲就是备份和记录,接下来我们要了解三种不同版本控制的发展历程。
2.1 本地版本控制系统
人们把项目拷贝到本地磁盘上进行备份, 然后以命名方式来区分,这种做法好处是简单,但坏处也不少比如备份比较多或许就会混淆不同版本之间的区别, 那为了解决这个问题,有人就开发了一个本地版本的管理系统,它的结构图如下:
本地版本管理就是把版本号存入数据库来记录文件的历次更新差异。
2.2 集中化版本控制系统
本地版本控制系统能够将不同版本的文档保存下来并且借助版本记录,可以很方便定位相关文件但又引入了新的问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法 。
这样做的好处是解决了人们开发协同的问题,但是把所有的代码提交到同一台服务器上有一个很明显的问题就是单点故障。如果这台服务器宕机了,那所有人都不能提交代码,还有如果这台服务器如果磁盘发生故障,碰巧没做备份,或者备份不够及时,就还是会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
2.3 分布式版本控制系统
为了解决集中化版本管理所带来的问题,分布式版本管理控制系统(Distributed Version Control System,简称 DVCS)就应运而生了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端不只是提取出最新版的文件快照,而是把最原始的代码仓库镜像到本地。这样一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份。
所以综上来看的集中化版本控制系统是对本地版本控制系统的一次升级,因为它加入了协同操作,分布式版本控制系统是对集中化控制系统的一次补充,使之更加完善。
三、Git 安装
3.1 Homebrew 安装
Homebrew 是一款 Mac OS 平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径的情况,十分方便快捷。
安装命令
- 命令1:(这个命令不好使会报错,如果报错尝试使用命令2)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- 命令2:(这是一个脚本,同样可以安装Homebrew)
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
3.2 安装 Git
打开终端(Terminal),输入命令
brew install git
3.3 验证安装
输入命令 git --version
四、Git 操作
4.1 用户配置
创建一个全局用户名、全局邮箱作为配置信息
# 配置用户名称
git config --global user.name "Your Name"
# 配置用户邮箱
git config --global user.email "Your Email"
# 查看配置信息
git config --list
注: git config
命令的 --global
参数,用了这个参数,表示我们这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和 Email 地址。
配置信息可以更改,以后想要更改使用上面指令就可以。
4.2 Git 文件的状态与工作模式
使用 Git 操作文件时,文件的状态有以下三种:
状态 | 描述 |
---|---|
已提交(committed) | 已提交表示数据已经安全的保存在本地版本库中。 |
已修改(modifified) | 已修改表示修改了文件,但还没保存到版本中。 |
已暂存(staged) | 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。 |
针对Git 文件的三种状态,这里需要了解 Git 项目的三个工作区域:工作区、暂存区和 Git 仓库。
分类 | 描述 |
---|---|
工作区 | 简单的理解为在电脑里能看到的目录,比如自己创建的本地项目目录 |
暂存区 | Git 的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫 index)的暂存区。 还有 Git 自动创建的第一个分支master,以及指向 master 的一个指针叫 HEAD。 |
Git 仓库 | 工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。 |
基本的 Git 工作流程描述如下:
- 在工作区中修改某些文件。
- 对修改后的文件进行快照,然后添加到暂存区。
- 提交更新,将保存在暂存区域的文件快照永久转储到 Git 仓库中。
流程图如下:
4.3 创建版本库并提交文件
版本库又名仓库,可以简单理解成一个目录,这个目录里面的所有文件都可以被 Git 管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
4.3.1 初始化版本库
开始一个新的项目,初始化新的代码仓库,要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:
# 初始化新的代码仓库
git init
4.3.2 添加文件到暂缓区
-
在 .git 同级目录下添加 test.txt 文件后,使用
git status
查看工作目录与暂存区文件状态# 创建文件 touch test.txt # 查看工作目录与暂存区文件状态 git status
git status
命令用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了,哪些没有,哪些文件没有被 Git tracked 到。
-
执行
git add
命令添加文件到暂存区git add
通常是通过git add <path>
的形式把<path>
添加到索引库中,<path>
可以是文件也可以是目录。 git 不仅能判断出<path>
中,修改(不包括已删除)的文件,还能判断出新添的文件,并把它们的信息添加到索引库中。# 添加指定新增或者改动过的文件 ( 添加所有:git add . ) git add test.txt
-
提交文件到本地版本库
文件被添加到暂存区后,执行
git commit
命令提交暂存区文件到本地版本库中。git commit
命令用于将更改记录(提交)到存储库。将索引的当前内容与描述更改的用户和日志消息一起存储在新的提交中。通常在执行提交时 在git commit
命令后跟上-m
属性,加入本次提交的记录说明,方便后续查看提交或改动记录。# 提交变更到本地版本库 git commit -m "注释信息"
-
查询提交日志信息
git log
命令用于显示提交日志信息。# 显示提交的日志记录 git log
五、远程仓库
Git 是一个分布式版本控制系统,同一个 Git 仓库,可以分布到不同的机器上。截止目前,并没有看到分布式的环境,因为以上的操作都在在本地发生的。对于 Git,除了前面提到的本地版本库外,Git 支持远程仓库的托管服务即使用者可以将本地版本库中的文件托管到远程服务器进行存储,这样就极大的方便开发,无论你走到哪,只要你的机器能够联网,就可以通过远程的仓库地址得到一份相同的项目库文件,并且下载到本地的文件版本记录与远程文件版本保持一致,并且可以很方便的实现多人协同开发操作。
对于 Git 远程仓库,GitHub 是比较知名的一个;而国内比较知名的当属 码云 了。当然除了这些远程仓库外,在公司,有的公司出于安全考虑,可能会自己搭建一套 Git 服务区来自 Git 的远程仓库,对于内部仓库会有专门人员来进行维护操作。
5.1 Github
5.1.1 创建 SSH key
Git 关联远端仓库时候需要提供公钥,本地保存私钥,每次与远端仓库交互时候,远端仓库会用公钥来验证交互者身份。通过终端命令创建 SSH key,期间会提示key文件保存位置、是否覆盖、输入密码、再次输入密码。
ssh-keygen -t rsa -C "your_email@youremail.com"
生成密钥后,在 本地的/Users/当前电脑用户/.ssh 目录下会生成两个文件 id_rsa、id_rsa.pub,id_rsa 文件保存的是私钥,保存于本地,id_rsa.pub 文件保存的是公钥,需要将里面内容上传到远端仓库。
5.1.2 获取字符串
- 输入
cat /Users/hayden/.ssh/id_rsa.pub
指令(我这里用的是绝对路径),查看id_rsa.pub
文件中内容
5.1.3 添加 Key
登录GitHub账号(默认已经注册了GitHub账号),在Settings
中的左侧边导航中找到SSH and GPG keys
,点击左面面板右上方的New SSH key
添加。填写完毕后点击Add SSH key
按钮
5.1.4 链接验证
输入命令,输入 “yes”,回车。看到欢迎提示即添加成功!
ssh -T git@github.com
5.1.5 提交本地项目到 GitHub
-
创建一个仓库
在页面的最右上角,你的头像的左边,点击“+”,在弹出的下拉选项中选择 “New repository”。
-
绑定远程地址到本地
进入前面已经初始化好的仓库目录,关联远程仓库
# 关联远程库 git remote add origin 远程仓库地址
根据 GitHub 说明,执行 SSH 推送,首先绑定远程地址到本地执行命令
git remote add origin git@github.com:nianan0908/helloworld.git
-
推送本地库到远程
# 查看当前分支 git branch # 分支重命名 git branch -M main # 将本地的分支推送到远程 git push -u origin main
注:如果第一次访问,需要输入 GitHub 的对应的用户名和密码。
5.1.6 克隆远程项目到本地
获取远程项目的地址
打开终端,进入项目想要存放的目录(示例放在桌面)
输入命令,克隆项目
# 克隆远程库的工程
git clone 远程项目地址
修改项目内容,执行相关操作
# 将修改后的文件添加到仓库 (.代表所有的文件)
git add .
# 将文件提交到仓库
git commit -m "注释内容"
# 上传到 GitHub
git push
5.2 Gitee
5.2.1 创建 SSH key
步骤与GitHub的相同,这里不再重复。
5.2.2 添加 Key
5.2.3 码云新建仓库
5.2.4 提交本地项目到码云
mkdir 仓库名称
cd 仓库名称
git init
touch README.md
git add *
git commit -m "注释信息"
git remote add origin 码云上的仓库地址
git push -u origin master
Username for 'https://gitee.com': 码云上的邮箱账号
Password for 'https://nianan0908@163.com@gitee.com': 账号对应的密码
如果已有本地仓库
cd 本地仓库目录
git remote add origin https://gitee.com/nian-an/helloworld02.git
git push -u origin master
5.2.5 克隆远程项目到本地
获取远程库的地址
输入命令,克隆项目
六、Git 分支
开发企业项目中在使用 Git 或者其他类似版本控制软件对项目版本进行管理时,多人合作的项目在开发时通常不会直接在主干 master 上进行操作,而是重新开辟新的分支,在新的分支上进行开发、调试等操作,当项目调试通过时才会将分支项目的代码合并到主干中,这是在实战中比较好的一种策略,特别是多人协同开发一个项目的情况下尤其明显。
6.1 基本命令
命令 | 描述 |
---|---|
git branch | 查看所有分支,并且 * 号标记当前所在分支 |
git branch <new_branch_name> | 新建分支 |
git checkout | 切换到指定分支 |
git checkout -b <new_branch_name> | 新建分支并切换到新建分支 |
git branch -d <branch_name> | 删除指定分支 |
git merge <branch_name> | 合并分支 |
git branch (-m | -M) <old_branch> <new_branch> | 重命名分支。 如果 new_branch 已经存在,则使用 -M 强制重命名;否则使用 -m 重命名。 |
git branch -a | 查看本地与远程分支 |
git push origin <branch_name> | 推送本地分支到远程 |
git checkout -b <local_branch_name> origin/<remote_branch_name> | 拉取远程分支,并在本地创建新分支且切换到新分支 |
git pull origin <remote_branch_name> | 从远程分支获取代码并合并本地 |
6.2 分支操作
6.2.1 查看分支
git branch
:查看所有的分支,* 号标记当前所在分支
6.2.2 新建分支
git branch dev
:新建一个名称为 dev 的分支
6.2.3 切换分支
git checkout dev
:切换到名称为 dev 的分支
6.2.4 新建并切换分支
git checkout -b dev02
:新建一个名称为 dev02 的分支,并且切换到该分支
6.2.5 删除分支
git branch -D dev02
:删除名称为 dev02 的分支
注:不能在待删除的分支上,执行删除当前分支操作!
6.2.6 合并分支
git merge dev
:在 dev 分支添加文件并提交,再切换到 master 分支,将 dev 分支的内容合并到 master 分支
6.2.7 重命名分支
git branch -m dev dev01
:分支重命名,将名称为 dev 的分支,重命名为 dev01
6.2.8 查看分支
git branch -a
:查看本地与远程的所有分支
6.2.9 推送分支
git push origin dev01
:将名称为 dev01 的本地分支推送到远程库
远程库中的分支列表
6.2.10 拉取分支
git checkout -b dev02 origin/dev02
:将远程库中的 dev02 分支拉取到本地,在本地创建分支 dev02 并切换到该分支
远程在线创建新分支 dev02
6.2.11 更新操作
git pull origin dev02
:拉取远程分支 dev02 的内容,并合并到本地
远程在线新建文件
拉取远程分支中的内容并合并本地
6.3 分支冲突
模拟两个用户操作同一分支同一文件的场景:
- 用户A 与 用户B:分别新开终端窗口,克隆项目
- 用户A 与 用户B:分别拉取远程分支 dev02,本地切到 dev02 分支
- 用户A:在本地修改 dev02 分支的 data.txt 文件,并将本地用户A提交的 data.txt 文件推送到远程 dev02 分支
-
用户B:在本地修改 dev02 分支的 data.txt 文件,并将本地用户A提交的 data.txt 文件推送到远程 dev02 分支
此时冲突出现,原因是另外一个用户推送的文件与当前客户端推送内容存在冲突。
解决方式:Git 已有对应提示,Push 之前先执行 Pull 操作,将远程文件拉取到本地,解决完冲突后再次执行Push 操作
-
解决冲突
先执行 Pull 拉取操作
查看冲突文件内容
Git 用 <<<<<<<,=======,>>>>>>> 标记出不同分支的内容
<<<<<<< HEAD 和 ======= 中间的是你自己的代码
======= 和 >>>>>>> 中间的是其他人修改的代码
自己确定保留那一部分代码,最后删除 <<<<<<< HEAD ,======= ,>>>>>>> 这种标志
在本地先处理冲突,将文本进行合并,然后本地提交,再执行 Push 操作
- 远程仓库内容