date
Apr 16, 2025
icon
password
Pin
Pin
Hide-in-Web
Hide-in-Web
网址
type
Post
slug
git-note
tags
笔记
category
学习分享
bottom
bottom
Hide-in-Config
Hide-in-Config
comment
Show
status
Published
summary
关于 git 的学习笔记,参考的是尚硅谷的网课
本笔记是关于 GIT 的入门笔记,参考了尚硅谷的网课、廖雪峰老师的教程以及 Git 的官方教程,目前已更新完毕。
在这个笔记中,介绍了有关 git 的基础指令、github 的团队协作和跨团队协作方法,在原课程中还介绍了 IDEA 集成 git 的操作,由于我本人是没有使用 IDEA 的,暂时没有学习 JAVA 的打算,因此这部分内容就没有加入到笔记中了(对 git 本身学习影响不大)。感兴趣的友友可以自行学习。
由于在写这份笔记前,我从未接触过
git
,因此,这份笔记也记录了我 git
的全部学习轨迹,以初学者的姿态记录相关内容,因此适合初学者学习和使用。在本篇笔记开始前,先提醒下各位,关于 Git,官方是有中文的详细教程的: Git - 官方教程(简体中文)。但官方的教程特别详细,有些指令并非是我们初学者会使用到的,因此大家可以根据自己的学习情况来选择。如果各位已经有了一定的 Git 基础(或是看完了我的这篇笔记),那么强烈建议大家再将官方教程中学过的部分再看看,一定会有新的收获。
绪论
为什么要学习 git?
学习一门工具最重要的就是“立意”,弄明白我们为什么要学习这款工具,这也正是为什么很多课程或教学网课都会有一个绪论的原因。弄清楚为什么而学不仅能够帮助我们坚持下去,也能够让我们学以致用,不至于学完就忘。
git 是一个分布式的代码版本管理工具,可以帮助我们管理自己不同版本的代码,与他人进行代码协作。
传统的代码管理中心有分布式和集中式两种。集中式的代码管理中心比较出名的就是 SVN。
集中式的代码管理中心需要通过一个中央服务器来对代码进行管理,如果我们要保存代码的历史记录,必须联网进行操作,这样就会导致一个问题,当用户处于离线状态时,它就无法获取到自己曾经上传的最新版本的代码了。当然,如果用户将最新版本的代码保存在了本地,如果他想要查看过去的历史记录,也必须要联网进行操作,十分的不方便;
而分布式的代码管理中心就解决了这个问题,它是通过本地库来实现历史记录的管理的。使用本地库就意味着离线状态下,用户也可以随时随地下载最新的代码,同时上传自己修改后的代码,或是查看以往的历史记录。因为我们无论使用集中式的代码管理工具还是分布式的代码管理工具,最初的目的就在于管理自己代码或文件的历史记录。
但更进一步地说,如果我们希望在一个团队中进行协作,大家一起对一个项目的代码进行写作或是修修补补,那么就需要一个云服务器对历史记录进行保存了。在这一点上,无论是集中式的代码管理工具还是分布式的代码管理工具是一样的,因为要从云服务器上获取到最新的代码文件,都是需要联网的。
什么是暂存区、本地库和云服务器?
在分布式管理工具中,以 git 为例,有工作目录、暂存区、本地库和云服务器这几个概念。
- 工作目录指的是处于当前 git 仓库中的文件但未上传到暂存区的文件;
- 暂存区用于将我们所做的所有修改进行临时保存,我们可以选择性地将暂存区的修改上传至本地库。这意味着经过多次修改后,处于暂存区的代码如果不合我们的心意,我们可以选择将其丢弃,而将符合要求的部分文件上传到本地库保存。
- 本地库,可以理解为是代码文件的“流水账”,记录了这个文件的前世今生,大大小小的改动都在其中。如果是在团队协作下,则本地库又可以当作是对云服务器中历史记录的本地备份,方便自己在离线时也能够获取到代码的历史记录。
- 云服务器其实就不言而喻了,就是为了团队协作,分享代码而存在的,我们可以将本地库的更新上传到云服务器,也可以将云服务器的最新更新下载到本地。其实就是 github 的发展方向。
git 的过去
2005 年之前,软件开发的世界被集中式版本控制系统统治着。CVS 和 SVN 是当时的主流工具,它们依赖一台中央服务器存储代码历史。开发者需要不断与服务器通信才能提交代码、查看历史——就像去图书馆借书,必须登记、排队,一旦图书馆关门(服务器宕机),所有人只能干等。更糟糕的是,分支(Branch)功能笨重,合并代码常引发冲突,开发者戏称其为“代码炸弹”。
此时的 Linux 内核团队正面临危机。他们用着一款名为 BitKeeper 的分布式工具,但它闭源且受商业公司控制。当 BitKeeper 突然撤销免费授权时,Linux 创始人 Linus Torvalds 意识到:必须造一个真正自由、高效的工具,夺回代码控制的自主权。
2005 年 4 月,Linus 给自己放了一周假,闭关开发 Git。他的目标极其明确:
- 完全分布式:每个开发者本地都有完整的代码仓库,不依赖网络即可提交、分支、回溯。
- 极速性能:Linux 内核有数万次提交历史,Git 必须在秒级完成操作,不能像 SVN 那样卡顿。
- 绝对可靠:用 SHA-1 哈希算法为每次提交生成唯一指纹,数据一旦被篡改立刻暴露。
短短十天后,Git 初版发布。Linus 并未止步于解决眼前问题,而是重新定义了版本控制的逻辑:
- 快照代替差异:传统工具记录文件变化(如“某行代码被修改”),而 Git 直接保存项目快照,切换版本如切换照片般迅速。
- 隐式分支:分支只是指向某个提交的“指针”,创建成本几乎为零。开发者可以大胆尝试新功能,合并时再处理冲突。
早期的 Git 只有命令行界面,学习曲线陡峭。但它的设计哲学很快吸引了极客们:
- 离线自由:开发者可以在飞机上编码、提交,网络恢复后一键同步。
- 历史可逆:用
git reset
回退错误提交,用git cherry-pick
移植特定修改,代码时间线尽在掌控。
真正的转折点发生在 2008 年。GitHub 的上线将 Git 的分布式能力与社交网络结合,创造了全新的协作模式:
- Fork & Pull Request:任何人都能轻松复制项目(Fork),修改后通过 Pull Request 提交贡献,开源协作门槛大幅降低。
- 代码即社交:GitHub 的 Issue 追踪、代码审查和 CI 集成,让 Git 从工具升级为开发生态系统。
微软在 2018 年以 75 亿美元收购 GitHub,争议背后正是 Git 不可替代的证明——它已是全球开源项目的“数字基础设施”,从个人博客到 SpaceX 的火箭代码,Git 无处不在。
git 的安装
直接参考尚硅谷网课视频的教程进行即可: 07_尚硅谷_Git_安装_安装和客户端的使用_哔哩哔哩_bilibili 。
这里有一个注意点,在进行到下图所示的安装步骤时,无论你是什么方向的,都建议选择第二个,毕竟第二个具有可扩展性,不仅可以实现第一个的功能,而且未来如果想要扩展到其他应用程序中使用也是方便的。

Git 基础
git 原本就是为了 linux 系统而设计的,因此 git 中可以使用 linux 的大部分代码,对于学过 linux 的人会比较友好,没有学过的都建议去学一学,Linux 算是程序员或是嵌入式工程师必备的技能了(学过 Linux 有些忘记了的友友可以看我的 『 Linux 笔记 』,没有学过的也可以学习,我觉得笔记还是比较易懂的,毕竟是前一阵子自己初学 Linux 时写的,会记录很多初学者的问题)。
【补充】适用于 git 管理的文件
由于 word,视频、图片等文件都是使用二进制进行编码的,虽然也能够使用 git 来保存版本,但是无法跟踪每次改动的变化。
因此,git 一般用于进行文本文件(代码文件)的版本变动,常用的源代码文件,如
.c
,.py
等都可以使用 git 来保存。由于 Windows 系统中的记事本中会在开头默认加入
0xefbbbf
这样的前缀保存 UTF-8 文件,导致正常的程序编译时出现意想不到的错误,因此尽量不要使用记事本编辑文本文件,并使用 git 上传。Git 配置用户名和邮箱
git 中一定要进行用户名和邮箱的设置,否则无法正常提交。
git config --global user.name [用户名]
:用于设置 git 账户的用户名,未来保存历史记录时会将修改文件的用户名一并保存,这样别人就知道是谁修改了代码。
git config --global user.mail [邮箱]
:用于设置 git 账户的邮箱,未来保存历史记录时也会将邮箱保存,这里的邮箱如果随便写也能够成功记录。后续会利用邮箱来匹配 github 或 gitee 的账户以实现文件的云端备份或团队协作。如果你没有这方面的需求,那么邮箱可以随便写。
--global
参数表示设置的是全局参数,也就是说,如果你本地创建了多个仓库,那么都将使用上面的用户名和邮箱。上述这两行代码一定要设置,否则 git 提交时会报错。可以按下 Win,在搜索栏中搜索
.gitconfig
文件,右键记事本打开,对刚刚添加的两个内容进行查看。其他配置指令(不用背,未来可能会用到):
git config user.name 用户名
:配置当前仓库的用户名;git config user.email 邮箱地址
:配置当前仓库的邮箱;git config --global user.name
:查看全局仓库配置的用户名;git config --global user.email
:查看全局仓库配置的邮箱;git config user.name
:查看当前仓库配置的用户名;git config user.email
:查看当前仓库配置的邮箱;git config --list
:列出所有生效的配置项(全局和当前仓库的配置);Git 常用的 linux 指令
在接下来的 git 笔记中,最常用到的 linux 指令如下:
cd 目录
;
cd 是
change directory
的意思,即切换目录,通过这条指令可以在 git 中进入到不同的文件夹下,比如 cd D:
进入 D 盘,cd D:/git
进入到 D 盘下的 git 目录。在 git 和 linux 中,都是使用
/
来作为路径分隔符的,Windows 中使用的是 \
,注意区分。ll
或ls -l
;
这两个指令是一样的意思,ls 意思是 list,即列出当前目录下的所有文件,一般直接使用
ll
;pwd
;
意思是
print work directory
,即打印当前的工作目录,这条指令用于显示当前 git 所在的工作目录。如果你通过
cd D:/git
进入了 D 盘下的 git 目录,那么 pwd
就会输出 /d/git
。cat 文件名或文件路径
;
该指令用于将文件的内容输出,如
cat hello.txt
,将当前工作目录下的 hello.txt
文件的内容输出到下面。touch 文件名或文件路径
;
该指令可以创建一个空文件(不会进入文件编辑模式),如
touch hello.txt
会在当前目录下创建一个 hello.txt
文件,touch D:/hello.txt
会在 D 盘下创建一个 hello.txt
文件。vim 文件名或文件路径
;
这条指令用于打开文件,如
vim D:/hello.txt
会打开 D 盘下的 hello.txt
文件,如果文件不存在则会先创建文件然后再打开。也可以使用 vim hello.txt
直接在当前目录下创建 hello.txt
文件。打开后,文件会处于“正常模式”,该模式下无法对文件内容进行编辑,可以对文件进行查看(键盘方向键移动光标);
在“正常模式”下按下键盘上的
i, I, o, O, a, A
中的任意一个都可以进入编辑模式,在编辑模式下可以对文件进行修改;如果修改完成,可以按下键盘上的
esc
键退出编辑模式;在正常模式下输入键盘上的冒号
:
(英文冒号)可以对文件进行一些操作,:wq
表示保存并退出文件,:q!
表示不保存强制退出文件。更多
vim
的操作可以查看我的 『 Linux 笔记 』。 代码库的初始化
首先创建一个未来存放自己代码历史版本的
git
目录(比如我的为 git_repository
),然后进入该目录,右键点击 “Git Bash” 打开 git
,此时 git
的当前目录就是你刚刚创建的目录。然后输入
git init
即可将当前目录设置为 git 的存放目录,设置完以后,可以回到刚刚的目录下,打开 Windows 显示隐藏项目的功能,即可看到多了一个 .git
文件夹,此时说明初始化成功。
【指令】文件的上传与提交 | 文件状态的查看
使用vim
或touch
创建了一个新的文件hello.txt
。
git add 文件名(文件路径)
:
通过该指令可以将文件上传到
git
的暂存区,此时还没有抵达本地库。比如, hello.txt
文件创建后还未上传至暂存区,使用指令 git add hello.txt
后,得到的结果如下图所示:
git status
:
可以查看当前
git
库的状态,可以显示哪些文件目前已经上传到暂存区,哪些文件已经上传到本地库,哪些文件还未上传,哪些文件在上传到暂存区或本地库后被删除(后面会详细介绍 git status
的不同状态)。
untracked files
表示正在处于修改中的文件,还未上传至暂存区。【补充】git status
的四种状态
Untracked files
表示的是未被 git 跟踪的文件,一般是在工作目录中新创建且还未执行
git add
指令添加到暂存区的文件。只要对文件执行过
git add
操作,后续无论是删除还是上传文件,文件都会处于被 git 跟踪的状态。Changes to be commited
表示的是已经上传到暂存区但是还未提交到本地库的文件。
Changes not staged for commit
staged
可以理解为暂存区。
针对已经被 git 跟踪的文件,若文件在上传到暂存区或是提交到本地库的状态下被修改或删除了,
git status
后可以看到文件处于当前状态。下图中 hello2.txt 文件已经上传到暂存区中,此时又对 hello2.txt 文件进行了修改,如果此时直接执行
git commit -m "提交 hello2.txt" hello2.txt
,那么会将未修改过的 hello2.txt
提交到本地库。如果直接执行 git add hello2.txt
则会将修改后的 hello2.txt
上传到暂存区。
Unmerged paths
同一文件的同一行在不同分支被修改时,如果进行合并操作会提示文件冲突,此时文件会被列在该状态下(后面会学到合并部分会介绍)。
git rm --cached 文件名(文件路径)
:
通过该指令可以将处于暂存区的文件撤回到工作目录,即将其退回
Untracked files
中,但文件夹里的文件仍然还存在(不等于将文件从硬盘中删除)。
git commit -m "提交备注" 文件名(文件路径)
:
通过该指令可以将处于暂存区的文件上传到本地库,其中的
-m
参数是必须要写的,每次上传到必须要备注这一次的修改,否则会上传失败。比如 git commit -m "第一次上传" hello.txt
。
此时通过
git status
指令就已经看不到 hello.txt
了。同样地,对于前面的图片中
deleted: readme.txt
文件,由于它从硬盘中删除了,我们可以通过 git commit -m "删除了 readme.txt 文件" readme.txt
来将删除操作同步到 git
本地库中。git commit -m "提交备注"
:
如果不指定特定的文件名,可以提交当前暂存区中的全部文件。
git commit
提交的宗旨是: Do one thing and do it best 。即只做一件小事并把它做好,方便未来自己与其他人阅读代码时能够快速理解和梳理。git reflog
(reflog → 【reference log】) :
等同于指令git log --oneline
。
可以查看所有的提交记录(简化版,只显示一些重要信息),提交记录是按时间倒序排列的(新的在前面),第一列为简化版的编号,最后一列为先前
-m
备注的内容。
对于 git 中提交的第一条记录,
commit
后面会有一个括号写着 initial
。图中还有一个值得注意的点,
HEAD -> master
,这里有一个指针,表示当前的 git 引用的是备注为 “第一次提交” 的文件。git log
:
可以查看所有的提交记录(详细版,显示记录的全部信息),提交记录也是安照时间倒序排列的,第一行的编号为记录的完整编号,最后一行为
-m
备注的内容。
git log
有一个参数 --pretty=oneline
,可以同时显示完整编号和备注内容,与 git reflog
类似。git log --pretty=oneline
的图示:
文件的迭代更替流程
本部分将模拟一个文件test.txt
修改更替的流程。test.txt
→Untracked files
→changes to be commited
。
touch test.txt
首先创建一个文件(文件是空的)。
git status
查看当前的git
状态。处于Untracked files
队列中。

git add test.txt
将test.txt
上传到暂存区。
git status
查看当前git
的状态。处于changes to be commited
队列中。

git commit -m "test 文件的第一次提交" test.txt
将处于暂存区的test.txt
文件上传到本地库;
git status
查看当前git
的状态。此时不会显示文件。

git reflog
查看本地库。

vim test.txt
修改test.txt
文件。

git status
查看当前git
的状态。

git add test.txt
将修改后的test.txt
上传到暂存区。
git status
查看当前git
的状态。处于changes to be commited
队列中。

git commit -m "test 文件的第二次上传" test.txt
将处于暂存区的test.txt
文件上传到本地库;

git reflog
查看更新后的本地库。

- 再次修改文件
test.txt
,此时新增一行,并在原有的一行后面加上一些内容。

git status
查看当前git
的状态。

git add test.txt
将修改后的test.txt
上传到暂存区。
git status
查看当前git
的状态。处于changes to be commited
队列中。

git commit -m "test 文件的第三次修改" test.txt
将处于暂存区的test.txt
上传。

1 file changed
表示有一个文件被修改,2 insertions
表示插入了两行内容,1 deletion
表示有一行被删除。这里需要注意,由于我们是在第一行末尾添加了 append
内容,因此上传时会将原先 test.txt
里的第一行删除,然后再将修改后的第一行插入,因此 deletion
的数量是 1。git reflog
直接查看当前的本地库。

【指令】版本穿梭(版本回退)
版本穿梭的原理
git
指令的版本回退本质上是利用指针来进行操作的。如下图所示,目前的
git
指针指向的是备注为 third
的文件编号。
其中,
HEAD
字面意思是“头部”,实际表示 当前所在的提交或分支,本质上是一个动态指针。而 master
表示的是默认的主分支,一个仓库可以有多个分支,具体使用哪个分支由 HEAD
指针确定。master
本质上也是一个动态指针,当我们要进行版本穿梭(即切换到过去的版本)时,改变的就是 master
的指针位置。当 master
发生变化时,HEAD
也会同步跟着 master
变化。master
实际指向的是各个历史版本的完整编号(下图中的绿框部分),因此我们可以根据编号来进行版本的切换。
版本穿梭的指令
- 首先通过
git reflog
查看版本编号;
- 通过
git reset --hard 版本号
指令即可将文件回退到我们指定的版本中。
其中,
--hard
表示会将所有的修改(工作目录中、暂存区中和本地库中的修改)整体回退到指定的版本。版本号既可以使用下图所示的版本编号:

也可以使用
HEAD^
这样的形式,HEAD^
表示回退到上一个版本,HEAD^^
表示回退到上上个版本,比如 git reset --hard HEAD
。如果要回退的版本比较多,可以使用
HEAD~n
,比如 HEAD~100
。运行上述指令回退版本时,也会创建一个提交记录来记录你回退的过程。如果在回退的版本下进行了修改,仍然是按照前面迭代更替的过程上传文件。
【补充】比较当前文件与本地库中文件的差异
指令:
git diff HEAD -- 文件
。该指令即可查看当前
HEAD
指向的本地库记录中的文件与未提交的文件之间的差异。比如执行
git diff HEAD -- hello.txt
:
上图中红色部分就表示当前文件与本地库文件相比缺少的地方。
当然,指令中的
HEAD
也可以使用 HEAD^
或 HEAD~n
这样的形式,表示与本地库前几个版本进行比较:
上图中绿色的部分为当前文件与前 5 个版本的本地库文件相比新增的地方。
【指令】分支(查看、创建、切换、合并)
分支的介绍
在公司的内部,分支的使用是非常常见的。分支可以使得程序并行设计,通常针对不同的功能都会创建一个独立的分支由特定的团队进行开发,开发完成后,可以合并到主分支中,如果合并过程中出现了一些 bug,可以另外设置一条
hot-fix
的分支(“热修”)用于紧急修复 bug,修复完成后再进行合并,若无法解决就只能回退到过去的版本。分支的切换在前面“版本穿梭”部分已经介绍过了,本质上还是利用指针来完成的。
查看、创建、切换、删除分支
命令名称 | 作用 |
git branch | 查看分支(仓库无任何提交时不显示分支) |
git branch -v | 查看所有分支及其最新的提交(仓库无任何提交时不显示分支) |
git branch 分支名 | 创建分支 |
git checkout 分支名 | 切换分支 |
git checkout -b 分支名 | 创建并切换分支 |
git branch -d 分支名 | 删除分支 |
当我们使用
git branch 分支名
创建了一个分支后(比如 git branch test_branch
),使用 git branch -v
可以进行分支的查看:
其中,蓝色括号部分的
(master)
表示的就是当前所在的分支;*
和对 master
绿色的高亮也表明了当前的分支是 master。其他没有高亮的分支,比如图中的
test_branch
表示的就是仓库里的其他分支。通过
git checkout test_branch
指令即可将当前分支切换为 test_branch
,如下图所示:
如果要删除还未合并过的分支,需要使用
git branch -D 分支名
强行删除。合并分支(普通合并、冲突合并)
合并分支需要分为两种情况讨论: ① 待合并的两个分支中只有一个分支发生了修改; ② 两个分支都发生了修改。
比如现在在
master
分支上有一个文件 hello.txt
,其中的内容为 hello, world!
。现在创建一个分支
git branch merge_branch
用于测试合并功能。第一种情况
省流:git merge 分支名 -m "备注"
(将“分支名”文件合并到当前分支下)
git checkout merge_branch
进入 merge_branch
分支后,vim hello.txt
编辑文件内容为:
输入
:wq
退出编辑器,然后通过 git add hello.txt
和 git commit -m "merge_branch 分支修改 hello.txt 文件" hello.txt
上传文件到本地库。git checkout master
回到主分支中,通过 git merge merge_branch -m "备注"
即可将 merge_branch
中新提交的修改合并到主分支 master
中。【这里要注意是谁合并谁】
从图中可以看到,合并过程中写着
Fast-forward
,表明这次的合并是快速合并,快速合并的好处就是将 master
的指针移动到 merge_brach
指向的位置,合并速度很快。后面也会介绍快进合并的不足之处。
第二种情况(冲突合并)
省流:git merge 分支名
→vim 冲突文件
→git add 文件名
→git commit -m "内容"
(无需文件名称)。
第二种情况在第一种情况修改的基础上进行,也就是说,此时
hello.txt
中的文件内容为:在
master
分支下,vim hello.txt
编辑文件内容,新增一条语句::wq
保存退出,然后通过 git add hello.txt
和 git commit -m "master 分支修改 hello.txt 文件, 用于测试第二种情况" hello.txt
上传文件到本地库。git checkout merge_branch
切换到 merge_branch
分支,此时 cat hello.txt
可以看到 hello.txt
文件中的内容。
vim hello.txt
编辑文件内容为:同样地,
:wq
保存退出,然后通过 git add hello.txt
和 git commit -m "merge_branch 分支修改 hello.txt 文件, 用于测试第二种情况" hello.txt
上传文件到本地库。现在,再次回到
master
分支下,cat hello.txt
文件打印文件内容:
可以看到,
master
分支下 hello.txt
文件的内容并没有被修改,现在需要将两个分支下的文件进行合并。由于两个分支下的文件都发生了修改,因此合并时会产生“冲突报错”:

如上图所示,出现了 CONFLICT (冲突)报错,同时,当前所在分支后面还多出了
|MERGING
字样。同时,我们输入
git status
时,也会出现下图所示的内容:
那么,如何解决冲突呢?
解决的方式就是打开冲突的文件,
vim hello.txt
,打开后会显示:
图中内容的分析:
我们根据需要选择性的保留,最后将等号分隔部分以及
<<<<<<< HEAD
和 >>>>>>> merge_branch
删除即可。我选择两条都保留,修改后如下所示:之后,
:wq
退出编辑器,然后按照正常的步骤 git add hello.txt
上传暂存区;在提交本地库的时候需要注意,使用 
git commit -m "master 和 merge_branch 分支合并" hello.txt
命令会出现报错(如下图所示),冲突合并时不能够加上文件名:
应该使用
git commit -m "master 和 merge_branch 分支合并"
指令直接进行合并。冲突合并是一种特殊类型的合并,当有多个冲突文件时,需要将所有的冲突文件都修改后才能够提交(不允许部分提交),由于冲突的文件都会被系统标记,因此无需文件名即可进行。
这里再多说一句,合并冲突与合并普通分支一样,只会修改当前分支(
master
)下的文件,而用于合并的分支(merge_branch
)不会发生变化。合并后的图示可以参考如下:
合并分支图示的显示
通常用git log --graph --pretty=oneline --abbrev-commit
绘制出合并冲突的图示。
下面来一步步拆解这条指令,首先使用
git log --graph
绘制分支图示:
图中图示的理解:
*
表示一个 commit(提交)(*
与commit 版本编号
是对齐的);
- 相同颜色的线表示一条分支,不同颜色的线表示不同分支(比如图中的绿线就表示 master 分支的提交,红线表示
merge_branch
分支的提交);
在信息量比较少的情况下(如上图),出现这么多信息看起来就有些累了,如果在信息量比较多的情况下,将会使得阅读更加困难。因此我们需要将上图中很多信我们不关注的信息移除(比如作者和时间是我们不需要的,只关注版本编号和备注),因此可以对内容进行精简,使用指令
git log --graph --pretty=oneline
:
可以看到上图精简了不少,但现在又有一个问题,完整的版本编号让我们的备注很靠后,不利于我们阅读,因此可以对版本编号进一步精简,使用指令
git log --graph --pretty=oneline --abbrev-commit
:
现在的图示就精简多了。从上图中,我们可以很容易将备注和编号与特定的
commit
对应。如果是在一个分支内进行的线性操作,而非合并,那么图示是这样的:

【补充】不使用快速合并(Fast-Forward
)合并分支
使用
Fast-Forward
快进合并 合并分支能够快速进行合并,但也会使得分支删除后,分支的信息丢失(git log --graph --pretty=oneline --abbrev-commit
中无法看到合并的分叉)。
为了避免这种情况的出现,可以在合并时采用禁用
Fast-Forward
的方式,使用指令 git merge --no-ff -m "备注"
,其中的 --no-ff
表示的就是不采用 Fast-Forward
。
如上图所示,若不采用
Fast-Forward
的方式进行合并,会产生一个新的分支来记录,这样即便 merge_branch
分支删除了,也能够保留分支的信息。【补充】分支的策略
所有【补充】都是在上完 尚硅谷 网课后自行学习和补充的知识,大家可以在后面团队协作部分学完后再回来看。
【补充】Git 2.33 以后的新指令(更人性化)
前面学习过程中介绍的指令都是旧指令,但旧指令不容易理解,而且相互之间可能会混淆,比如
git checkout -- file
表示的是将文件返回到最新状态,而 git checkout branch
就又表示切换分支。在 Git 2.33+ 的版本中,引入了更人性化的指令方式:
git switch
;
git switch -c 分支名
:创建并进入新分支,相当于git checkout -b 分支名
;
git switch 分支名
:切换分支,相当于是git checkout 分支名
;
【补充】Git 查看当前暂存区和本地库的文件集合(🌟🌟)
本部分内容参考了 【Git reset三种常用模式区别和用法】 这个视频。这部分内容是理解后面几个补充操作的基础。
在 git 中,工作目录、暂存区和本地库都会维护一个自己的文件集合。在工作目录、暂存区和本地库三者处于同步状态,即三者的文件集合(包括文件和文件内容)是相同的时候,此时的 git 是处于未被修改的稳定状态的。当我们修改了某个文件或是添加、删除了某个文件,工作目录中的文件集合就与暂存区和本地库的不同了。
此时使用
git status
查看暂存区的状态,会看到暂存区中文件状态发生了变化,此时我们通过 git add
指令可以实现工作目录和暂存区的文件集合同步。同步后本地库就与暂存区和工作目录的文件集合不同了,此时再运行 git commit
指令将暂存区的文件提交,这样就又可以实现工作目录、暂存区和本地库的同步了。在理解了以上内容的基础上,介绍两个指令来查看暂存区和本地库的文件集合:
git ls-files -s
查看暂存区的文件集合;
git ls-tree -r HEAD
查看当前分支最新状态的文件集合。
那么问题来了,如何查看工作目录中的文件集合呢,通过前面介绍过的指令
ll
即可列出当前工作目录下的文件集合。相比于
git reflog
和 git log
,git ls-tree -r HEAD
查看的是文件集合,而另外两个则查看的是所有的提交记录,应用场景不一样。删除文件的情况示例:
当我们在工作目录中通过
rm 文件名
操作删除了文件后,如果文件正处于暂存区或本地库中,通过 git ls-files -s
指令与 git ls-tree -r HEAD
指令仍将会查看到文件,因为此时并未实现工作目录与暂存区、本地库的同步。通过
git rm 文件名
或 git add 文件名
实现暂存区和工作目录的同步后,通过 git ls-files -s
指令将不会看到文件的存在,但通过 git ls-tree -r HEAD
指令仍将会查看到文件处于本地库中。再通过
git commit
实现本地库的同步后,文件将彻底移除暂存区、本地库的文件集合(但这并不意味着文件无法恢复了,因为文件曾在本地库中被 git 记录过,因此可以通过版本回退恢复)。成功实现同步后,通过 ll
指令与 git ls-files -s
指令与 git ls-tree -r HEAD
指令将不再看到该文件的存在。【补充】输出工作目录、暂存区和本地库中某个文件的内容
请在理解了前面暂存区和本地库文件集合的基础上阅读这部分内容。
cat 文件名称
:可以输出工作目录中文件的内容,如 cat hello.txt
;git show :文件名称
:可以输出暂存区文件集合中该文件的内容,如 git show :hello.txt
;git show HEAD:文件名称
:可以输出本地库文件集合中该文件的内容,如 git show HEAD: hello.txt
;【补充】git reset
的三种工作模式(--hard
、--soft
、--mixed
)
本部分内容参考了 【Git reset三种常用模式区别和用法】 这个视频。
在理解了前面“暂存区、本地库文件集合”部分内容的基础上,通过下面的示例来对
git reset
进行讲解。假设最初的状态是下图这样,readme.md 文件已经有了三个版本的迭代,同时在 v3 状态下工作目录、暂存区和本地库中的文件集合已经实现了同步。

如果采用 
--hard
模式,得到的修改是这样的:
实现的是工作目录、暂存区和本地库中文件的整体回退,工作目录和暂存区中的文件修改全部撤销,相当于是回到了 v2 版本下工作目录与暂存区、本地库同步的状态。
如果采用 
--soft
模式,得到的修改是这样的:
只有本地库中的文件回到了上一个版本,而工作目录和暂存区中的文件修改保持不变。此时工作目录与暂存区实现了文件集合的同步,而本地库与当前状态不同步。如果此时进行
git commit
操作可以实现同步。如果采用 
--mixed
模式(git reset
指令的默认模式),得到的修改是这样的:
只有暂存区和本地库中的文件回退到上一个版本,而工作目录中的文件修改保持不变。此时暂存区与本地库是同步的,而工作目录与这两者不同步,因此执行该指令后,使用
git status
指令会看到 readme.md
文件正处于 Changes not staged for commit
状态。【补充】文件的撤回操作
请在理解了 ① 暂存区和本地库文件集合 ②
git reset
的三种工作模式 的基础上阅读这部分内容。这部分内容可以说是 git reset
使用方式的思路拓展。git reset HEAD 文件路径(文件路径)
(相当于git reset --mixed HEAD 文件名(路径)
);
该指令可以将指定文件从暂存区撤回到工作目录下,相当于执行了下图所示的变换:

git reset HEAD 文件路径
等同于指令 git restore --staged 文件路径
(Git 2.23+ 版本可用)。git --version
查看当前的 git 版本。git reset HEAD
(等同于指令git reset --mixed HEAD
,在 Git 2.23+ 版本中等同于指令git restore --staged
);
该指令可以将所有文件都从暂存区撤回到当前工作目录下。
git reset --soft HEAD
;
该指令可以将所有文件从本地库中撤回到暂存区中(但是过去提交的记录是无法修改的)。由于
--soft
操作本质上移动的是 HEAD
指针,因此无法针对单个文件进行撤回。git checkout 版本 -- 文件名(文件路径)
;
该指令可以将某个特定的文件从本地库中撤回到暂存区,比如当前
hello3.txt
文件经过两版的修改后还没有第一版的好用,可以通过 git checkout HEAD~2 -- hello3.txt
来进行回退。回退后当前工作目录和暂存区中的文件都会被覆盖为过去的版本,而本地库中文件仍然保持回退前的样子,此时只需要再次通过 git commit
进行提交即可更新本地库。git checkout -- 文件名(文件路径)
;
该指令可以撤销在当前工作目录中对文件的修改,如果文件之前已经上传到了暂存区(此时又对文件进行了修改),那么就将文件撤回到暂存区中的状态;如果文件还未上传到暂存区,但之前已经上传到本地库中了,那么就将文件撤回到本地库中的最新状态。
如果在当前目录误删了文件,可以使用该指令恢复。
指令中的
--
不能够省略,否则就变成后面切换分支的指令了。git rm --cached 文件名(文件路径)
;
该指令可以将某个已经上传到暂存区或是提交到本地库的文件重新设置为未跟踪的状态(相当于从暂存区文件集合中将该文件移除,本地库中该文件仍然存在,可以通过
git ls...
指令验证),执行该指令后,通过 git status
查看该文件的状态,会出现下图所示的情形:
我对
hello3.txt
文件执行了该指令,于是 hello3.txt
便经历了两个状态:① 从暂存区的文件集合中被删除;② 重新被列入未追踪状态,git 不再跟踪该文件的变化。只要此时通过
git commit
进行提交,那么本地库中也会将该文件移除,此时文件只会处于当前工作目录中。【补充】Git 仓库中的文件删除操作
请在理解了前面暂存区和本地库文件集合的基础上阅读这部分内容。本节介绍一下文件的删除操作。
文件的删除有两种方式可以实现:
rm 文件名
直接移除工作目录中的文件;
git rm 文件名
直接移除暂存区中的文件。
第一种方式在前面介绍“暂存区和本地库文件集合”时就已经提过了,现在说明一下
git rm 文件名
的方式。这种方式其实也很好理解,它相当于是将工作目录和暂存区中的文件一起移除了,此时通过
git status
查看当前工作区的状态会看到删除的文件处于 Changes to be committed
状态。因此只需要进行删除文件的提交即可,git commit -m "删除文件 hello2.txt"
。
【补充】Bug 分支
省流:git stash -m "xxx"
(保存暂存区)→git switch master
→git switch -c issue-xxx
→ 修复 bug →git add xxx && git commit -m "xxx"
→git switch master
→git merge --no-ff -m "xxx" issue-xxx
→git branch -d issue-xxx
(删除问题修复分支)→git switch dev
(切换回工作分支) →git stash pop
→git cherry-pick <bug提交记录的编号>
→ 完成,继续工作。
假如我们当前在
dev
分支上进行工作,突然间被告知 master
分支上的某个文件出现了 bug,我们就被迫要停下手中的工作,去进行 bug 的修复。由于我们之前的工作尚未完成,因此文件的创建、删除或修改的记录仍然存放在暂存区中。在修复 bug 前,我们必须先明确一点:所有分支的暂存区内容是同步的,也就是说,我们在
dev
分支中产生的暂存区记录在 master
分支上同样存在。因此,如果我们要前往
master
分支修复 bug,在修复完成后,我们必须使用 git commit -m "备注" 文件名
对指定的 bug 文件进行提交,如果直接使用 git commit -m ""
则会将之前的所有工作一并提交,当我们回到 dev
分支时,过去的工作就都会不存在了。上述对指定 bug 文件进行提交的操作只适用于少量的文件(只有一两个文件)出现错误的情况,因为如果改动 bug 涉及到多个文件,我们一一指定文件名进行提交不仅会增加工作量,而且可能会错误提交之前处于暂存区的文件。因此,在修复 bug 时,更加推荐的一个方法是 —— 将当前暂存区先保存快照,然后再去修复 bug。
首先,在当前分支下执行指令
git stash
(指令 git stash push
的简化版),将当前的暂存区打包储存(有点类似于保护工作现场的操作),此时再运行指令 git status
会发现当前的暂存区被清空了。git stash
会默认将当前分支最近一次提交的备注内容作为暂存区的备注,当我们多次备份同一分支时会出现混淆,比如
因此,我们最好像提交本地库一样,对
git stash
也做好备注,方法为 git stash -m "xxx"
。然后转换到出现问题的分支,在该分支上创建一个新的分支
issue-自定义编号
(当然也可以用其他名字) ,用于专门修复 bug 文件。在 issue-xxx
分支中修复完 bug 后,回到问题分支,将 issue-xxx
分支与问题分支合并,确认没有问题后再次回到过去工作的分支下。现在要做的工作就是恢复暂存区了,使用指令
git stash list
可以查看所有储存的暂存区:
接下来有两种方式可以对暂存区进行恢复:
git stash pop stash@{n}
恢复第 n 次暂存,同时将第 n 次暂存记录删除,stash@{n}
可以通过git stash list
查看;
【
git stash pop
可以恢复最近一次的暂存并删除该次记录,如果只有过一次暂存,用这条指令比较方便】git stash apply stash@{n}
能够恢复第 n 次暂存,同时保留第 n 次记录,如果后续要将这一次的记录删除,可以使用git stash drop stash@{n}
进行。
如果仅想删除第 n 次暂存记录,也可以使用
git stash drop stash@{n}
。现在来讨论一个问题,由于 bug 是在其他分支(如
master
)上出现的,虽然我们对那个分支进行了修改,可是我们当前工作的分支其实还是存在这个 bug 的,因此,我们还需要对自己的分支进行一遍修改,如果 bug 数目比较少还好说,但如果要修改的 bug 数目很多呢?手动再进行一次修改肯定不现实,git
贴心的提供了一条指令帮助我们在当前分支回放之前的修改(只会同步我们在 bug 分支上改动过的内容,而不会像 merge
一样合并整个分支)。假设我们一开始在
merge_branch
分支中工作(master
分支和 merge_branch
分支都存在 bug.txt
文件),现在到 master
分支中创建了 issue-1
分支,将 bug 文件修复,此时回到 master
分支合并修复。
现在,我们想要在
merge_branch
中同步 master 里的修改,可以采用 git cherry-pick ff550f9
指令。其中 ff550f9
就是我们在 issue-1
分支修复完并提交的记录。【补充】Git 标签
标签的添加与查看:
- 命令
git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个commit id(git tag <tagname> [commit id]
),如git tag v0.1 f52c663
;
- 命令
git tag -a <tagname> -m "blablabla..."
可以指定标签信息(或git tag -a <tagname> -m "xxx" [commit id]
指定 commit id 的标签信息);
- 命令
git tag
可以查看所有标签;
- 命令
git show <tagname>
可以查看标签信息。
标签的推送与删除:
- 命令
git push <远程库链接或别名> <tagname>
可以推送一个本地标签;
- 命令
git push <远程库链接或别名> --tags
可以推送全部未推送过的本地标签;
- 命令
git tag -d <tagname>
可以删除一个本地标签;
- 命令
git push <远程库链接或别名> :refs/tags/<tagname>
可以删除一个远程标签。
【补充】.git
文件的查看
使用 git bash 打开 git 仓库后,通过
cd .git
即可进入仓库的 .git
目录,ll
即可显示 .git
仓库的文件及目录。
其中,
HEAD
中存放的是当前 HEAD
指针指向的分支,index
中存放的是暂存区中的文件。【补充】.gitignore
目录 → 忽略文件
可以前往廖老师的 github 项目中自动生成 git 文件: Git Ignore Online Generator
本部分内容摘自 git 的官方教程: git - 忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为
.gitignore
的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore
例子:第一行告诉 Git 忽略所有以
.o
或 .a
结尾的文件(DF:后面会介绍)。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。 要养成一开始就为你的新仓库设置好
.gitignore
文件的习惯,以免将来误提交这类无用的文件。文件
.gitignore
的格式规范如下:- 所有空行或者以
#
开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(
/
)开头防止递归。
- 匹配模式可以以(
/
)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(
!
)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(
*
)匹配零个或多个任意字符;[abc]
匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?
)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9]
表示匹配所有 0 到 9 的数字)。 使用两个星号(**
)表示匹配任意中间目录,比如 a/**/z
可以匹配 a/z
、 a/b/z
或 a/b/c/z
等。我们再看一个
.gitignore
文件的例子:💡 Tip | GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表, 你可以在 https://github.com/github/gitignore 找到它。 |
DF:这里我已经给大家下载好了:
📚 Note | 在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore 文件,它递归地应用到整个仓库中。 然而,子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。 (Linux 内核的源码库拥有 206 个 .gitignore 文件。)
多个 .gitignore 文件的具体细节超出了本书的范围,更多详情见 man gitignore 。 |
【补充】Git 别名
下面的内容摘自: Git - Git 别名
Git 并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过
git config
文件来轻松地为每一个命令设置一个别名。 这里有一些例子你可以试试:这意味着,当要输入
git commit
时,只需要输入 git ci
。 随着你继续不断地使用 Git,可能也会经常使用其他命令,所以创建别名时不要犹豫。从上面的教程中可以看出,配置别名的指令为
git config --global alias.[别名] [指令名称]
。其中:
- 指令名称多于一个单词的时候(指令间用空格分隔时)需要使用引号括起来,如
'reset HEAD'
;
- 如果指令中需要用到双引号,则最外层就用单引号括起来,如
git commit -m 'update "README.txt"'
;
- 如果指令中需要用到单引号,则最外层就用双引号括起来,如
git commit -m "update 'README.txt'"
。
在指令中,
--global
参数表示当前的配置对当前用户的所有仓库生效,是写在全局仓库中的,配置信息会存入 %userprofile%/.gitconfig
文件中(在 Windows 资源管理器的地址栏中输入即可打开)【或通过路径 C:\Users\用户名\.gitconfig
找到】。如果不使用
--global
参数默认是只对当前仓库生效的,配置信息会存入 /.git/config
文件中,在 git bash
里输入 cat .git/config
即可查看文件内容:
其中
[alias]
参数后面的指令就表示当前设置的别名,我们可以直接通过 vim .git/config
修改文件中的内容,添加或删除一些配置。一个有意思的别名:
在查看 git 的提交信息时,如果我们想要输出的信息可视化程度更高,同时信息更丰富,可以使用下面的配置:
然后调用
git lg
指令,就可以生成如下图这样美观的提交记录:
【补充】Git 的图形化工具
官方记录的所有 git 的图形化工具:Git - GUI Clients 。
在我们熟练了
git
的相关指令后,可以使用git
的图形化工具来可视化我们的 git
提交,提高我们的效率(这样就不用在 git bash
中一个个敲指令了)。寥雪峰老师推荐我们使用 SourceTree 这款工具,SourceTree 工具是免费的,下载地址为: Sourcetree | Free Git GUI for Mac and Windows。
寥老师对这款工具的使用做了一些介绍: 使用SourceTree - Git教程 - 廖雪峰的官方网站 。
Git 实现团队协作与跨团队协作(Github、Gitee)
当需要使用 git 进行团队协作时就需要进行联网了,同时 git 的远程库都会保存在云服务器中。全球比较知名的云服务器为 github(全球最大的同性交友网站);国内比较知名的是 Gitee。
团队协作与跨团队协作
团队协作
在前面介绍的内容中,
git
都是基于本地库来进行操作的,也就是说前面的所有操作都是可以在离线状态下进行的,而如果要进行团队内的协作,那么就需要在联网状态下进行。团队协作是基于远程库进行的,每个远程库都有一个管理员,管理员具有最高的权限,可以赋予其他成员将本地库文件
push
到远程库的权力。而在团队中的每个成员,默认都可以进行远程库中文件的下载,这个过程称为是
clone
。团队成员修改代码后,将代码发送给管理员的行为称为是 pull request
,管理员接收到文件后进行审核,无误后合并修改后的文件到远程库中。团队协作的一般流程为:管理员
push
文件到远程库,团队成员将远程库中的文件 clone
到本地库中。若团队成员认为文件内容有优化的地方,对代码文件进行了修改,需要向管理员请求 push
的权限(或发起 pull request
),管理员允许后,团队成员可以将修改后的文件 push
到远程库的特定分支(或通过 pull request
提交修改)。管理员对文件进行审核,如果确认修改无误,最终完成合并操作。【pull request
每个成员默认都可以进行,而 push
到特定分支只有授权后才能进行】跨团队协作
跨团队协作是基于主团队远程库进行的,主团队远程库的管理员拥有最高权限,可以决定是否接受外部团队提交的修改。
外部团队的成员默认只能下载主团队远程库的文件,这个过程称为
clone
。若外部团队认为需要修改主团队的代码,需要先在自己的远程库中创建主团队远程库的完整副本,这个过程称为 fork
。外部团队在 fork
的仓库中修改文件后,可以向主团队发起 pull request
,请求合并修改到主团队的远程库中。主团队的管理员会收到
pull request
通知,并对修改内容进行审核。如果管理员认为修改合理,可以批准并将外部团队的代码合并到主团队的远程库中;如果存在冲突或问题,管理员会要求外部团队调整代码后重新提交。跨团队协作的一般流程为:主团队管理员
push
初始文件到远程库,外部团队将主团队库 fork
到自己的远程库中,外部团队成员将副本 clone
到本地库中进行修改。外部团队成员修改好代码后,直接 push
到自己 fork
的仓库(进行团队内部协作),并通过 pull request
提交给主团队。主团队管理员审核代码,确认无误后完成合并,最终更新主团队的远程库。Github(SSH 协议)
利用 github 实现团队协作
首先需要创建一个 github 账号,大家可以去网上搜一搜怎么创建 github 账户,按照教程来就行,下面的教程假设大家已经拥有 github 账户了。
大家如果想要在不通过科学上网的情况下访问 github,拉取 github 的远程库,可以使用后面的 SSH 协议实现免密登录。
【工具推荐】关于 github 访问的网络问题
推荐大家一个加速工具
steam++
,相信经常用 steam 打游戏的友友应该对这个不陌生。这个软件除了可以用来加速 steam 外,也可以用于 github 和 spotify 等网站的加速,而且这些网站的加速还是免费的。steam++
只能够保证我们能够访问 github 网站,对于其他软件,如 git
,还是无法实现代理,因此如果只有访问 github
的需求,那么这个软件是足够的,如果要进行后面的 push
操作,只能使用另外的“科学上网”工具。“科学上网”工具,入门的我推荐浏览器的插件 “无忧行 ”,它虽然是浏览器插件,但它有定期提供 v2ray 节点,因此我们在浏览器安装 无忧行 插件后,再下载一个 v2rayN 工具即可实现全局代理了。当然,无忧行是需要付费的,不过也不贵。
创建远程库
登录 github 账户后,可以在网页的右上角找到下图所示的按钮,点击
New repository
即可创建一个新的远程库了。
接着,按照下图所示的步骤进行操作:

创建好仓库后会跳转到下面这个页面中,一定要记得点击
HTTPS
:
点击了
HTTPS
后,复制右侧的链接。经过上述过程,远程库就建立完成啦,之后就等待后续的文件上传了。
创建远程库链接别名
打开
git
目录,右键进入 git bash
,在 git bash
中,与远程库别名相关的指令有两条:git remote -v
;
可以查看当前 git 库中已经创建了哪些别名;
git remote add 别名 远程库链接
;
可以为远程库链接取一个别名,方便后续调取使用,建议别名取为自己的 git 目录名,防止未来仓库多起来时产生混乱。
按照下图所示的步骤为刚刚复制的 github 远程库链接创建一个别名。

【补充】修改远程库链接别名
推送本地库到远程库(push
)
省流,非冲突推送:git push 别名(或 github 远程库链接) 分支名
;
省流,冲突推送:git pull 远程库别名/远程库链接 本地库分支
→vim 冲突文件
→git add 冲突文件
→git commit -m "内容"
→git push 别名(或 github 远程库链接) 分支名
【需要利用到后一节的指令】
指令:
git push 别名(或 github 远程库链接) 分支名
。其中,别名就是前面创建的远程库别名,如果当时没有创建别名,那么也可以使用 github 的远程库链接,最后的分支名为需要推送的分支名字。
注意,推送的最小单位为分支,需要指定推送的是本地库的哪个分支。
比如,我推送的指令为
git push git_repository master
。推送完成后,会显示下图所示的信息:
如果 github 远程库中有本地库文件,但 github 远程库中的文件和 git 本地库中的文件同时进行了修改,发生了冲突合并的情况:
首先,在 git 中创建一个新文件
push.txt
(touch push.txt
)用于测试冲突合并,然后通过 git add push.txt
和 git commit -m "创建了 push.txt" push.txt
将 push.txt
文件上传到本地库。通过 git push git_repository master
将同步 github 的远程库与本地库。下面同时修改 github 远程库与 git bash 本地库中的文件:


这里要记得在 git 中将
push.txt
的修改上传到本地库,运行 git add push.txt
和 git commit -m "git bash 中修改了 push.txt" push.txt
指令。然后将本地库中的文件推送到远程库中,
git push git_repository master
。
此时出现上图所示的报错,说必须要先将 github 中的文件拉取到本地库中进行修改,然后才能再次
push
到本地库中(要使用后面一个部分的内容)。拉取远程库到本地库(pull
)
省流, 非冲突情况:git pull 远程库别名/远程库链接 本地库分支
;省流,冲突情况:git pull 远程库别名/远程库链接 本地库分支
→vim 冲突文件
→git add 冲突文件
→git commit -m "内容"
(无需加上文件名)。
当远程库的代码被修改后,就需要将远程库的代码拉取到本地库中合并。
拉取指令:
git pull 远程库别名/远程库链接 本地库分支
。比如我在 github 中对
hello.txt
文件进行如下编辑:

通过左图操作打开编辑模式后,添加上面的语句。
现在我在 git bash 中对远程库的文件进行拉取,会提示修改的信息:

注意,从远程库中拉取时都是拉取到本地库中,因此拉取后会直接与本地库的最新文件进行合并。
如果同时修改
github
和 git bash
中的 hello.txt
文件:git bash
中:
git bash
中修改后记得运行 git add hello.txt
和 git commit -m "在 git bash 中修改了 hello.txt 文件" hello.txt
语句将修改提交到本地库。github
中:
此时运行指令
git pull git_repository master
时也会出现冲突合并的报错:
按照过去所学的合并冲突分支的方法,对冲突内容进行取舍后,得到下图所示的文件:


最后再执行
git add hello.txt
和 git commit -m "github 和 git bash 冲突文件合并"
。
远程库代码克隆到本地库(clone
)
省流:git clone 复制的远程库链接
即可实现克隆操作。
git clone
用于首次获取远程仓库的全部代码,将整个远程仓库(包括所有分支、提交历史、标签等)完整复制到本地。
克隆仓库的几个注意点:
- 克隆仓库无需登录账号(也就是说新创建的 git 仓库即使不进行
git config...
也能够克隆代码);
- 克隆会自动实现 ① 拉取代码; ② 初始化本地库; ③ 创建别名 三个操作;
- 无论本地库是否进行了初始化操作,是否是一个新的本地库,都可以进行克隆操作(个人尝试后得出的结论)。
克隆的基本流程:
首先,按照下图所示方式获取远程库的克隆链接:

然后,在本地新建一个目录(如果想将库克隆到自己已有的库中,这里就无需新建一个目录),进入目录后右键打开 git bash,输入
git clone 复制的远程库链接
即可实现远程库的克隆。【这里远程库链接如果使用创建的别名,好像就无法运行了,比如 git remote add git_repository 远程库链接
→ git clone git_repository
】克隆的远程库会以文件夹的形式放在你的 git 仓库中:

我们可以在
git bash
里输入 cd git_repository
进入我们克隆的远程库,通过 git remote -v
指令即可看到克隆过程中已经自动帮助我们创建了仓库的别名 origin
:
上述操作给我的感觉就是库的嵌套,在我们的本地库中嵌套了一个远程库,在这个远程库里的操作与在本地库中的操作方法是相同的。
clone
和 pull
两条指令的区别(AI 总结):场景 | git clone | git pull |
适用阶段 | 初次下载项目 | 已有本地仓库,需更新代码 |
数据量 | 下载整个仓库(完整历史) | 仅下载新增的变更(增量更新) |
本地仓库状态 | 新建本地仓库 | 更新现有本地仓库 |
远程关联 | 自动关联远程仓库( origin ) | 依赖已配置的远程仓库地址 |
合并操作 | 无需合并 | 可能触发合并冲突 |
模拟团队内成员合作的流程
这个部分建议大家自己去模拟一下,在这个部分,我新建了两个库,重复了本地库与远程库的相关操作。
假设团队内有两个成员
DFBlowing
和 df-xiao
,他们的本地库名分别为 git_DFBlowing
和 git_df-xiao
。我将使用 Edge 浏览器登录
DFBlowing
的 github 账户,使用谷歌浏览器登录 df-xiao
的 github 账户来分别模拟两个用户。其中,
git_DFBlowing
创建了一个 github 的远程库(名字为 git_DFBlowing
),在本地库中创建并上传了 hello.txt
文件,hello.txt
的内容如下:
git_DFBlowing
将本地库文件上传到了远程库,因此在 github 的 git_DFBlowing
库中有了 hello.txt
文件:
此时,
git_df-xiao
获取了 github 的远程库链接,并将远程库 clone
到了本地库中,效果如下:
接下来模拟团队内成员合作的流程:
开始时,
DFBlowing
未将 df-xiao
拉到自己的团队中,因此 df-xiao
修改文件后无法直接 push
到 git_DFBlowing
仓库中。因此先模拟产生报错的情形。- 用 git bash 打开
df-xiao
的 git 仓库,cd git_DFBlowing
进入克隆的仓库,使用vim hello.txt
修改hello.txt
文件:

- 通过
git add hello.txt
和git commit -m "df-xiao 修改了 hello.txt 文件" hello.txt
将修改后的hello.txt
文件上传到本地库。

- 在
df-xiao
推送本地库之前,请先进入 Windows 凭据管理器将先前DFBlowing
的登录情况给删除,避免使用DFBlowing
的 github 账户推送df-xiao
的修改,造成错误的结果;
凭据管理器删除过程如下


- 删除凭据管理器中关于
git: DFBlowing
的登录后,通过git push origin master
将本地库文件推送到远程库,会弹出弹窗要求登录验证,使用df-xiao
的账户登录(因为是df-xiao
要上传文件给DFBlowing
的远程库),出现了下图所示的报错:

报错的原因就是
DFBlowing
未将 df-xiao
拉入自己的团队。下面,模拟
DFBlowing
将 df-xiao
拉入自己的团队后的 push
操作:- 首先将
df-xiao
拉入DFBlowing
的团队;
加入步骤如下
注意,邀请是在某个远程库中进行的。邀请成功后,df-xiao
也许在该本地库中与DFBlowing
是一个团队,但在DFBlowing
的其他库中需要重新被邀请的。





- 再次执行
git push origin master
的操作,可能仍会弹出一个弹窗要求登录,再次使用df-xiao
的账户登录后,会提示上传成功:

在谷歌中的
DFBlowing
账户里查看 hello.txt
文件,可以看到内容已经发生了更改:
模拟跨团队协作的流程
跨团队协作与团队内协作的流程相比,主要是多出了 fork 的流程。通过 fork 操作,我们可以将代码分叉到我们自己的远程仓库中,同时,保留自己的该仓库与原仓库之间的关联性。我们在 fork 的仓库里进行的修改,可以通过 pull request 提交给仓库作者,与仓库作者交流沟通修改的内容。这也是为什么 github 会被称为是全球最大的同性交友网站的原因,我们所有人无论是作为个人还是作为团队,都可以与其他人或其他团队交流新的代码修改,相比于微信和 QQ,内容更聚焦于项目本身。
跨团队协作过程的模拟:
仍然采用
DFBlowing
和 df-xiao
两个用户进行跨团队协作的模拟,使用 Edge
浏览器登录 DFBlowing
的账户,使用谷歌浏览器登录 df-xiao
的账户。DFBlowing
和 df-xiao
两个用户的本地库名分别为 git_DFBlowing
和 git_df-xiao
。现在要进行的是 DFBlowing
fork 用户 df-xiao
的本地项目。首先在
df-xiao
的 github 中创建远程库 git_df-xiao
(这里与 df_xiao
的本地库同名) ,然后用 git bash 打开 git_df-xiao
的本地库,创建并上传 test.txt
文件到远程库中,test.txt
的内容如下:

然后打开
DFBlowing
的账户,寻找 df-xiao
的项目有两种方式。寻找方式
- 利用 github 的项目搜索,搜索框中输入
用户/项目名称
,比如df-xiao/git_df-xiao
。
具体步骤
以下步骤只是演示,大家不要 fork 我的这个项目哦。




- 利用对方发送过来的项目链接。

fork 项目以后,
DFBlowing
的本地仓库内就会多出一个项目 git_df-xiao
,将该项目(要 fork 过来的远程库的项目链接)克隆到本地库中进行修改。
打开
git_DFBlowing
目录,右键打开 git bash,在 git bash 中输入 git clone 远程库链接
,克隆的过程如下:
通过
vim test.txt
修改文件内容为:
将修改后的文件保存、提交、上传到远程库中(记得删除凭据管理器中 git 的记录),上传的过程如下:

上传完成后,
DFBlowing
进行 pull request
,具体的流程如下:





fork
和 clone
有些人可能会想,
fork
原项目到本地仓库后还需要进行 clone
操作,那么我为什么不能将原项目 clone
到本地库,在 github 中创建一个空的库,然后将代码修改后 push
到自己的远程库中呢?首先呢,这种方法确实是理论可行的,但违背了
fork
和 clone
的初衷。我们
fork
项目的目的一方面是为了享受原项目带来的帮助,另一方面是为了进行跨团队的协作。fork
代码可以将我们的远程库与作者的远程库相关联,如果你对于代码有新的想法和修改意见,你可以在本地将代码修改后 push
到远程库中,然后执行 pull request
(PR)操作,这样作者就能够看到你的修改,与你一同讨论交流。而如果你仅仅只是进行
clone
操作,那么就失去了自己项目与原项目之间的关联性,无法进行 PR 操作。从另一个角度上来说,
fork
项目是对原项目作者的一种支持,能够鼓励原项目作者持续不断的进行开源更新,如果有些人只想秉持白嫖精神到底,连一颗 fork
的星星都不愿意给出,那么就是对开源的一种迫害。不进行 fork
直接 clone
也会让他们无法知晓项目何时更新,必须付出更多的精力去浏览该项目,而 fork
的好处便是你能够在自己 fork
的仓库中看到项目的更新情况,让你始终跟上项目的节奏。通过 SSH 协议实现免密登录
SSH(Secure Shell) 是一种加密网络协议,用于在不安全的网络(如互联网)中安全地访问和管理远程计算机或服务器。
相信学习过 Linux 的小伙伴应该对 SSH 协议不陌生,当我们使用 Xshell 或其他软件远程登陆 Linux 系统时,使用的就是 SSH 协议。
使用 SSH 协议可以让我们与 GitHub、GitLab 等平台安全通信,无需每次输入密码。
下面介绍如何实现 SSH 协议下的免密通信:
第一步,本地创建 .ssh
文件并复制公钥
首先,需要在本地创建
.ssh
文件。打开文件资源管理器,在地址栏输入 %userprofile%
进入用户文件夹,然后右键打开 git bash
,输入 ssh-keygen -t rsa -C xxx.com
,其中 -t rsa
表示使用 rsa
加密算法,xxx.com
请改成自己需要免密登录的邮箱地址(也就是和 github 关联的邮箱)。执行指令后若需输入内容,按下回车即可。指令执行完成后后,会在本地目录中生成
.ssh
文件:
进入
.ssh
文件,我们即可看到加密的公钥和私钥:
在之前打开的
git bash
中 cd .ssh
进入 .ssh
文件,然后通过 cat id_rsa.pub
将公钥打印出来,复制打印出来的公钥,接下来要粘贴到 github 中。第二步,将公钥添加到 github 中
打开需要进行免密登录的 github 账户(与刚刚创建 SSH 的邮箱账户一致),按照下面的操作进行设置:





第三步,测试能否从 github 中拉取远程库文件到本地
添加完成后,可以先测试一下能否从 github 中拉取库。在 git bash 中输入
git pull [远程库 SSH 链接] [分支]
,比如 git pull git@github.com:... master
。如果最后有下面的字样,说明拉取成功,如果显示
fatal: ...
,说明网络原因拉取失败。
如果因为网络原因拉取失败可以进行下面的操作(无需外网即可进行 github 远程库的拉取)—— 修改 git 的 SSH 端口。
第四步,若第三步失败,则修改 SSH 端口号
再次进入文件资源管理器,在地址栏输入
%userprofile%
进入用户文件夹,右键空白处打开 git bash。在 git 中输入
vim .ssh/config
创建 config 文件,然后在文件中输入(直接复制粘贴就行):输入完成后按下
esc
键,输入 :wq
保存退出。然后在需要进行 SSH 免密登录的 git 仓库中右键打开 git bash,输入
ssh -T git@github.com
测试能否通过 SSH 访问到 github,如果提示 “Hi 用户名! You've successfully authenticated…”
即表示配置成功。再次执行指令
git pull 远程库SSH链接 分支
应该就可以实现拉取了。
Gitee(码云)
介绍
Gitee(码云)是中国领先的代码托管和协作平台,由开源中国(OSChina)团队开发,专注于为开发者提供高效、稳定的代码托管服务,尤其适合中国本土用户。
Gitee 可以算得上是 Github 的平替版,首先具有 github 的全部功能,同时界面是全中文的。
Gitee 的使用方法与 github 基本一致。
关于码云的注册
在注册码云时,如果大家有 github 账户,建议大家直接使用 GitHub 的邮箱地址进行注册,同时个人空间地址最好与 github 的用户名是相同的,这样在本地管理仓库会十分方便。不过这些在注册以后也可以进行更改,可以根据自己的需求来。
导入 github 项目
在码元中可以实现 github 项目的导入,同时也支持项目的更新。具体操作方法如下:



当然,我们也可以将 gitee 与 github 关联,这样可以直接导入自己在 github 中的仓库。
更新 github 项目
当导入的 github 的项目更新时,可以在码云内部直接实现同步:

点击图中的红框部分即可更新。
github 和 gitee 的仓库链接
github 和 gitee 的远程库链接是相似的,组成方式如下:
其中,如果是 github 仓库,网址就是
github.com
,用户名就是 github 的用户名,仓库名要根据特定的仓库而定,如果是 github 的 git_repository
仓库,仓库名就是 git_repository
;如果是 gitee 仓库,网址就是
gitee.com
,用户名就是注册时输入的个人空间地址,仓库名也是根据特定仓库而定,与 github 规则相同。下面是同一个仓库在 github 与 gitee 中的链接示意:
github 仓库:
https://github.com/DFBlowing/git_repository.git
;gitee 仓库:
https://gitee.com/DFBlowing/git_repository.git
。【补充】git rebase
操作
这部分内容参考 B 站视频 【B站最全Git进阶课程】git rebase: 人生无法重来,但代码可以!,视频、截图大部分来源于该视频。
git rebase
的使用方法
该指令的使用方法和场景与
git merge
一样,使用方法为:git rebase 分支名
。具体的区别在下一个部分介绍。rebase
操作用中文描述为 “变基” 操作。git rebase
和 git merge
的区别
git merge
和 git rebase
指令类似,都可以将本地最新的修改同步到远程库中。假设现在我们从远程库中克隆了最新的分支(拥有版本 和 )到本地进行修改,增加了三个版本 、 和 ,但在我们进行分支修改的时候,远程库中的分支发生了新的变化(增加了版本 和 ),现在比较
merge
和 rebase
两个指令有什么区别。git merge
的过程:从上面的视频中可以看到,
git merge
是以分支中的 版本、 版本以及本地修改的 版本为参考,新生成了一个 版本后合并。合并之后,如果使用 git log --graph --pretty=oneline --abbrev-commit
指令查看远程库中分支的提交过程,既会显示图中绿色的分支,也会显示蓝色的分支,在同一时间有多个人提交多个分支后,会显得比较混乱(如下图所示)。
git rebase
的过程:从上面的视频中可以看到,
git rebase
与 git merge
不同,是将当前本地库中的三个版本 、 和 中新增加的修改修补到 版本中,如果使用 git log --graph --pretty=oneline --abbrev-commit
指令查看分支的修改过程,只会显示一条分支,这样的分支修改更加的清爽,减小了代码审查员的工作量。merge
和 rebase
两者最终结果的差异:
git rebase
指令的常用操作
首先介绍指令
git rebase -i [目标]
,接下来要进行的操作都是基于该指令进行的。git rebase -i [目标]
会打开一个交互式变基窗口,在窗口中可以进行修改、合并、删除或重新排序提交等操作。其中
[目标]
项用于指定变基起点,起点可以是 分支名、版本号或是 HEAD
及其相对引用。比如:
git rebase -i master
(将当前分支的提交变基到master
分支下,会找到当前分支与master
分支最后一次同步的基点作为变基的起点);
git rebase -i 9f34ab1
(直接使用某个提交的哈希值作为变基的起点);
git rebase -i HEAD^3
(将最近的第 3 次提交作为变基的起点)。
打开交互式变基窗口后,可以看到如下的窗口,其中没有
#
的部分就是接下来变基操作要执行的指令(从上到下顺序执行):
常用指令的使用效果:
- 直接修改提交顺序;
由于指令是从上到下顺序执行的,如果我们修改了
pick
的顺序就会修改接下来变基操作的提交顺序。
pick
→squash
;

pick
→drop
;

综合使用:
假如现在我们在 版本上又新增了 的版本,但在要提交时,发现有些版本颠倒一下顺序比较好,有些则不是很需要可以扔掉,最终的流程如下。

千万不要用
rebase
处理已经被其他协作者修引用的提交。Git 指令总结
如果本篇笔记对你有用,能否『请我吃根棒棒糖🍭 』🤠…