Skip to content

Git 教程

作为一名人类高质量程序员,进厂的首要任务就是熟悉项目,而熟悉项目的第一步就是拉取同事的代码!作为进厂的第一行代码,熟悉 Git 等版本控制工具的相关操作能极大地方便我们在团队中进行协同项目的开发!

1 Git 简介

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。与常用的版本控制工具 CVS,Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

2 版本控制

版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。简单讲就是备份和记录,接下来我们要了解三种不同版本控制的发展历程。

2.1 本地版本控制系统

人们把项目拷贝到本地磁盘上进行备份, 然后以命名方式来区分,这种做法好处是简单,但坏处也不少比如备份比较多或许就会混淆不同版本之间的区别, 那为了解决这个问题,有人就开发了一个本地版本的管理系统,它的结构图如下:

本地版本管理就是把版本号存入数据库来记录文件的历次更新差异。

2.2 集中化版本控制系统

本地版本控制系统能够将不同版本的文档保存下来并且借助版本记录,可以很方便定位相关文件但又引入了新的问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法 。

3

这样做的好处是解决了人们开发协同的问题,但是把所有的代码提交到同一台服务器上有一个很明显的问题就是单点故障。如果这台服务器宕机了,那所有人都不能提交代码,还有如果这台服务器如果磁盘发生故障,碰巧没做备份,或者备份不够及时,就还是会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

2.3 分布式版本控制系统

为了解决集中化版本管理所带来的问题,分布式版本管理控制系统(Distributed Version Control System,简称 DVCS)就应运而生了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端不只是提取出最新版的文件快照,而是把最原始的代码仓库镜像到本地。这样一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份。

4

所以综上来看,集中化版本控制系统是对本地版本控制系统的一次升级,因为它加入了协同操作,分布式版本控制系统是对集中化控制系统的一次补充,使之更加完善。

3 Git 安装

官方下载地址:https://git-scm.com/downloads/

5

6

3.1 Homebrew 安装

Homebrew 是一款 MacOS 平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径的情况,十分方便快捷。

安装命令

  • 命令1:(这个命令不好使会报错,如果报错尝试使用命令2)

    bash
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 命令2:(这是一个脚本,同样可以安装Homebrew)

    bash
    /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

3.2 安装 Git

打开终端(Terminal),输入 brew install git

7

3.3 验证安装

输入命令 git --version

8

4 Git 操作

4.1 用户配置

创建一个全局用户名、全局邮箱作为配置信息

bash
# 配置用户名称
git config --global user.name "Your Name"  

# 配置用户邮箱
git config --global user.email "Your Email" 

# 查看配置信息
git config --list

注: git config 命令的 --global 参数,用了这个参数,表示我们这台机器上所有的 Git 仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和 Email 地址。

9

注:配置信息可以更改,以后想要更改使用上面指令就可以。

4.2 Git 文件的状态与工作模式

使用 Git 操作文件时,文件的状态有以下三种:

状态描述
已提交
committed
已提交表示数据已经安全的保存在本地版本库中。
已修改
modified
已修改表示修改了文件,但还没保存到版本中。
已暂存
staged
已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

针对 Git 文件的三种状态,这里需要了解 Git 项目的三个工作区域:工作区、暂存区和 Git 仓库。

分类描述
工作区简单的理解为在电脑里能看到的目录,比如自己创建的本地项目目录
暂存区Git 的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫 index)的暂存区。
还有 Git 自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD。
Git 仓库工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。

基本的 Git 工作流程描述如下:

  • 在工作区中修改某些文件。
  • 对修改后的文件进行快照,然后添加到暂存区。
  • 提交更新,将保存在暂存区域的文件快照永久转储到 Git 仓库中。

流程图如下:

10

60

4.3 创建版本库并提交文件

版本库又名仓库,可以简单理解成一个目录,这个目录里面的所有文件都可以被 Git 管理起来,每个文件的修改、删除,Git 都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

4.3.1 初始化版本库

开始一个新的项目,初始化新的代码仓库,要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:

bash
# 初始化新的代码仓库
git init

11

4.3.2 添加文件到暂存区

  • 在 .git 同级目录下添加 test.txt 文件后,使用 git status 查看工作目录与暂存区文件状态
bash
# 创建文件
touch test.txt

# 查看工作目录与暂存区文件状态
git status

12

git status 命令用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了,哪些没有,哪些文件没有被 Git tracked 到。

  • 执行 git add 命令添加文件到暂存区

git add 通常是通过 git add <path> 的形式把 <path> 添加到索引库中,<path> 可以是文件也可以是目录。 git 不仅能判断出 <path> 中,修改(不包括已删除)的文件,还能判断出新添的文件,并把它们的信息添加到索引库中。

bash
# 添加指定新增或者改动过的文件
git add test.txt

# 添加当前目录下所有文件
git add .

# 可以使用通配符
git add *.txt

13

4.3.3 提交文件到本地版本库

文件被添加到暂存区后,执行 git commit 命令提交暂存区文件到本地版本库中。

git commit 命令用于将更改记录(提交)到存储库。将索引的当前内容与描述更改的用户和日志消息一起存储在新的提交中。通常在执行提交时 在 git commit 命令后跟上 -m 属性,加入本次提交的记录说明,方便后续查看提交或改动记录。

bash
# 提交变更到本地版本库
git commit -m "注释信息"

14

  • 查询提交日志信息

git log 命令用于显示提交日志信息。

bash
# 显示提交的日志记录
git log

# 可以使用 --oneline 来显示简洁的记录
git log --oneline

15

4.4 回退版本

使用 git reset 命令可以回退版本,回退版本后,暂存区的文件会回退到工作区,但是工作区的文件不会回退到上一个版本。

bash
# 回退到上一个版本
git reset --hard HEAD^

# 回退到上上一个版本
git reset --hard HEAD^^

git reset 的三种模式:

  • --soft:仅仅在本地库移动 HEAD 指针,不会修改暂存区和工作区
  • --hard:在本地库移动 HEAD 指针,重置暂存区和工作区
  • --mixed:在本地库移动 HEAD 指针,重置暂存区,不会修改工作区

4.5 查看差异

使用 git diff 命令可以查看文件的差异,查看工作区与暂存区的差异,查看工作区与本地版本库的差异。

bash
# 查看工作区与暂存区的差异
git diff

# 查看工作区+暂存区与本地版本库的差异
git diff HEAD

# 查看暂存区与本地版本库的差异
git diff --cached
# 或者
git diff --staged

# 比较提交之间的差异
git diff <commit_id1_hash> <commit_id2_hash>
# 或者
git diff HEAD~ HEAD

# 比较分支之间的差异
git diff <branch_name1> <branch_name2>

4.6 删除文件

使用 git rm 命令可以删除文件,删除文件后,需要执行 git commit 命令提交到本地版本库中。

bash
# 将文件从工作区和暂存区中删除
git rm <file>

# 将文件从暂存区中删除,但是保留在当前工作区中
git rm --cached <file>

# 递归删除目录下的所有文件
git rm -r *

# 提交到本地版本库
git commit -m "注释信息"

4.7 忽略文件

在项目中,有些文件是不需要提交到版本库中的,比如编译生成的文件、日志文件、缓存文件等,这些文件可以通过 .gitignore 文件来忽略。

bash
# 忽略文件
*.log
*.txt
*.class

# 忽略目录
target/

# 忽略指定目录下的文件
target/*.txt

5 远程仓库

Git 是一个分布式版本控制系统,同一个 Git 仓库,可以分布到不同的机器上。截止目前,并没有看到分布式的环境,因为以上的操作都在在本地发生的。对于 Git,除了前面提到的本地版本库外,Git 支持远程仓库的托管服务即使用者可以将本地版本库中的文件托管到远程服务器进行存储,这样就极大的方便开发,无论你走到哪,只要你的机器能够联网,就可以通过远程的仓库地址得到一份相同的项目库文件,并且下载到本地的文件版本记录与远程文件版本保持一致,并且可以很方便的实现多人协同开发操作。

对于 Git 远程仓库,GitHub 是比较知名的一个;而国内比较知名的当属 码云 了。当然除了这些远程仓库外,在公司,有的公司出于安全考虑,可能会自己搭建一套 Git 服务器(如 GitLab)来作为远程仓库,对于内部仓库会有专门人员来进行维护操作。

5.1 Github

5.1.1 创建 SSH key

Git 关联远端仓库时候需要提供公钥,本地保存私钥,每次与远端仓库交互时候,远端仓库会用公钥来验证交互者身份。通过终端命令创建 SSH key,期间会提示 key 文件保存位置、是否覆盖、输入密码、再次输入密码。

bash
ssh-keygen -t rsa -C "your_email@youremail.com"

16

生成密钥后,在 本地的 /Users/当前电脑用户/.ssh 目录下会生成两个文件 id_rsaid_rsa.pub,id_rsa 文件保存的是私钥,保存于本地,id_rsa.pub 文件保存的是公钥,需要将里面内容上传到远端仓库。

5.1.2 获取字符串

输入 cat /Users/hayden/.ssh/id_rsa.pub 指令(我这里用的是绝对路径),查看 id_rsa.pub 文件中内容

17

5.1.3 添加 Key

登录 GitHub 账号(默认已经注册了 GitHub 账号),在 Settings 中的左侧边导航中找到 SSH and GPG keys ,点击左面面板右上方的 New SSH key 添加。填写完毕后点击 Add SSH key 按钮

18

19

5.1.4 链接验证

输入命令,输入 "yes",回车。看到欢迎提示即添加成功!

bash
ssh -T git@github.com

20

5.1.5 提交本地项目到 GitHub

  • 创建一个仓库

在页面的最右上角,你的头像的左边,点击“+”,在弹出的下拉选项中选择 “New repository”。

21

22

  • 绑定远程地址到本地

进入前面已经初始化好的仓库目录,关联远程仓库

bash
# 关联远程库
git remote add origin 远程仓库地址

根据 GitHub 说明,执行 SSH 推送,首先绑定远程地址到本地执行命令

bash
git remote add origin git@github.com:nianan0908/helloworld.git

23

查看远程仓库:

bash
git remote -v
  • 推送本地库到远程
bash
# 查看当前分支
git branch

# 分支重命名
git branch -M main

# 将本地的分支推送到远程
git push -u origin main

24

注:如果第一次访问,需要输入 GitHub 的对应的用户名和密码。

25

5.1.6 克隆远程项目到本地

获取远程项目的地址

26

打开终端,进入项目想要存放的目录(示例放在桌面)

27

输入命令,克隆项目

bash
# 克隆远程库的工程
git clone 远程项目地址

28

修改项目内容,执行相关操作

bash
# 将修改后的文件添加到仓库 (.代表所有的文件)
git add .
# 将文件提交到仓库
git commit -m "注释内容"
# 上传到 GitHub
git push

29

5.2 Gitee

5.2.1 创建 SSH key

步骤与 GitHub 的相同,这里不再重复。

5.2.2 添加 Key

30

31

5.2.3 码云新建仓库

32

33

5.2.4 提交本地项目到码云

bash
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': 账号对应的密码

34

如果已有本地仓库

bash
cd 本地仓库目录
git remote add origin https://gitee.com/nian-an/helloworld02.git
git push -u origin master

5.2.5 克隆远程项目到本地

获取远程库的地址

35

输入命令,克隆项目

36

5.3 git pull 和 git fetch

git pull

git pull 命令用于从另一个存储库或本地分支获取并集成(整合)。

git pull 命令的格式如下:

bash
git pull <远程主机> <远程分支>:<本地分支>

git fetch

git fetch 的完整操作步骤如下:

首先,需要确定你要从哪个远程仓库获取数据。这通常是克隆仓库时使用的远程仓库名称,例如 "origin"。

接下来,需要指定你要获取哪个分支的数据。可以指定分支的名称,例如 "master" 或 "dev"。

执行 git fetch 命令,后面跟上远程仓库名称和分支名称。例如:

bash
git fetch origin main

这将从名为 "origin" 的远程仓库获取名为 "main" 的分支的最新更改。

一旦执行了 git fetch 命令,Git 将从远程仓库拉取最新的提交记录,并将其存储在本地仓库中。你可以使用 git log 或 gitk 等工具查看这些更改。

现在,你可以根据需要将这些更改合并到你的当前分支。如果你已经切换到了要合并的分支,可以使用 git merge 命令将远程分支的最新更改合并到当前分支。例如:

bash
git checkout <your-branch-name>
git merge FETCH_HEAD

这将把远程分支的最新更改合并到名为 "your-branch-name" 的当前分支中。

6 Git 分支

开发企业项目中在使用 Git 或者其他类似版本控制软件对项目版本进行管理时,多人合作的项目在开发时通常不会直接在主干 master 上进行操作,而是重新开辟新的分支,在新的分支上进行开发、调试等操作,当项目调试通过时才会将分支项目的代码合并到主干中,这是在实战中比较好的一种策略,特别是多人协同开发一个项目的情况下尤其明显。

6.1 基本命令

命令描述
git branch查看所有分支,并且 * 号标记当前所在分支
git branch <new_branch_name>新建分支
git checkout <branch_name>切换到指定分支
git switch <branch_name>切换到指定分支(新版本功能)
git checkout -b <new_branch_name>新建分支并切换到新建分支
git branch -d <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>拉取远程分支,并在本地创建新分支且切换到新分支

6.2 分支操作

6.2.1 查看分支

git branch:查看所有的分支,* 号标记当前所在分支

37

6.2.2 新建分支

git branch dev:新建一个名称为 dev 的分支

38

6.2.3 切换分支

git checkout dev:切换到名称为 dev 的分支

39

6.2.4 新建并切换分支

git checkout -b dev02:新建一个名称为 dev02 的分支,并且切换到该分支

40

6.2.5 删除分支

git branch -D dev02:删除名称为 dev02 的分支

41

注:不能执行删除当前所在分支的操作!

6.2.6 合并分支

git merge dev:在 dev 分支添加文件并提交,再切换到 master 分支,将 dev 分支的内容合并到 master 分支

42

如果不想继续执行合并操作,可以使用 --abort 参数,取消合并操作:

bash
git merge --abort

除了使用 git merge 操作外,还可以使用 git rebase 操作。

rebase 变基操作可以在任意分支上执行操作,将本地未 push 的分叉提交历史整理成直线,形成线性历史,不会产生额外的提交记录。

Merge

优点:不会破坏原分支的提交历史,方便回溯查看

缺点:会产生额外的提交节点,分支图比较复杂

Rebase

优点:不会新增额外的提交记录,形成线性历史,比较干净直观

缺点:会改变提交历史,改变当前分支的提交节点,应避免在共享分支上操作

6.2.7 重命名分支

git branch -m dev dev01:分支重命名,将名称为 dev 的分支,重命名为 dev01

43

6.2.8 查看分支

git branch -a:查看本地与远程的所有分支

44

6.2.9 推送分支

git push origin dev01:将名称为 dev01 的本地分支推送到远程库

45

远程库中的分支列表

46

6.2.10 拉取分支

git checkout -b dev02 origin/dev02:将远程库中的 dev02 分支拉取到本地,在本地创建分支 dev02 并切换到该分支

远程在线创建新分支 dev02

47

48

6.2.11 更新操作

git pull origin dev02:拉取远程分支 dev02 的内容,并合并到本地

远程在线新建文件

49

50

拉取远程分支中的内容并合并本地

51

6.3 分支冲突

模拟两个用户操作同一分支同一文件的场景:

  • 用户A 与 用户B:分别新开终端窗口,克隆项目

52

  • 用户A 与 用户B:分别拉取远程分支 dev02,本地切到 dev02 分支

53

  • 用户A:在本地修改 dev02 分支的 data.txt 文件,并将本地用户A提交的 data.txt 文件推送到远程 dev02 分支

54

  • 用户B:在本地修改 dev02 分支的 data.txt 文件,并将本地用户A提交的 data.txt 文件推送到远程 dev02 分支

此时冲突出现,原因是另外一个用户推送的文件与当前客户端推送内容存在冲突。

解决方式:Git 已有对应提示,Push 之前先执行 Pull 操作,将远程文件拉取到本地,解决完冲突后再次执行 Push 操作

55

  • 解决冲突

先执行 Pull 拉取操作

56

查看冲突文件内容

57

bash
# Git 用 <<<<<<<,=======,>>>>>>> 标记出不同分支的内容 
# <<<<<<< HEAD 和 ======= 中间的是你自己的代码
# ======= 和 >>>>>>> 中间的是其他人修改的代码
# 自己确定保留那一部分代码,最后删除 <<<<<<< HEAD ,======= ,>>>>>>> 这种标志

在本地先处理冲突,将文本进行合并,然后本地提交,再执行 Push 操作

58

  • 远程仓库内容

59

最后更新于:

编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!