『Git』Git使用教程
基本概念
-
概念
Git 是一种 分布式版本控制系统(DVCS),用于跟踪文件的更改,特别适用于软件开发。它允许多个开发者协作处理同一个项目,并能有效管理代码的历史记录。
-
Git 与 GitHub、GitLab 的区别
GitHub、GitLab 等是 基于 Git 的代码托管平台,允许开发者远程存储和管理 Git 仓库。它提供了一系列协作工具,如 issue 追踪、Pull Request(PR)合并、代码审查等。
-
SVN 与 Git 的区别
-
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。
-
Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
-
-
Git 的工作原理
1)工作区、暂存区和本地仓库
- 工作区就是我们在文件资源管理器里面看到的项目文件夹,包含所有的代码和文件。这里的文件可以是新创建的、修改过的,甚至是删除的。但这些更改并不会自动被 Git 追踪,必须手动添加到暂存区。
- 暂存区是 Git 记录变更的 临时存放区,当你使用
git add
命令时,修改会被加入暂存区,只有暂存区中的内容才能被git commit
提交到本地仓库。它保存了当前文件的状态,而不会影响其他未暂存的文件。 - 本地仓库存放的是你所有的提交历史,保存在
.git
目录中。当你运行git commit
时,暂存区的内容就会被提交到本地仓库,形成一个新的提交记录。这里的文件是 受 Git 版本控制的,但还没有推送到远程仓库。
2)本地仓库和远程仓库
远程仓即远程仓库是存放在 GitHub、GitLab、Bitbucket 等代码托管平台上的仓库。
初始化配置
-
下载安装Git并连接Github
参考:https://blog.csdn.net/secretstarlyp/article/details/106576882
-
配置用户名和邮箱
后续每一个 Git 提交都会使用这些信息,这样在提交的时候才能识别出来是谁提交的内容。
1
2
3
4git config --global user.name isoda_das
git config --global user.email xxxxx@qq.com
# 保存
git config --global credential.helper store这里使用了–global参数,表示该设置为全局配置,对所有仓库有效。如果不设置的话仅对本地仓库有效
-
查看配置信息是否生效
1
git config --global --list
Git 基础命令
新建Git仓库
新建一个文件夹或现有的文件夹并不是 git 仓库,因为文件夹内不包含 .git
文件夹,没有被 git 管理。
所以可以在你希望使用 git 管理的文件夹下,运行如下命令初始化空的git版本库。
1 | git init |
初始化完成后,如果在项目文件夹中没有看到 .git
文件夹,则需要开启显示隐藏文件。
记录更新到Git仓库
流程:工作区开发—>将修改后的文件添加到暂存区—>将暂存区的文件记录到版本库
-
把工作区变化的文件添加到暂存区
1
2
3
4
5
6
7
8
9
10
11# 将 index.html 添加到暂存区
git add index.html
# 将css目录下一切添加到暂存区
git add css
# 添加所有后缀为txt的文件
git add *.txt
# 将当前目录下所有变化都暂存
git add . -
将暂存区内的文件提交到本地仓库
注意这里不会提交工作区的文件,此处文字说明可以不加引号
1
2
3
4
5# 直接输入提交信息
git commit -m "第一次提交"
# vim输入提交信息
git commit如果commit中存在一些错误:
- 在没有推送到远程仓库的情况下:可以通过
git commit --amend
这个命令来修改最近的commit信息 ,生成一个新的提交替代原有的提交 - 在已经推送到远程仓库的情况下:可以通过
git revert <commit_hash>
命令来撤销掉这个提交,创建一个新的提交并进行git push
- 在没有推送到远程仓库的情况下:可以通过
查看状态
-
查看提交记录
1
git log
-
查看仓库状态
1
git status
可以看到
- 绿色:表示已经被添加到暂存区,但未被提交(到本地仓库)
- 红色:未被跟踪,即没有被添加到暂存区的文件
-
版本差异检查
1
2
3
4
5
6
7
8
9
10# 比较工作区和暂存区的差异
git diff
# 比较工作区和本地仓库的差异
git diff HEAD
# 比较暂存区和本地仓库的差异
git diff --cache
# 比较两个版本提交记录之间的差异
git diff 5af90b8 7100ee3
# 仅比较file.txt的差异内容
git diff xx file.txt
版本回退
使用git log
查看提交历史,前面即历史提交的标识符
1 | # 回退上一个版本 |
删除文件
直接从工作区和暂存区删除,但后续仍然要提交commit
1 | git rm file.txt |
直接放入回收站的话,注意后续仍要进行add和commit操作
gitignore忽略文件
有些时候,我们可能希望设置不push项目目录下的某些内容上去,如密钥文件等。
创建gitignore文件,在里面写入需要进行忽略的内容
1 | echo access.log > .gitignore |
规则:
Git 分支
创建分支
在Git中新建一个项目后,默认有一个分支,即主分支。主分支一般表示项目的稳定版本(已完成的代码),主分支应该包含稳定没有 Bug 的代码,并保持随时可以发布的状态。而 dev是平常用来开发的分支,开发完成后再将 dev 分支合并到 master 分支
对于小型项目来说,只有一个主分支就够用了,每次我们提交都会创建一个commit节点。
1 | git commit -m "c1" |
上面的命令会创建三个commit节点,此时master分支如下图所示,代码经历了C1,C2,C3这三个版本,且master分支目前指向C3这个提交版本。
如果项目功能较复杂,且需要多次提交,不建议在主分支直接修改。主分支上应该只包合并提交,所有的迭代应该都在分支上进行。如果是简单的改动,直接在主分支修改也是可以的。
当有新的功能要开发时,应该新建一个功能分支,比如创建一个名为a的分支,并切换到a分支,命令如下:
1 | git checkout -b a |
创建新分支时,新分支默认指向的代码提交版本为当前分支所指向的代码提交版本,比如这里新分支a指向的提交将为C3。此时当前分支为a,所指向的提交为C3。
合并分支
如果需要合并experiment分支和master分支
merge方法
-
原理
将两个或多个分支的修改集成到一个新的提交中。在合并时,Git 会首先找到两个分支的共同祖先作为基准点,然后使用三方合并算法来将两个分支的修改合并到一个新的提交中。该算法比较共同祖先和要合并的两个分支之间的差异,然后尝试自动合并这些差异。如果两个分支对同一个文件的不同部分进行了修改,Git 通常能够自动合并这些修改;但如果两个分支对同一文件的同一部分进行了不兼容的修改,就会产生冲突,需要手动解决。
最后实现的结果:
-
方法
切换到目标分支(通常是主分支): 在合并之前,确保你已经切换到你希望将其他分支合并到的目标分支。例如,通常我们会将分离出来的开发分支合并到主分支。
1
2
3git checkout main
或
git switch master合并指定分支到当前分支
1
git merge <branch>
后续可以再删除掉
experiment
分支1
git branch -d experiment
-
冲突处理
如果出现了冲突,则修改冲突文件,add然后commit该文件
1
2
3# 没有冲突时不需要下方的命令。有冲突时,就修改冲突文件,再add然后commit该文件,如下:
git add readme.txt
git commit -m "conflict fixed"
rebase方法
-
原理:
首先找到当前分支和目标基底分支的最近共同祖先,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,接着将当前分支指向目标基底,最后将之前另存为临时文件的修改依序应用到目标基底上。
最后实现的结果:
简单来说,就是提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次,像“重新播放”一样。
-
命令
1
2
3# 将主题分支<topicbranch>变基到目标分支<basebranch>上。
# 即提取在<topicbranch>上的补丁和修改,然后在<basebranch>的基础上应用一次。
git rebase <basebranch> <topicbranch>或者
1
2git switch <topicbranch>
git rebase <basebranch>合并完成后可以删除掉
experiment
分支1
git branch -d experiment
-
冲突处理
区别
-
原理
merge
:会创建一个新的合并提交(merge commit),以标记分支合并的时刻。这是一个显式的合并点。rebase
:没有合并提交,只是将提交“移动”到目标分支后,历史上看不到合并点。
-
历史记录
merge
:保留了分支的历史记录,包括分支的分叉和合并点。合并提交让历史图呈现出分支结构。rebase
:将所有提交按顺序重新应用,消除了分支结构,使得历史记录看起来是线性的。
-
使用场景
merge
:适用于团队合作中,多个开发者并行开发并合并到主分支时。保留所有的开发历史可以帮助回溯。rebase
:适用于在个人开发中,确保自己的开发历史更简洁、线性,并且可以在准备将工作合并到主分支之前,整理自己的提交历史。特别适合在需要保持干净、整洁的提交历史时使用。
远程仓库同步
我们上面学习的都是在本地的操作,只是将文件提交到本地仓库,这样并不能实现和其他开发者的同步。我们还需要一个代码托管平台作为远程仓库,比如这里我们选择 Github。
Git 和 Github 的连接在我们前面的初始化配置中已经完成。
将github项目pull到本地
什么是pull:将远程代码仓库中(新)的内容下载到本地,并更新本地代码仓库的内容
第一次pull:
首先需要在本地创建一个空文件夹,作为项目的存放仓库。然后进入该文件夹下,打开Git Bush,输入以下命令将该目录初始化为Git仓库。
1 | git init |
然后将这个本地仓库连接到Github上的对应项目
1 | # git remote add 仓库命名 远程仓库地址(github上项目的HTTPS协议地址) |
如果不小心填错了,可以使用指令清除地址重新设置
1 git remote remove origin同样也可以执行命令查看是否连接成功
1 git remote -v
然后,使用Pull指令拉取代码,从远程源的主分支更新代码到本地
1 | # git pull origin <branch-name> |
后续拉取github上的更新到本地:
1 | git pull origin master |
将本地项目push到github
-
什么是push:将本地库的内容推送到远程仓库中
-
第一次push:
同样的,在本地项目文件夹内初始化Git仓库
1
git init
执行add命令将整个文件夹添加到本地仓库
1
git add .
将这个本地仓库连接到Github上的对应项目
1
2# git remote add 仓库命名 远程仓库地址(github上项目的HTTPS协议地址)
git remote add origin https://github.com/soda-VV/soda-VV.github.io.git将本地更新后的代码上传到GitHub只需要
1
2git commit -m "第一次上传"
git push origin master/main注意:
如果推送失败的话,可以看一下仓库命名(origin)是否出错,或者是分支名称写错了(为main分支)
-
后续推送本地库的内容到远程仓库:
1
2
3git add .
git commit -m "第n次上传"
git push origin master
多人协作
如果在多个远程设备上操作,记得开始进行今日的操作前要先:
1 | git pull origin master/main |
完成所有操作准备离开时要记得:
1 | git add . |
tip: 要保证本地库和server是同步的,不然忘记先pull,若其他远程设备上已经push了新的内容,自己这里是push不上去的,只能进行git pull合并,这个操作还会覆盖你已经更改了的部分,会非常痛苦。
冲突问题
Git冲突通常发生在以下几种情况下:
- 拉取远程分支:当从远程仓库拉取分支时,如果本地分支与远程分支有不同的修改,并尝试合并时也可能发生冲突。
- 不同合并分支:当两个开发者在不同的分支上进行并行开发,并尝试将分支合并时,如果对同一文件的同一部分进行了修改,就会导致冲突。
拉取远程分支冲突
场景:在同一分支上,你本地有未提交的更改,但是别人也修改并 push 到远程了,这种情况下我们如何进行同步呢?
示例: 假设你正在开发一个特性,修改了 file.txt
文件,并且将它提交到本地分支。但是,在你提交后,远程仓库的其他开发者也修改了 file.txt
并提交了他们的更改。当你执行 git pull
拉取远程分支时,就可能会遇到冲突。
解决步骤:
-
首先执行
git pull
,Git 会显示冲突的文件,并在冲突的文件中插入标记:1
2
3
4
5<<<<<<< HEAD
你的本地修改
=======
远程的修改
>>>>>>> origin/branch-name -
你需要手动编辑
file.txt
,选择保留本地修改、远程修改,或者结合两者的内容。删除冲突标记(
<<
和>>
标识)后,保存文件。 -
在解决冲突后,使用
git add
将解决后的文件标记为已解决:1
git add file.txt
-
最后,执行
git commit
完成合并:1
git commit
如果修改较大且难以手动解决,也可以使用工具如 git mergetool
来辅助解决冲突。
不同分支合并冲突
场景:在多人并行开发时,每个开发者可能会在不同的分支上工作。如果他们修改了相同文件的相同部分,当尝试合并这两个分支时,也可能会发生冲突。
示例:开发者 A 在 feature1
分支上工作,修改了 file.txt
的第 10 行。开发者 B 在 feature2
分支上工作,也修改了 file.txt
的第 10 行。当开发者 A 和 B 都完成了工作并试图将 feature1
合并到 main
分支时,Git 会检测到冲突,因为两人都修改了 file.txt
的相同部分。
解决步骤
-
执行
git merge feature1
或git merge feature2
,Git 会检测到冲突并提示哪个文件有冲突。 -
与前一种情况类似,你需要手动编辑冲突文件,解决冲突。冲突部分会用
<<<<<<<
和>>>>>>>
标记出来。手动编辑并选择保留的修改,删除标记后,保存文件。
-
执行
git add file.txt
将解决冲突的文件标记为已解决。 -
最后,提交合并:
1
git commit
强制推送本地修改
git
强制推送本地修改的操作通常是使用 git push
命令,并加上 --force
(或者简写为 -f
)选项。这个操作会将本地仓库的内容强制推送到远程仓库,覆盖远程仓库当前的内容。下面是如何使用强制推送:
1 | git push origin <branch_name> --force |
注意:在日常工作中我们是不推荐 git -f
,为什么:
强制推送会覆盖远程仓库中的内容,如果是多人开发的情况下,可能会覆盖掉他人的工作。