1、初识Git
概述:Git 是一个开源的分布式版本控制系统,可以有效、高速地处理项目版本管理。
知识点补充:
版本控制:一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
分布式:每个人的开发机上都有独立的版本库,开发者可以在自己的开发机管理代码版本。
下载地址:Git (git-scm.com)
安装后验证:
python
# 在命令提示符中的任意路径输入如下命令
git -v
运行结果如下:
2、Git配置用户信息
配置用户信息:
python# 注意: --global 表示声明为全局设置,为可选项 $ git config --global user.name xxx $ git config --global user.email xxxx.com
检查用户的配置信息:
python$ git config --list
首先在桌面点击右键,然后点击 Git Bash Here 打开命令行:
然后配置用户名和邮箱,运行结果如下:
3、Git初始化本地仓库
如果要初始化本地仓库,需要进入工作区所在目录并执行如下命令:
pythongit init
首先在 D 盘创建一个名为 git 的文件夹,然后进入 git 文件夹,创建一个名为 sourceFile 的文件夹用于存放项目,进入该文件,点击右键,打开 Git Bash Here ,并输入如下命令:
python
# 在当前目录创建一个名为project01的文件夹
mkdir project01
# 进入创建的文件夹
cd project01
# 初始化本地仓库(重点是要提前进入工作区)
git init
运行结果如下:
初始化本地仓库后,该目录会多一个名为 .git 的文件夹:
如果看不到 .git 文件夹,按下面的步骤进行操作:
4、Git工作区暂存区和本地仓库
· 工作区:放项目代码的地方,项目代码对应的文件;
· 暂存区:也叫索引,是一个文件,保存了下次将提交的文件列表信息;
· 本地仓库:就是安全存放数据的位置,这里边有你提交的所有版本的数据。
Git 的工作流程:
①、在工作区中添加、修改文件;
②、添加工作区的更改到暂存区;
③、将暂存区域的文件列表信息提交到本地仓库。
5、Git跟踪文件
查看文件当前所处状态:
pythongit status
实现对文件的跟踪(将文件添加到暂存区):
pythongit add 要跟踪的文件
实现提交(将文件提交到本地仓库):
pythongit commit -m '提交信息'
注意:要想测试以上命令,首先需要在项目文件中存有工作文件。
实操:首先进入前面创建的如下目录中 D:\git\sourceFile\project01 ,然后打开 Git Bash Here 创建有效的文件:
python
# 将 "我要学git" 写入 remendme.txt 文件
echo "我要学git" > remendme.txt
运行结果如下:
接下来查看当前项目文件中文件的状态,继续在 Git Bash Here 输入如下命令:
python
git status
运行结果如下(显示当前有一个文件未被跟踪):
结果中提示可以通过 git add 命令去跟踪文件:
python
git add remendme.txt
运行结果如下:
再次查看当前项目文件中文件的状态,运行结果如下:
注意:其实将文件添加为跟踪状态,就是将其放入缓存区,从而git就可以跟工作区、本地仓库做比对。
由于刚刚指定了 git 对 remendme.txt 文件进行跟踪,所以缓存区发生了变化,缓存区若发生变化就需要提交,接下来对缓存区进行提交:
python
# -m 表示添加备注
git commit -m "对remendme.txt文件进行跟踪"
运行结果如下:
再次查看当前文件的状态,运行结果如下:
当用 git status 查看当前目录中文件的状态时,如果反馈说 clean 就表示当前处于已提交状态。
6、Git修改文件
修改文件:
python# 和linux的操作方法一摸一样 vim 要修改的文件
查看提交记录:
python# --oneline为可选参数,表示只出现提交的简短信息,不会展示是谁提交的 git log (--oneline)
注意:文件修改后需跟踪文件并提交。
实操:首先进入前面创建的 D:\git\sourceFile\project01 目录中,打开 Git Bash Here 对remendme.txt文件进行修改。
vim remendme.txt
进入文件后首先按 i 键切换到插入模式,然后输入你要添加的内容,添加完内容后,首先按 ESC 键退出插入模式,然后按 :wq 回车即可退出文件(一定要在英文状态下输入)。
接下来查看文件状态:
git status
运行结果如下:
根据结果可知文件发生了变更,要求对remendme.txt文件进行跟踪并提交,下面对该文件进行跟踪并提交,然后再查看文件状态:
python
# 对当前目录的文件进行跟踪
git add .
# 将跟踪的文件提交到暂存区文件,并给予注释信息
git commit -m 'updata remendme.txt'
# 查看文件状态
git status
# 查看所有的提交记录
git log
运行结果如下:
7、Git删除文件
删除工作区文件:
python# 也可以通过手动直接删除指定的文件 rm 文件
实操:首先我们创建一个新的文件,然后删除该文件。
既然要新建文件,就是对工作区的文件做了修改,因此要将当前目录修改的文件添加到缓存区并提交到本地仓库:
python
# 将指定内容写入文件,如果该文件不存在会自动创建
echo '新的测试文件' > myTest1.txt
# 添加到缓存区并提交到本地仓库
git add .
git commit -m 'add myTest1.txt'
# 查看文件状态
git status
运行结果如下:
接下来通过命令删除新建的文件:
python
# 删除刚刚创建的文件
rm myTest1.txt
# 查看状态
git status
运行结果如下:
从上面的结果可知,删除文件后也需要添加到缓存区并提交到本地仓库:
python
# 添加到缓存区
git add .
# 提交到本地仓库
git commit -m 'rm myTest1.txt'
# 查看文件状态
git status
运行结果如下:
知识点补充:使用 git rm 文件名不仅从工作区删除文件并且缓存区的也被删除,使用该命令对文件进行删除后只需将修改提交到本地仓库即可。
下面尝试用 git rm 文件名 来删除文件,创建文件的过程不再演示:
python
# 创建文件
echo '111' > myTest2.txt
# 添加到缓存区
git add .
# 提交到本地仓库
git commit -m 'add myTest2.txt'
# 查看当前目录的文件状态
git status
# 利用 git rm 删除文件
git rm myTest2.txt
# 查看当前文件的状态
git status
# 提交到本地仓库
git commit -m 'rm myTest.txt'
# 查看当前文件状态
git status
参考图片如下:
8、Git撤销本地修改
概述:实现Git撤销本地修改的原理就是从暂存区拿到之前提交的指定文件的信息覆盖工作区对应文件的内容。
将文件从暂存区复制到工作目录:
python# 方法一 git restore 文件名 # 方法二 git checkout -- 文件名
提示1:checkout的功能很多,从 Git 2.23 版本开始引入了两个新的命令:git switch 用来切换分支,git restore 用来还原工作区的文件。
提示2:从暂存区恢复工作区数据的前提是暂存区有对应数据(如果都没提交过某个文件,就想对该文件进行撤销操作是无法实现的)。
实操:首先对 remendme.txt 文件进行修改:
python
# 手动对文件内容进行修改或通过vim命令对文件内容进行修改
# 查看当前文件状态
git status
修改后的文件内容:
注意:不要将工作区的文件提交到暂存区或本地仓库,否则无法撤销本地修改。
根据上面的运行结果可知,可以通过 git restore 命令撤销本地操作:
python
# 撤销本地修改方法1
git restore remendme.txt
# 撤销本地修改方法2
git checkout -- remendme.txt
# 查看文本内容方法1(推荐)
cat remendme.txt
# 查看文本内容方法2(不推荐)
vim remendme.txt
参考图片如下:
9、Git取消暂存
概述:与上一章节类似,原理就是从本地仓库获取之前提交的指定文件的信息到暂存区覆盖提交的对应文件的信息,覆盖完成后暂存区的数据就和之前的文件信息一样了,但是恢复了暂存区的数据后,并不会影响工作区内容的变更。
恢复暂存区:
python# 方法1(重点是添加staged参数,否则会恢复工作区的文件操作) git restore -- staged 文件名 # 方法2 git reset -- 文件名
实操:首先对已有文件 remendme.txt 进行修改,然后将修改的文件提交
python
# 修改文件内容
echo 'niubi' >> remendme.txt
# 查看修改后的文件内容
cat remendme.txt
# 将修改后的文件添加到暂存区
git add .
# 查看当前路径的文件状态
git status
# 将暂存区里 remendme.txt 文件恢复到上一个版本
# 或使用 git reset -- remendme.txt
git restore --staged remendme.txt
# 将工作区里的 remendme.txt 文件恢复到上一个版本
git restore remendme.txt
# 查看当前 remendme.txt 文件的内容
cat remendme.txt
参考图片如下:
10、Git跳过暂存区
概述:本章节说的跳过暂存区并不是真的跳过暂存区,而是通过 git commit -a自动将跟踪过的文件放入 暂存区并一起提交,从观感上给人一种跳过了暂存区的假象。
提示:使用 -a 跳过 git add 步骤的前提是这些待提交的数据,是已跟踪过的。-a不会自动将未跟踪文件变为已跟踪。
语法:
python# 下面的括号表示可选项 # Git 自动把所有已经跟踪过的文件暂存起来一并提交 git commit (-a | 如果是单个文件直接写文件名即可) (-m "注释信息") # 使用最后一次提交,覆盖暂存区跟工作区(恢复工作区和暂存区的状态) git checkout HEAD --文件名
实操:首先对remendme.txt文件进行修改,然后用一条命令实现将数据添加到暂存区并提交到本地仓库。
python
# 追加文件内容
echo "人生苦短,就学python" >> remendme.txt
# 将修改的文件内容添加到暂存区并提交到本地仓库
git commit -am 'update remendme.txt'
# 查看当前目录的文件状态
git status
参考截图如下:
接下来尝试覆盖文件内容,然后将文件内容恢复到上次提交的状态:
python
# 更改文件内容
echo "我要打上海Major" > remendme.txt
# 将当前目录中所有文件恢复到上次提交的状态(如果只想恢复单个文件将.替换为文件名即可)
# git checkout HEAD remendme.txt
git checkout HEAD .
# 查看文件内容
cat remendme.txt
# 查看当前目录文件的状态
git status
运行结果如下:
11、版本回退
11.1、版本回退方法一
语法:
pythongit reset 指定的回退版本
指定回退版本的方法:
①、通过ID指定版本:通过 git log 获取所有的提交信息,commit后跟的就是ID,取前四位就可以定位到指定的版本;
②、通过HEAD指定版本:
- HEAD 表示当前版本
- HEAD^ 上一个版本
- HEAD^^ 上上一个版本
- HEAD^^^ 上上上一个版本
- 以此类推...
③、通过使用 ~数字 指定版本:
- HEAD~0 表示当前版本
- HEAD~1 上一个版本
- HEAD~2 上上一个版本
- 以此类推...
实操:实现版本回退。
首先查看提交过的版本(按 q退出日志):
python
git log
运行结果如下:
尝试将版本回退到 提交修改 的那个版本:
python
# 查看当前文件的内容
cat remendme.txt
# 回退到指定版本(实操时要将ID换位自己对应版本的ID)
# git reset HEAD^^^ 效果一样
# git reset HEAD~3 效果一样
git reset b0c1
# 工作区回退到暂存区中最新的版本
# git reset . 效果一样
git restore .
# 查看当前文件的内容
cat remendme.txt
运行结果如下:
当然也可以再次查看版本信息,看当前是否在指定的版本:
python
git log
运行结果如下:
11.2、版本回退方法二
概述:在上一小节中通过 git reset 指定版本 实现了暂存区回退到指定版本,然后通过 git restore 实现了工作区回退到暂存区的版本,本小节将通过一条语句实现将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交。
语法:
pythongit reset --hard 指定的版本(和上一小节的用法基本一样)
实操:通过一条语句实现版本回退到前两个版本,首先查看当前的版本信息:
python
git log
运行结果如下:
接下来切换到前两个版本:
python
# 切换到前两个版本
git reset --hard HEAD^^
# 查看当前目录状态
git status
运行结果如下:
12、Git撤销提交
概述:例如现在某文件有版本1和版本2,在版本2中我们做了一些开创性的尝试,但程序依然存在问题,如果直接采用版本回退这些含有价值的代码就不会被保存,此时就有了既要保存错误文件,又要当前版本没有错误的需求,这时候就可以使用 git revert HEAD 实现既保留存在错误的版本2,又提交了版本3(其实就是对原有的版本1再提交一次)。
语法:
python# 保留当前版本并回退到上一版本 git revert HEAD # 与上一个命令差别就在于运行命令后不会进入编辑界面,即不会自动提交,需要手动提交。 # 说人话就是保留了现有版本,并且工作区已经回退到了上一版本,但需要手动提交 git revert -n HEAD
实操:首先对remendme.txt文件进行内容追加,然后在保留版本记录的基础上撤销本地的内容提交(说白了就是保留提交的版本,但文件内容是上次提交的内容)。
对remendme.txt文件进行内容追加并提交版本:
python
# 查看文件内容
cat remendme.txt
# 对文件做内容追加
echo '追加的内容' >> remendme.txt
# 提交版本
git commit -am "对remendme.txt文件的内容做了追加"
# 查看追加后的文件内容
cat remendme.txt
参考截图如下:
接下来保留现有版本并回到上一个版本:
python
git revert HEAD
运行完上述命令后会进入如下界面:
首先按 i 键切换到插入模式,然后直接输入任意一个名字,输入完成后按 ESC键退出插入模式,然后输入 :wq 即可,参考下图:
再次查看文件内容:
python
cat remendme.txt
运行截图如下:
查看版本记录:
python
git log
运行结果如下:
13、Git设置忽略文件
概述:一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。
格式规范:
- 所有空行或者以注释符号 # 开头的行都会被 Git 忽略
- 可以使用标准的 glob 模式匹配
- 匹配模式最后跟斜杠(/)说明要忽略的是目录
- 要忽略指定模式以外的文件或目录,可以在模式前加上感叹号(!)进行取反
glob模式:所谓的 glob 模式是指 shell 所使用的简化了的正则表达式,匹配规则如下:
"*"
:星号匹配零个或多个任意字符。[]
:匹配任何一个列在方括号中的字符,如[ab]匹配a或者匹配b。"?"
:问号匹配一个任意字符。[n-m]
:匹配所有在这两个字符范围内的字符,如[0-9]表示匹配所有0到9的数字。示例:logs/:忽略当前路径下的logs目录或多级路径下的logs目录,包含logs下的所有子目录和文件。 /logs.txt:忽略根目录下的logs.txt文件。*.class:忽略所有后缀为.class的文件。 !/classes/a.class:不忽略classes目录下的a.class文件。 tmp/*.txt:只忽略tmp目录下的.txt文件。 **/foo:可以忽略/foo, a/foo, a/b/foo等。
实操:首先在当前目录创建一个名为a的文件夹,然后在该文件夹中创建一个名为b的文件夹和一个名为c.txt的文件:
然后进入project01文件夹中创建一个名为**.gitignore**的文件:
查看当前目录中所有文件的状态:
python
git status
运行结果如下:
通过运行结果可知git要求我们去对a文件夹和.gitignore文件进行跟踪,但我们不想让git对a文件夹的内容进行跟踪,此时就可以在ignore文件中写入a的路径:
再次查看当前目录的文件状态:
此时就成功忽略了a文件夹!
14、Git比较文件差异
对比工作区跟暂存区的变化,显示未暂存的改动:
pythongit diff
对比本地仓库最新版本跟暂存区的变化,显示未提交的改动:
pythongit diff --cached|--staged
对比本地仓库中不同版本之间的差异:
python# 可以用HEAD做定位,也可以用ID前四位做定位 git diff 定位的版本1 定位的版本2
实操:首先对remendme.txt文件进行修改,然后查看工作区与暂存区的区别:
python
# 对文件进行编辑
vim remendme.txt
# 查看工作区与暂存区的区别
git diff
运行结果如下:
提示:上图中 +号 后面的内容就表示增加的内容,同理,- 号后面的内容代表删除的内容。
接下来对工作区的修改的内容提交到暂存区,然后再查看工作区和暂存区未提交内容的差异以及暂存区与本地仓库之间未提交内容的差异:
python
# 将工作区修改的内容提交到暂存区
git add remendme.txt
# 查看工作区与暂存区之间未提交内容的差异
git diff
# 查看暂存区与本地仓库之间未提交内容的差异
git diff --staged
运行结果如下:
接下来将暂存区的版本提交到本地仓库并查看暂存区与本地仓库之间是否还存在差异:
python
# 将暂存区中remendme.txt的最新版本提交到本地仓库
git commit remendme.txt -m '为remend.txt文件添加了内容:123'
# 查看暂存区与本地仓库之间是否还有未提交版本的差异
git diff --cached
运行结果如下:
最后比较以下当前版本与前一版本的差异:
python
# 下面命令的意思是与当前版本相比,前一版本有什么不同
# 注意:这里除了能用HEAD定位版本,也能用ID前四位去做定位
git diff HEAD HEAD^
运行结果如下:
15、Git代码托管平台
远程仓库:目前我们使用到的 Git 命令都是在本地执行,如果你想通过 Git 分享你的代码或者与其他开发人员合作, 你就需要将数据放到一台其他开发人员能够连接的服务器上,托管在这台服务器上的数据的就是我们的远程仓库。
注意:在使用远程仓库之前,我们首先需要创建仓库,创建仓库有很多种,这里常见的有如下几种:
自己搭建个 Git 服务器,安装如 GitLab 的Git版本管理系统
使用第三方托管平台,如国内的 和国外的
常用的托管服务平台:
GitHub (地址: GitHub: Let's build from here · GitHub)是一个面向开源及私有软件项目的托管平台,因为只支持Git作 为唯的版本库格式进行托管,故名GitHub。
码云(地址: Gitee - 基于 Git 的代码托管和研发协作平台)是国内的一个代码托管平台,由于服务器在国内,所以相比于 GitHub,码云速度会更快。
GitLab (地址: The most-comprehensive AI-powered DevSecOps platform | GitLab) 是一个用于仓库管理系统的开源项目,使用Git作为代 码管理工具,并在此基础上搭建起来的web服务。
以上提到的代码托管平台,都基于git技术来实现。
实操:首先在码云平台新建仓库(需要提前注册账号)。
登录码云后会进入首页,然后根据下图引导进行操作:
上面已经完成了仓库的创建以及readme文件的初始化,下面为仓库添加成员:
16、本地添加远程仓库
流程:
①、添加远程仓库;
②、初始化本地仓库:
git init
③、为本地添加远程仓库:
python# 后面将把 自定义的本地仓库与远程仓库的关联名 简称为 仓库关联名 git remote add 自定义一个本地仓库与远程仓库的关联名 远程仓库的地址
查看远程仓库:
git remote
删除远程仓库:(这里所说的删除是删除本地仓库与远程仓库的关联,而不是删除码云等代码托管平台的仓库)
pythongit remote rm 仓库关联名
获取远程仓库的代码:
python# 远程主机名就是仓库关联名 git pull 远程主机名 远程分机名
推送本地仓库代码到远程仓库:
python# 远程主机名 == 仓库关联名 == 添加远程仓库时本地仓库与远程仓库的关联名 git push 远程主机名 本地分支名 : 远程分支名 # 如果本地分支名与远程分支名相同可按如下格式书写 git push 远程主机名 本地分支名
实操:为本地添加远程仓库:
首先进入前面创建的project01文件夹打开 Git Bash Here:
然后前往gitee获取远程仓库的地址:
接下来为本地添加远程仓库,并为远程仓库取名为myFirstTest:
python
# 为本地添加远程仓库
git remote add myFirstTest 'https://gitee.com/muxishiye/project1'
# 查看当前本地仓库拥有哪些远程仓库
git remote
运行结果如下:
下面我再为当前的本地仓库添加一个相同的远程仓库,然后删除后添加的远程仓库:
python
# 再次为本地仓库添加一个远程仓库
git remote add mySecondTest https://gitee.com/muxishiye/
# 查看当前仓库有哪些关联的远程仓库
git remote
# 删除刚刚新关联的远程仓库
git remote rm mySecondTest
# 查看当前仓库有哪些关联的远程仓库
git remote
运行结果如下:
下面简要提一下怎么看本地分支名和远程分支名:
以下时本地分支名(Git Bash Here 中查看):后面小括号中的内容就是本地分支名
以下是远程仓库的分支名(在代码管理平台查看):分支左侧展示的就是分支名,当前只有一个名为master的分支名
下面拉取远程仓库中master分支的文件到本地仓库:
python
git pull myFirstTest master
运行结果如下:
最后尝试将本地仓库的文件推送到远程仓库:
python
git push myFirstTest master
运行结果如下:
报错的原因就是 在本地仓库上的修改没有基于远程库最新版本,你的本地仓库版本落后于远程仓库(起初我们在本地仓库的练习从未与远程仓库同步过),我们可以使用参数实现强制推送(但要100%确定以及肯定你的代码是没有问题的):
python
git push myFirstTest master --force
运行结果如下:
17、Git的克隆与推送
克隆:
git clone 远程仓库地址
推送本地仓库到远程仓库:
python# 如果只有一个远程仓库,push后的内容可以省略 git push (本地仓库与远程仓库的关联名 本地分支名:远程分支名)
实操:假定当前公司给我们发了一台新设备,现需要将之前远程仓库的代码克隆到新电脑的如下路径 D:\git\sourceFile\project02。
首先进入该路径,然后鼠标右键打开 Git Bash Here:
python
# 克隆远程仓库的文件
git clone 替换成自己远程仓库的地址
# 进入克隆的文件夹
cd ./project1
# 查看当前文件夹的远程仓库
git remote
运行结果如下:
克隆完文件后,我们对文件内容做任意修改再推送到远程仓库:
python
# 查看当前myTest2.txt文件的内容
cat myTest2.txt
# 对myTest2.txt追加内容
echo '222' >> myTest2.txt
# 查看追加内容后的myTest2.txt文件
cat myTest2.txt
# 将修改提交到本地仓库
git commit -am '为myTest2.txt文件追加了内容'
# 将本地仓库的内容提交到远程仓库
git push
运行结果如下:
18、Git拉取
在前面的学习中,通过如下语句拉取远程仓库的代码:
git pull 远程主机名 远程分机名
为了简化操作,可以提前设置跟踪信息,然后用简化命令直接拉取即可:
python# 设置跟踪信息 (关联名通过 .git 目录下的 config 文件查看) git branch --set-upstream-to=本地仓库与远程仓库的关联名/本地仓库的分支名 远程仓库的分支名 # 拉取跟踪的远程仓库文件 git pull
实操:在 D:\git\sourceFile 目录下创建两个新的文件夹(project03和project04)用于模拟两个开发者对同一远程仓库的文件进行修改:
首先为 project03 和 project04 拉取远程仓库的文件:
python
# 克隆远程仓库的文件
git clone https://gitee.com/muxishiye/project1
# 进入project04目录
cd ../project04
# 克隆远程仓库的文件
git clone https://gitee.com/muxishiye/project1
运行结果如下:
首先对project04文件夹中拉取的文件进行修改,然后将修改后的项目同步到远程仓库:
python
# 进入克隆的文件夹
cd project1/
# 通过重定向新建文件
echo 'project04修改了项目' > mylog.txt
# 跟踪该文件夹中所有的文件
git add .
# 提交当前目录中所有文件到本地仓库
git commit -m '新增日志文件'
# 将当前的远程仓库内容同步到远程仓库
git push
参考代码如下:
下面对project03文件夹中的内容做同步,如果直接用git pull是能直接拉取的,但为了演示如何设置跟踪信息我们需要对 D:\git\sourceFile\project04\project1\.git\config文件进行修改:
将选中的行删除并保存:
然后进入project03目录下的project文件夹中运行如下命令:
python
# 正常运行该命令就能直接获取到远程仓库的命令,如果无法拉取也会有操作提示
git pull
# 设置跟踪信息
git branch --set-upstream-to=origin/master master
# 再次拉取远程仓库的内容
git pull
参考截图如下:
19、Git抓取
将远程仓库的数据拉取到本地,但不会自动合并:
pythongit fetch
手动合并命令:
pythongit merge 本地仓库与远程仓库的关联名/本地仓库的分支名
实操:首先在project03目录下的project1文件夹对mylog.txt文件进行修改。
python
# 对原有文件进行内容的追加
echo '123321' >> mylog.txt
# 将修改提交到本地仓库
git commit -am 'update mylog.txt'
# 将本地仓库的修改同步到远程仓库
git push
参考截图如下:
接下来让project抓取远程仓库的文件:
python
# 进入project04拉取的文件中
cd ../../project04/project1/
# 拉取远程仓库的文件
git fetch
# 查看文件内容
cat mylog.txt
参考截图如下:
从结果可知,project04中的mylog.txt文件仍处于之前的文件内容,接下来手动合并远程仓库拉取的文件与本地文件:
python
# 手动合并
git merge origin/master
# 再次查看文件内容
cat mylog.txt
运行结果如下:
20、Git合并冲突
解决合并冲突的方法:在第二个目录下先拉取远程仓库的数据,如果有冲突,则会提示。打开指定的冲突文件,手动对文件内容进行修改,重新提交文件并推送到远程仓库即可。
实操:本实操将演示project03和project04两个用户同时对myTest02文件进行修改,但两个用户写的是针对不同功能的代码,最后将保留两个用户所有的代码的情况:
首先是project04的用户修改文件:
python
# 对文件内容进行追加
echo 'project04用户新增的内容' >> myTest2.txt
# 将修改文件提交到本地仓库
git commit -am 'update by project04'
# 将本地仓库提交到远程仓库
git push
运行结果如下:
接下来修改project03文件夹中的myTest2.txt文件:
python
# 进入project03所在的目录
cd ../../project03/project1/
# 对文件内容进行修改
echo 'project03用户新增的内容' >> myTest.txt
# 提交工作区的修改到本地仓库
git commit -am 'update by project03'
# 将本地仓库的内容提交到远程仓库(由于版本存在冲突所以会报错)
git push
# 从远程仓库拉取项目
git pull
参考截图如下:
由于 project03 和 project04 的用户提前就商量过两人开发不同的功能代码,所以提交时需要同时保留两人提交过的代码:
打开修改的myTest2.txt文件,内容如下:
修改后的文件内容如下,保存退出即可:
修改完内容后,将修改提交到本地仓库后,再将本地仓库同步到远程仓库即可:
python
# 将工作区文件提交到本地仓库
git commit -am 'update by project03'
# 将本地仓库同步到远程仓库
git push
参考截图如下:
温馨提示:我们要养成推送之前,先拉取代码的习惯,防止覆盖同事的代码。
21、GitHub创建远程仓库
①、首先进入GitHub官网:GitHub
②、登录GitHub,然后按下图步骤进行操作:
创建完成后得到如下信息:
接下里进入任意目录创建一个文件夹来克隆GitHub上的远程项目:
python
# 创建文件夹
mkdir project06
# 进入该文件夹
cd project06
# 克隆远程仓库的文件
git clone https://github.com/muxishiye/project2.git
# 进入克隆的目录
cd project2/
# 创建一个文件
echo '操作前须知' > readme.txt
# 对工作区的文件进行追踪
git add .
# 提交暂存区的文件到本地仓库
git commit -m 'add file'
# 提交本地仓库的文件到远程仓库
git push
参考代码如下:
运行完以上命令后会弹出如下登录框:
登录后就成功的将本地仓库的文件推送到了远程仓库:
远程仓库刷新后如下:
22、Git使用SSH协议
概述:之前本地仓库跟远程仓库数据的传递使用的是https协议,需要用户名跟密码进行身份验证。我们还可以使用SSH协议,配置一次,以后每次再传递数据就不需要再使用用户名跟密码进行认证了。
SSH协议:SSH 是 Secure Shell (安全外壳协议)的缩写,由 IETF 的网络小组(Network Working Group)所制定。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
生成一对私钥和公钥:(在命令提示符中运行如下命令)
python# 输入完命令后按三次回车 ssh-keygen -t rsa
实操1:利用 SSH 链接本地仓库与 Gitee 远程仓库。
①、首先在命令提示符中输入如下命令生成公钥和私钥:
python
ssh-keygen -t rsa
运行结果如下:
②、进入上图的默认目录查看 id_rsa.pud 文件内容并复制。
③、然后进入Gitee官网按下图所示步骤进行操作:
④、接下来尝试利用ssh来克隆远程仓库:
python
# 创建目录project07
mkdir project07
# 进入目录
cd project07
# 利用ssh克隆远程仓库
git clone git@gitee.com:muxishiye/project1.git
参考截图如下:
实操2:利用 SSH 链接本地仓库与 GitHub 远程仓库。
①、首先点击右上角的头像 > 点击Settings :
②、点击添加SSH钥匙:
③、获取仓库的ssh链接:
④、创建一个新文件夹,通过ssh克隆远程仓库的文件:
python
# 创建新目录
mkdir project08
# 进入创建的目录
cd project08
# 通过ssh克隆远程仓库的文件
git clone 远程仓库ssh的链接
运行结果如下:
23、初识Git分支
概述:Git 中的分支,其实本质上就是一个指向 commit 对象的可变指针。Git 会使用 master 作为默认分支。
下图是默认情况下的分支:(分支在每次提交的时候都会自动向前移动。在进行了若干次提交后,你其实已经有了一个指向最后一次提交对象的分支。)
基于当前分支创建一个新分支:这会在当前分支指向的commit 对象上新建一个新的分支指针
pythongit branch 新的分支名
提示: Git 中的分支实际上仅是一个包含所指对象校验和(40 个字符长度 SHA-1 字串)的文件。
24、Head与分支
概述:在 Git 中,有一个指向你正在工作中的本地分支的指针,叫做Head。如果我们只有一个默认的master分支,则HEAD指向master分支。如果有多个分支,切换工作分支,HEAD指针的指向也会更改。
切换分支:
pythongit checkout 分支名
下图演示如果切换到新的分支上并提交内容后的情况:(每次提交后 HEAD 随着分支一起向前移动)
切换回原来的master分支后的情况:
注意:切换分支后,除了HEAD指针发生移动之外,工作目录中的文件也会换成当前分支所指向的commit版本
25、分支分类及其应用
常见的分支:
- 生产分支:专门用来上线,这里的代码必须是经过测试的稳定版。(一般为master分支)
- 开发分支:生产分支的平行分支,专门用于后续的开发,或仅用于稳定性测试,一旦进入某种稳定状态,便可以把它合并到 master 里。(一般为develop分支)
- 功能分支:从develop分支创建,开发人员在这个分支上完成功能模块代码,提测的时候合并到develop分支。(名称一般由这次的开发功能自定义)
实战模拟:你正在分支a上做功能开发,突然接到一个紧急问题的修补需求,面临的问题是当前的功能代码不能提交到线上,所以不能在当前分支进行bug修复。
解决思路:
- 切换到已经发布到生产服务器上的分支
- 为当前分支建立一个新分支,并在其中修复问题
- 通过测试后,回到生产服务器所在的分支,将修补分支合并进来,然后再推送到生产服务器上
- 切换回分支a继续做功能开发
26、分支的管理
新建分支名:
pythongit branch 新的分支名
查看本地所有分支:
pythongit branch
查看各个分支最后一个提交对象的信息:
pythongit branch -v
切换分支:
pythongit checkout 切换的分支名
新建并切换分支:
pythongit checkout -b 分支名
切换分支:
pythongit branch -d 分支名
实操:新建一个名为project09的文件夹实操以上命令。
首先创建一个新的文件夹初始化git后建立一个新的分支:
python
# 创建一个新的目录
mkdir project09
# 进入新建的目录
cd project09
# 初始化git
git init
# 尝试新建一个分支
git branch a
参考截图如下:
报错原因是初始化git后没有做任何的提交,导致还没有名为master的分支,解决该问题可以先提交任意文件到本地仓库后,再基于master分支新建分支:
python
# 运用重定向新建文件
echo '用前须知' > readme.txt
# 跟踪文件
git add .
# 提交暂存区文件到本地仓库
git commit -m 'add readme.txt by user1'
# 基于当前的master分支新建一个名为a的分支
git branch a
# 查看当前仓库所有的分支(结果中前面有*号的就是当前使用的分支)
git branch
运行结果如下:
接下来切换到分支a并对文件做修改,提交修改后查看所有分支最后提交的记录:
python
# 切换到分支a
git branch a
# 修改文件并提交
echo '我读完了该文件' >> readme.txt
git commit -am 'update readme.txt by a'
# 查看当前仓库所有分支组后提交的记录
git branch -v
运行结果如下:
最后我们基于分支a新建一个名为b的分支,创建完b分支后立即切换到该分支:
突然发现b分支没有什么存在的意义,接下来删除b分支:
python
# 当前在b分支,尝试直接删除b分支
git branch -d b
# 切换到除b分支以外的分支
git checkout a
# 再次删除b分支
git branch -d b
运行结果如下:
结论:当需要删除某一个分支时,一定要切换到除该分支以外的分支,否则会报错。
27、合并分支
合并分支的流程:
①、创建并切换到新分支:
pythongit checkout -b 新的分支名
②、在新分支提交内容:
pythongit commit -m '注释信息'
③、将新分支的提交合并到原来的分支:
python# 先切换到被合并的分支 git checkout 被合并的分支名 # 对分支做合并 git merge 被合并的分支名
④、删除没用的分支:
pythongit branch -d 没用的分支名
实操:实现分支合并。
在上一节的实操中,我们基于master分支新建了a分支,并在a分支上修改了readme.txt文件,现尝试将master分支与a分支进行合并,合并完成后将a分支删除。
python
# 切换到被合并的分支
git checkout master
# 将master分支与a分支进行合并
git merge a
# 删除a分支
git branch -d a
# 查看当前仓库有哪些分支
git branch
# 查看当前分支的readme.txt文件的内容是否发生变化
cat readme.txt
参考如下文件:
28、合并分支冲突
概述:有时候合并操作并不会如此顺利。如果在不同的分支中都修改了同一个文件的同一部分,Git 就无法准确地把两者合到一起。
实操:首先基于master分支创建两个分支,分别为a和b,接下来在两个分支中都对readme.txt文件做修改(a做覆盖操作,b做追加操作),将a,b分支合并到master分支时就会产生分支冲突:
python
# 查看master分支下readme.txt文件的内容
cat readme.txt
# 基于master分支创建并直接切换到分支a
git checkout -b a
# 对文件做覆盖操作并提交到本地仓库
echo 'a分支对文件做了覆盖操作' > readme.txt
git commit -am 'update readmel.txt by a'
# 切换到master分支,再基于master分支创建一个名为b的分支
git checkout master
git checkout -b b
# 对b分支的readme.txt文件做追加操作
echo 'b分支对文件做了追加操作' >> readme.txt
# 提交工作区的文件到本地仓库
git commit -am 'update readme.txt by b'
参考截图如下:
上面已经基于master分支创建了分支a和分支b,并对readme.txt文件做了不同的修改,接下来尝试合并分支a与分支b到master分支:
python
# 切换到master分支
git checkout master
# 将分支a合并到master分支
git merge a
# 将分支b合并到master分支
git merge b
运行结果如下:
打开文件,readme.txt文件内容如下:
此时要解决分支冲突的办法就是提前沟通,看两次修改是否都保存或保存某一部分,然后直接对文件内容进行修改,修改完成后将文件提交到暂存区,然后同步到本地仓库即可:(下面演示分支a和分支b的内容都保存的情况)
readme.txt文件修改后的内容如下:
修改完文件并保存后运行如下命令:
python
# 将存在冲突的文件修改后进行追踪(提交到暂存区)
git add .
# 将暂存区的文件提交到本地仓库
git commit -m '解决了分支冲突问题'
# 查看readme.txt文件的内容
cat readme.txt
运行结果如下:
29、Git储藏
概述:有的时候我们需要从当前正在工作的这个分支,切换到其它分支去解决问题,要切换到其它分支,我们可以先将当前的工作分支的本地修改进行提交,如果说你不想提交,你的代码并没有写完,这个时候我们还可以把当前分支的本地修改暂时储藏起来,让它的工作区保持干净,这样就可以切换到别的分支了。将来我们还可以把储藏起来的更改进行恢复,从而继续之前的工作。
储藏当前的修改:
pythongit stash
取出之前储藏的修改:
pythongit stash apply
实操:尝试对上一章节中a分支的readme.txt文件进行修改,不提交就直接切换分支:
python
# 切换到分支a
git checkout a
# 查看当前readme.txt文件的内容
cat readme.txt
# 对文件内容做追加
echo '暂时不提交的内容' >> readme.txt
# 尝试在修改没有提交的前提下切换分支
git checkout master
运行结果如下:
根据提示可知,要么我们对修改的内容进行提交后再切换分支,要么就通过 git stash 命令对修改进行储藏后再切换分支。
在前面的学习中都是修改完文件后将修改提交到本地仓库后再切换分支,下面演示将修改储藏后切换分支的操作:
python
# 对a分支的修改进行储藏
git stash
# 尝试切换到master分支
git checkout master
# 查看master分支里readme.txt文件的内容
cat readme.txt
# 再次切换到a分支
git checkout a
# 查看当前a分支readme.txt文件的内容
cat readme.txt
# 恢复之前储藏的修改
git stash apply
# 再次查看readme.txt文件
cat readme.txt
运行结果如下:
30、远程分支与本地分支的区别
远程分支:是远程仓库中的分支的索引,它们实质上是无法移动的本地分支,远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。常用 远程仓库与本地仓库关联的名称 / 远程仓库的分支名 这样的形式表示远程分支。
注意:在本地我们只能移动本地master分支,不能移动远程分支origin/master。
下图演示从远程仓库克隆项目到本地:
在本地master分支修改内容,提交后,本地master分支移动,origin/master分支保持不变:
只有跟服务器通信,远程分支origin/master分支才会移动,比如其他人往远程仓库推送了代码,则远程仓库中,master分支向前移动,我们可以通过 git fetch 获取远程仓库库的最新数据:
如果需要将远程分支的变更合并到本地master分支可通过如下命令实现:
pythongit merge orgin/master
31、创建远程仓库的分支
概述:创建远程仓库的方式分为从本地仓库向远程仓库推送分支和在远程仓库直接新建新分支两种方式。
31.1、通过本地向远程仓库推送分支创建
流程介绍:
①、在本地创建分支a;
②、推送本地分支到远程仓库:
python# 远程分支名跟本地分支名相同时可采用简写(省略:远程分支名) git push 本地仓库与远程仓库的关联名 本地分支名:远程分支名
③、协作的同事可以通过如下命令获取远程仓库的分支:
pythongit fetch
④、通过远程分支创建本地分支:
pythongit checkout -b 本地分支 远程分支 # 参考命令如下 git checkout -b feature_user origin/a
注意:
- 通过 git checkout -b 本地分支名 远程分支名 创建的本地分支会自动跟踪远程分支;
- 可以先在本地新建名为 abc 的分支 ,然后用 git fetch 获取最新数据,再通过 git merge origin/abc 手动合并到本地分支,但需要手动跟踪远程分支。
- 设置跟踪分支:
pythongit branch --set-upstream-to=origin/master master
实操:在 D:\git\sourceFile 目录创建一个名为 project10 的文件夹,然后通过命令创建a,b两个目录,a目录用于创建和推送分支,b目录用于使用远程仓库的分支:
首先创建project10目录,并通过命令创建a,b两个目录,创建完成后a,b两个目录都对远程仓库的文件进行克隆:
python
# 进入创建的project10目录
cd project10/
# 在当前目录创建a,b两个目录
mkdir a
mkdir b
# 进入a目录并克隆远程仓库的项目
cd a
git clone 替换成自己远程仓库ssh的链接
# 进入b目录并克隆远程仓库的项目
cd ../b
git clone 替换成自己远程仓库ssh的链接
运行结果如下:
接下来进入a目录中拉取的文件夹中创建一个新分支,并推送到远程仓库:
python
# 远程仓库的名字就叫project2,所以克隆后的文件夹就叫project2
cd project2/
# 创建分支
git branch branch_a
# 将本地分支推送到远程仓库
git push origin branch_a:branch_a # 由于本地仓库的分支名与远程仓库的分支名一致,所以可以简写为git push origin branch_a
运行结果如下:
刷新远程仓库后可以看到当前远程仓库中就新加了一个名为branch_a的分支:
接下来切换到b文件夹中拉取远程仓库的最新数据,再基于远程仓库创建一个本地的分支:
python
# 切换到b文件夹中拉取的项目目录中
cd ../../b/project2/
# 拉取远程仓库中最新的数据
git fetch
# 基于远程仓库的分支新建一个本地分支
git checkout -b branch_a origin/branch_a
运行结果如下:
以上就是通过获取远程仓库最新数据后,创建基于远程仓库指定分支的本地分支的操作流程。
下面将演示如何通过直接在本地创建分支,然后获取远程仓库的最新数据,最后对远程仓库的内容和本地仓库的内容做合并实现远程仓库分支的流程:
python
# 首先切换到其它分支
git checkout main
# 删除先前创建的分支
git branch -d branch_a
# 创建本地分支
git checkout branchs_a
# 拉取远程仓库中最新数据
git fetch
# 合并拉取的内容和本地仓库的内容
git merge origin/branch_a
# 尝试拉取远程仓库的信息
git pull
# 由于没有指定远程仓库的分支名,所以需要根据提示指定分支
git branch --set-upstream-to=origin/branch_a branchs_a
# 再次拉取远程仓库的数据
git pull
运行结果如下:
总结:通过对比两种方式的创建过程,当然是使用基于远程仓库的分支新建一个本地分支的方式更加简单,省去了自己手动合并并指定分支的操作。
31.2、直接在远程仓库添加分支
下面将以GitHub仓库为例,根据下图指示的步骤进行操作即可(Gitee平台的操作也大差不差):
32、删除远程分支
概述:当我们的某个分支已经合并到了master分支,并且之后也不会继续在该分支上进行开发使用,则可以从远程仓库把该分支删除掉。
删除方式:
①、通过命令删除远程分支:
pythongit push 本地仓库与远程仓库的关联名 --delete 分支名
注意:删除远程分支,会将本地远程分支这个指针跟服务器上面的对应分支删除掉,但本地分支不会被删除。
②、直接在远程仓库进行删除。
实操:尝试在工作区通过命令删除远程仓库的分支。
python
# 进入a目录拉取的项目目录中
cd ../../a/project2/
# 通过命令删除远程分支
git push origin --delete branch_a
# 查看本地分支
git branch
运行结果如下:
33、初识标签
概述:标签可以是一个对象(带注解标签),也可以是一个简单的指针(不带注解标签),用来标注某次提交对象。
如果只是一个简单的指针,则它就相当于一个不会移动的分支。
如果是一个对象,则除了保存指向的提交对象的信息之外,还会保存是谁打的标签,什么时间,还可以保存注解信息。(推荐使用)
使用标签的原因:我们可以为重要的版本(某个里程碑)打上标签,相当于为这次提交记录指定一个别名,方便提取文件。比如人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做。
标签与分支的区别:分支会跟着我们的提交移动,指向最新的提交对象,但是标签不会移动,它就是指向某个固定的提交对象。
34、管理标签
新建标签:
git tag -a 标签名 -m '标签说明信息'
语法补充:
-a 选项意为创建一个带注解的标签,如果不加 -a 则创建的是一个不带注解的标签,一个简单的引用;
-m 选项则指定了对应的标签说明。
注意:默认情况下,新建的标签指向最新的提交对象。
查看指定标签的版本信息,并连同显示打标签时的提交对象:
git show 标签名
追加标签:
python# 提交对象的ID可以通过 git log (--oneline) 查看 git tag -a 标签名 提交对象的Id -m '标签说明信息'
列出所有标签:
git tag
删除标签:
git tag -d 标签名
实操:练习本章节提到的命令。
首先新建一个文件夹并初始化git,然后创建任意文件并提交到本地仓库,提交完成后立即打标签,并查看当前有哪些标签:
python
# 创建新的目录project11
mkdir project11
# 进入创建的目录
cd project11
# 初始化git
git init
# 利用重定向新建文件
echo '读前须知' >> readme.txt
# 追踪新文件
git add .
# 提交修改到本地
git commit -m 'create new file -- readme.txt'
# 为当前提交的内容打标签
git tag -a v1.0 -m 'add file -- readme.txt'
# 查看当前仓库有哪些标签
git tag
运行结果如下:
接下来对readme.txt文件进行多次修改并提交:
python
# 第一次修改并提交
echo '123' >> readme.txt
git commit -am 'first update readme.txt'
# 第二次修改并提交
echo '456' >> readme.txt
git commit -am 'second update readme.txt'
运行结果如下:
修改完两次并提交后,我发现第一次修改还挺重要的,一定要给它打个标签,此时我们就需要查看提交记录,然后根据提交对象的ID去为第一次修改打标签:
python
# 查看简化日志
git log --oneline
# 为指定版本打标签
git tag -a v1.1 替换成自己要修改的提交对象ID -m 'version1.1'
# 查看所有的标签
git tag
运行结果如下:
最后发现v1.0并不是很重要,下面删除 v1.0 标签:
python
# 删除指定标签
git tag -d v1.0
# 获取所有的标签
git tag
运行结果如下:
35、标签的推送与检出
推送标签到远程仓库:
pythongit push 本地仓库与远程仓库的关联名 标签名
通过标签获取对应版本(检出):
pythongit checkout -b 本地分支名 标签名
提示:检出的前提是你本地已经有了远程的标签,如果没有,使用 git fetch 获取远程仓库最新数据,再执行检出。
实操:本实操将在34章节创建的project11文件夹中进行,首先为本地仓库添加远程仓库:
python
# 为本地仓库添加远程仓库
git remote add myGitHub 远程仓库的链接
# 查看远程链接是否创建成功
git remote
# 尝试将本地仓库同步到远程仓库
git push
# 指定远程仓库的分支进行推送
git push --set-upstream myGitHub master
运行结果如下:
接下来查看本地仓库的标签,并将标签推送到远程仓库:
python
# 查看本地的标签
git tag
# 推送本地标签v1.1到远程仓库
git push myGitHub v1.1
运行结果如下:
此时远程仓库就多了一个标签:
接下来尝试实现检出操作:首先退出到上一级目录并创建一个新目录,然后克隆有标签的远程仓库,然后做检出操作,查看ID是否一致:
python
# 创建新的目录
mkdir project12
# 进入创建的目录
cd project12
# 克隆远程仓库的项目
git clone 远程仓库链接
# 进入克隆得到的项目文件夹
cd 远程仓库项目名
# 查看当前所有的标签
git tag
# 做检出操作
git checkout -b branch_1.1 v1.1
# 查看所有分支最后一次提交的信息
git branch -v
# 查看指定标签的信息
git show v1.1
运行结果如下: