文章目录
- 一、 版本控制
- 1.1 集中式版本控制
- 1.2 分布式版本控制
- 二、 Git的安装及配置
- 2.1 安装
- 2.2 Git的配置
- 2.2 查看配置
- 三、 Git基本理论
- 3.1 工作区域
- 3.2 文件状态
- 四、Git项目的搭建与操作
- 4.1 初始化Git仓库
- 4.2 常见的操作
- 4.2.1 文件添加到暂存区
- 4.2.2 文件提交更新
- 4.2.3 查看历史提交记录
- 4.2.4 版本回退
- 2.5 .gitignore配置文件
- 五、远程仓库
- 5.1 身份认证
- 5.1.1 HTTP凭证
- 5.1.2 SSH密钥
- 5.2 管理远程仓库(添加)
- 5.3 与远程仓库的交互
- 5.4 pull与push可能会出现的错误
- 5.4.1 git pull时会出现的错误
- 5.4.2 git push时会出现的错误
- 5.5 项目开发可能的流程
- 5.6 常见的开源协议
- 六、 Git分支
- 6.1 校验和
- 6.2 Git的提交对象(commit object)及底层原理
- 6.3 Git创建tag标签
- 6.4 认识Git分支
- 6.5 Git分支的操作
- 6.5.1 开发项目(master分支上提交)
- 6.5.2 中途修复bug (创建并切换分支)
- 6.5.3 bug修复完,合并分支,继续后续的开发
- 七、 远程分支
- 7.1 远程分支的基本操作
- 7.2 举例
- (1) 新建项目
- (2) 新建dev分支进行开发
- (3) 一位新入职的员工需要在dev分支上进行开发
一、 版本控制
版本控制可以帮助程序员进行代码的追踪、维护、控制等一系列操作。
最权威的资料——Git官网:https://git-scm.com/doc
1.1 集中式版本控制
集中式版本控制(Centralized Version Control Systems, 简称CVCS )的特点:
- 采用一个集中管理的服务器,保存所有文件的修订版本
- 问题是:中央服务器不能出现故障
- 如果服务器宕机,那么谁都无法提交更新,也就无法协同工作。
- 如果中心数据库发生损坏,没有备份的话,将丢失关键数据
1.2 分布式版本控制
Git属于分布式版本控制系统 (Distributed Version Control System, 简称DVCS):
- 客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下
来,包括完整的历史记录; - 任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复;
(因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份)
二、 Git的安装及配置
2.1 安装
- git官网下载:https://git-scm.com/
- 淘宝镜像下载:http://npm.taobao.org/mirrors/git-for-windows
Git安装的几个工具
Git在安装时,也会安装如下几个工具,这几个工具的作用都是为了运行git命令。
-
Git Bash(推荐):就是一个shell,可执行Linux的命令行。GitBash是基于CMD的,在CMD的基础上增添一些新的命令;
-
Git CMD:命令行提示符(CMD)是Windows操作系统上的,Git CMD就是对其的进一步封装,就看做是Window上的CMD;
-
Git GUI:提供了一个图形用户界面来运行git命令
(设置环境变量是为了全局使用,而git可以在任何地方右击选择Git Bash使用,所以配或不配没啥大区别)
常用Linux命令
cd
:改变目录cd..
:回退到上一个目录,直接cd进入默认目录pwd
: 显示当前所在的目录路径Is
:都是列出当前目录中的所有文件touch
:新建一个文件 比如 touch index.jsrm
: 删除一个文件 rm index.jsmkdir
: 新建一个目录,即新建一个文件夹rm -r
:删除一个文件夹 如 rm -r src 删除src目录mv
:移动文件,mv index.html --将index.js移动到src文件夹,这样写必须保证文件和目标文件夹在同一目录下reset
: 重新初始化终端清屏clear
:清屏history
:查看历史命令help
:帮助exit
:退出#
:注释
2.2 Git的配置
(1) 设置用户名和邮件地址(重要)
每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改;如果使用了 --global
选项,那么该命令只需要运行一次。
- 设置用户名
git config-global user.name 'lxh'
git config-global user.email '邮箱地址@qq.com'
(2) 配置别名(可配可不配)
如果不想每次都输入完整的Git命令,可以为某些命令设置一个别名
$git config --global alias.br branch
$git config --global alias.ci commit
$git config --global alias.st status
别名的使用:
2.2 查看配置
- 查看系统配置(系统给配置的东西)
git config --system --list
- 查看本地配置(用户自己配置的)
git config --global --list
- 查看配置所有配置(系统配置+本地配置)
git config -l
三、 Git基本理论
3.1 工作区域
- Workspace : 工作区,即平时存放项目代码的地方(项目文件)
- Stage/Index:暂存(暂缓)区,用于临时存放你的改动,事实上他只是一个文件,保存即将提交到文件列表信息
- Repository:仓库区(或
本地仓库
),即安全存放数据的位置,这里面有提交到所有版本的数据。其中HEAD指向最新放入仓库的版本 - Remote:
远程仓库
,托管代码的服务器(比如Gitee)。
3.2 文件状态
对文件划分不同的状态,以确定这个文件是否已经归于Git仓库的管理
- 未跟踪(Untracked):并未加入git库中,通过
git add
状态变为Staged
- 已跟踪:添加到Git仓库管理的文件处于已跟踪状态,已跟踪状态的文件又可细分为以下几个状态
- Unmodifed:未修改状态;文件已提交到git仓库,且为修改
- Modified:文件已修改,但并未进行其他操作
- Statged:暂存状态
查看文件状态
#查看指定文件状态
git status [filename]
#查看所有文件状态
git status
# 查看更简洁的状态信息
git status -s
简洁信息 ,左侧表示暂存区状态,右侧表示工作区的状态:
四、Git项目的搭建与操作
可将VSCode的默认终端设置为bash,这样每次打开终端都是bash
4.1 初始化Git仓库
在创建一个新项目时,需要初始化本地仓库;(很多脚手架在创建项目时都会默认创建一个Git仓库)
$ git init
Initialized empty Git repository in xxxx
git init
命令将创建一个名为.git的子目录,含有Git仓库所必须的文件
4.2 常见的操作
4.2.1 文件添加到暂存区
- 跟踪新文件(将新文件添加到暂存区)
git add 文件名
- 如果已经跟踪了一个文件,该文件修改之后处于
modified
状态。也需要重新添加到暂存区 - 将当前目录的所有文件添加到暂存区(
.
是当前目录的意思)git add .
4.2.2 文件提交更新
git commit
将暂存区的所有文件提交到本地仓库中;(建议在提交之前,先用git status
检查是否所需文件都在暂存区)- 提交信息时,写上参数
-m
来备注提交信息git commit -m '提交信息'
git commot 文件名 -m '提交信息'
,提交某个单独的文件
- 添加到暂存区,提交到仓库,两个命令可以用一行来代替
git commit -a -m '提交信息'
- 等价于
git add .
+git commit -m '提交信息'
4.2.3 查看历史提交记录
git log
查看历史提交记录,在不传入任何参数的默认情况下,git log会按时间先后顺序列出所有的提交,最近的更新排在最上面。
# 简单打印历史记录
git log --pretty=oneline
# 以图的方式打印历史记录
git log --pretty=oneline --graph
前边黄色的一大长串的字符是校验和,每次提交生成的校验和是不一样的,也被称做commit ID,用来标识每次的提交。
4.2.4 版本回退
Git通过HEAD指针记录当前版本,HEAD总是指向该分支上的最后一次提交。我们可以通过HEAD来改变Git目前的版本指向;
- 通过HEAD改变Git版本的方式
git reset --hard HEAD^ // 回退到上一个版本
git reset --hard HEAD~1000 // 回退到上1000个版本
git reset --hard 校验和ID // 指定回退到某一个版本
- 当通过校验和指定回退的版本时,只写前几位,能定位到具体的提交版本即可,不用全写
如果想恢复最新的版本,通过git log
已经看不到回退之前的版本了,可通过git reflog
查看目前做过的所有操作。
这样可以查看到回退HEAD之前的某些版本的校验和,进而进行版本回退
2.5 .gitignore配置文件
有些文件无需纳入Git的管理,也不希望它们出现在未跟踪文件列表里;因此可创建.gitignore
文件,列出要忽略的文件。
这个文件一般不需要自己写,直接用网上的模板即可。github官方给出了一些模板:
链接:github-gitignore
五、远程仓库
多人合作开发项目时,会将代码共享到远程仓库中。所以需要在Git服务器上搭建一个远程仓库。
目前使用Git服务器的方式
- 使用第三方的Git服务器:GitHub,Gitee,Gitlab等
- 在自己的服务器搭建一个Git服务器。
- 在云服务器上,通过某些软件,搭建Git服务器;Git服务器里可以创建很多的远程仓库。
比如刚入职时,初始化本地仓库,可用命令git clone
将远程仓库的内容拉取到本地。如果远程仓库是一个私人仓库,则需要进行身份认证。
5.1 身份认证
对于私人的远程仓库,想要进行操作时,远程仓库会对我们的身份进行验证。目前Git服务器验证手段有两种:
- 方式一:基于HTTP的凭证存储(Credential Storage)
- 方式二:基于SSH的密钥
5.1.1 HTTP凭证
HTTP协议本身是无状态的连接,也就是说,第一次连接时,需要输入用户名和密码;第二次连接时,Git服务器并不会记录是否曾经连接过,所以还是需要输入用户名和密码;每一次连接都需要用户名和密码。
好在Git有一个凭证系统来处理这个事
Git Credential Manager for Windows
会将凭证以加密的方式缓存起来。在安装Git时,选择对应的选项,就会自动顺便下载这个工具。
# 输入这行命令来检查电脑的Windows系统中是否安装了这个工具
git config credential.helper
manager # 命令行输出这一句则表示已安装
使用步骤:
- 在第一次拉取远程仓库的代码时,需要输入账号密码,生成凭证,后续就不需要重复输入了。
在控制面板里可以查看或删除凭证(也叫凭据)
- 然后在终端 执行这行命令,即可拉取远程仓库代码到本地
5.1.2 SSH密钥
Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。
SSH以非对称加密实现身份验证。 其中一种方法是人工生成一堆公钥和私钥,通过生成的密钥进行认证,这样就可以在不输入密码的情况下登录。
以SSH的方式访问Git仓库,就需要生成对应的公钥和私钥;接下来以Gitee种的远程仓库为例,进行配置SSH的说明(gitee官网公钥设置全流程):
SSH使用步骤:
-
生成密钥
ssh-keygen -t ed25519 -C '注释xxxx' // 或者 ssh-keygen -t rsa -C 'xxxx'
-t
:生成的key的类型
-C
:注释
-
生成的公钥和私钥文件:
-
将生成的公钥(打开文件,复制粘贴) 添加到Gitee账户中。
-
最后,执行这行命令拉取远程仓库的代码
分析一篇博客::Github配置ssh key的步骤(大白话+包含原理解释)
需要注意:后续在连接github远程仓库时碰到这个错误(代理问题)
$ git fetch origin main
fatal: unable to access 'https://github.com/keke474/remote-unsame.git/': Empty reply from server
解决方法:在与远程仓库建立连接时,选用SSH,而非HTTP验证
5.2 管理远程仓库(添加)
现有两个项目,一个项目的仓库是本地初始化的;一个项目是从远程仓库clone拉取下来的
-
查看某个项目连接的远程仓库
-
git remote
, 列出该项目连接的远程仓库 -
git remote -v
,显示远程仓库的详细信息(clone下来的项目的远程仓库名称默认为origin)
-
-
添加远程仓库(让本地仓库与远程仓库建立连接)
git remote add 自定义远程仓库名称 地址
让
01_GitDemo
与远程仓库建立连接; (一个本地仓库可以连接多个远程仓库) -
重命名远程仓库:
git remote rename gitlab glab
(将名字gitlab改为glab) -
移除远程仓库:
git remote remove 仓库名
5.3 与远程仓库的交互
- 从远程仓库clone代码
git clone xxxx项目地址
- 将本地仓库的代码推送到远程仓库中
git push <远程仓库名> 当前分支名:远程仓库分支名
,将当前分支推送到远程仓库的某个远程分支中- 简单写法:
git push
,将代码推送到远程仓库(5.4会详细讲这个命令)
- 从远程仓库fetch代码:从远程仓库获取最新的代码
git fetch
,默认从origin中获取代码git fetch xxx
,从指定的仓库中获取代码
- 获取到代码后默认并没有合并到本地仓库,需要通过merge合并
git merge
- 从远程仓库pull代码:pull等价于fetch+merge
git pull
5.4 pull与push可能会出现的错误
先把 第6节 Git分支的内容看个大概,再来看下边的内容
以下错误,都是先建立本地仓库,后连接远程仓库造成的;
5.4.1 git pull时会出现的错误
先创建本地仓库,然后将本地仓库01_GitDemo
与远程仓库建立连接,在将本地代码push到远程仓库之前,要先拉取(pull)一下远程仓库的代码。但是执行git pull
时会报错
问题背景:先建立本地仓库,后连接远程仓库,二者默认分支都名为master
-
问题一:未指定要跟踪的分支。
本地仓库和远程仓库通过
git remote
建立了连接,但是仓库里有很多分支,并未指定本地仓库的哪个分支与远程仓库的哪个分支有链接,所以pull代码时,不知道要从哪个仓库的哪个分支里拉取代码。- 方案一:指定仓库分支
git pull <remote> <branch> #指定从哪个仓库哪个分支拉取代码
-
方案二:指定上游分支(采用这个)
将远程仓库里的某个分支 指定为 本地仓库当前的分支(master)的一个上游分支(跟踪分支)。
# 指定origin仓库的master分支作为上游分支 $ git branch --set-upstream-to=origin/master Branch 'master' set up to track remote branch 'master' from 'origin'.
以后每次pull代码只需执行
git pull
即可
- 方案一:指定仓库分支
-
问题二:合并远程分支时,拒绝合并历史不相干的分支
pull = fetch+merge
, 这个问题出现在merge合并阶段。
历史不相干的意思是:
远程仓库有很多次commit,本地仓库也有很多次commit;这两个仓库的提交历史没有交接的地方(没有共同的base基础),就是历史不相干。
比如:当远程仓库R4和本地仓库的L5要合并时,由于它们两个历史不相干,所以会出现上述错误;而L5和T101因为有共同的base L4,历史相干,所以这两个合并时不会出错。
解决方法:加参数--allow-unrelated-histories
在已经确定了上游分支后,执行这行代码,远程仓库的代码会成功出现在本地仓库中
$ git pull --allow-unrelated-histories # 或者 $ git fetch $ git merge --allow-unrelated-histories
再执行
git push
,本地的代码则成功上传到远程仓库。
中间也出现过这种问题:git fatal: branch ‘master‘ does not exist
解决方法:git checkout master
(具体见博客)
5.4.2 git push时会出现的错误
问题背景:先创建本地仓库,后连接远程仓库,二者默认分支名不同(本地:master,远程:main)
现新建项目remote_branch
, 进行以下操作
$ git init # 初始化仓库
$ git add . # 添加到暂存区
$ git commit -m 'aaa.js' # 提交
$ git remote add origin git@github.com:keke474/remote-unsame.git # 连接远程仓库
$ git branch --set-upstream-to=origin/main # 设置上游分支
$ git pull --allow-unrelated-histories # 拉代码
接下来将本地的代码push到远程仓库中(是想把aaa文件push到远程仓库中)
解决方案一: 写完整版的push命令
# 将本地的master分支内容 push 到远程仓库的main分支
$ git push origin matser:main
但是每次都push都需要写完整版的命令比较麻烦 如果简写为:
$ git push origin matser
则是将本地master分支的内容,push到远程仓库origin的master分支上。(远程仓库没有master分支,则执行命令时会自动创建一个master分支)
解决方案二:设置push
既然设置了上游分支,我们更希望git push
默认会将当前分支的内容提交到上游分支中。
查看文档可知push.default
的默认值为simple
也就说明git push
默认情况下是将当前分支的内容推送到远程的同名分支中。所以需要改一下配置
# 设置默认将当前分支推送到上游分支
$ git config push.default upstream
# 然后只需运行git push命令即可
git push
另外科普一下这两个配置
# 设置将当前分支的内容推送到远程仓库的同名分支中,若远程仓库没有同名分支,则新建一个
$ git config push.default current
# 设置将当前分支的内容推送到远程仓库的同名分支中,若远程仓库没有同名分支,则报错
$ git config push.default simple
此时若新建一个分支dev,修改代码并commit后,进行push。也会报错
$ git push
fatal: The current branch dev has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin dev
最开始设置的上游分支是master
的上游分支,所有dev需要重新设置上游分支。设置上游分支即可。
如果修改push默认配置为current,则远程仓库会新建一个dev分支
5.5 项目开发可能的流程
情况一:接触的项目已有远程仓库了
1. 克隆到本地 git clone xxx
2. 进行开发
git add .
git commit -m 'xx'
git pull
git push
情况二:要搭建一个全新的项目
1. 创建一个远程仓库(去github上新建一个远程仓库)
2. 方案一:
2.1 克隆到本地 git clone,在clone下来的文件夹中搭建整个项目
2.2 进行开发
git add .
git commit -m 'xxx'
git push
方案二:
2.1 搭建本地项目,在项目中创建一个本地仓库(git init)
2.2 与远程仓库建立连接 git remote add orign xxx
2.3 建立上游分支 git branch --set-upstream-to=origin/master
2.4 拉取代码 git fetch
2.5 设置允许历史不相干的合并 git merge --allow-unrelated-histories
2.6 上传本地代码 git push
5.6 常见的开源协议
在创建开源的远程仓库时,会选择开源协议;比如Vue.js是一个开源项目,开源协议就是规定,当别人用Vue开发别的项目时,需要遵守的一些约定。
六、 Git分支
6.1 校验和
Git中所有的数据在存储前都计算校验和,然后以校验和来引用
校验和作为本次提交的唯一ID,所以每次提交的校验和都是不一样的。如果回看历史记录,想知道某次提交都提交了什么文件,则该次提交的校验和作为索引值去查找。
6.2 Git的提交对象(commit object)及底层原理
结合具体例子更好的理解提交对象及底层原理:
-
新建本地仓库,并将
111.js
与222.js
通过add命令存入暂缓区,此时,在.git/objects
文件夹里,生成了两个新的文件0c
和3e
,
-
通过
git cat-file -p
读取0c 和3e里的这两个文件。
这个命令会自动去
.git/objects
文件夹里找到对应的文件(3e0017,就是指objects文件夹里名为3e的文件的 0017的文件)。读取出来发现这两个文件记录的分别是111.js
和222.js
两个文件的内容。 -
现通过commit将这两个js文件提交到本地仓库,会发现objects文件夹里又多了两个文件
6b
,48
读取6b
文件,列出了本次提交的注释等信息,以及一个tree
,而tree后边指向的正是48
这个文件
读取48
文件,又列出了刚才生成的0c
和3e
两个文件。
其实这些文件的名称都是唯一的,都是校验和。
总结来说,Git底层存东西原理:
每次commit提交,Git都会保存一个提交对象(Commit Object),
通过git log获取到该次提交的校验和,就能获取到这次提交的Commit Object。
$ git log --pretty=oneline
6bf8c7627e630f6bea80171a58dc34eeef249534 (HEAD -> master) 提交111与222js文件
提交对象里存在tree
属性,而该属性的值也是一个校验和,根据该校验和可到这次提交所依赖的文件(二进制形式的111.js和222.js)。
除了第一次提交之外,后面每次提交的Commit Object对象里,都会有parent
属性,指向上一次的提交对象。当执行git log
时,找到的是最后一次提交的对象,然后根据parent
属性,一步步找到前边提交的所有对象,然后依次列出来。
当将新建的ccc和ddd文件,git add .
添加到暂缓区时,Git仅仅时将这两个文件作为二进制文件,保存在objects
文件夹里面,并没有对应的提交对象指向这两个文件;
当执行commit
命令时,才会通过提交对象的tree
属性将这两个文件与提交对象联系在一起;
6.3 Git创建tag标签
对于重大版本,我们常常会打上一个标签,比如用标签标记发布节点(v1.0,v2.0)
-
创建标签
git tag v1.0
git tag -a v1.1 -m '额外信息'
-
将标签push到远程仓库
- 默认情况下,
git push
不会将标签传送到远程仓库,需要指定 git push 仓库名 v1.0
- 默认情况下,
-
删除标签
- 删除本地仓库标签:
git tag -d v1.1
- 删除远程仓库标签:
git push 仓库名 --delete v1.1
- 删除本地仓库标签:
-
检出tag(就是切换到某一个tag节点)
git checkout v1.0.0
举个例子:从github 克隆空白项目到本地(github远程仓库的默认分支叫main,不是master),提交四次,并push到远程仓库中;目前HEAD指向最新节点444
# 将本地打的标签提交到远程仓库
$ git push origin v1.0.0
# 检出tag
$ git checkout v1.0.0
HEAD is now at c3ffb8e 333
# 当切换到v1.0.0时,一般是要创建分支,在该分支上继续别的开发,最后合并时,切回到main分支上
$ git checkout main
Switched to branch 'main' # 切回之后,HEAD不是指向c3ffb8e了,而是最新节点555
6.4 认识Git分支
-
在Git中,默认有一个
HEAD
指针指向默认分支master
; Git通过Head
指针判断当前处于哪个指针 -
Git的分支,本质上是一个指向Commit Object的可变指针;Git默认的分支名字是master,master分支并不是一个特殊分支,这个分支是命令
git init
默认创建的分支。
比如:现初始化一个项目,并commit
了三次,并在提交333
时,创建了一个tag;
此时通过git branch xxx
创建分支,并通过git checkout xxx
切换到该分支。
多个分支的来回切换,本质是改变HEAD指针的指向
可以看出,分支testing
目前指向的是333
这个节点;
当在testing分支提交test1
,master分支提交444
时:
结构变为:
6.5 Git分支的操作
git branch 分支名 # 创建Git分支
git checkout xxx # 切换到xxx分支
git checkout -b xxx # 创建的同时切换分支
git merge hotfix # 合并分支
git branch # 查看当前所有的分支
git branch -v # 同时查看最后一次提交
git branch --merge # 查看所有合并到当前分支的分支
git branch --no-merge # 查看所有未合并到当前分支的分支
git branch -d xxx # 删除xxx分支
git branch -D xxx # 强制删除xxx分支
6.5.1 开发项目(master分支上提交)
列举一个实际工作中的类似的工作流:
- 开发某个项目,在默认分支master上进行发布;
- 实现项目的功能需求,不断提交;
- 并在一个大的版本完成时,发布版本,打上一个
tagV1.0.0
- 然后继续开发新功能
$ git init
$ git add .
$ git commit -m '111'
$ git commit -a -m '222'
$ git commit -a -m '333'
$ git tag V1.0.0
$ git commit -a -m '444'
$ git commit -a -m '555'
6.5.2 中途修复bug (创建并切换分支)
在继续开发后面的功能时,要求修复V1.0.0
的bug
- 切换到标签
V1.0.0
的节点 - 创建
hotfix
分支并切换到该分支 - 在新创建的分支上修复bug
- 完成工作后,打上标签tag
V1.0.1
$ git checkout V1.0.0 # master指向V1.0.0的版本
$ git checkout -b hotfix # 创建并将HEAD指针切换到hotfix分支
$ git commit -a -m 'fix_01' # 提交修复后的代码
$ git commit -a -m 'fix_02' # 提交修复后的代码
$ git tag V1.0.1 # bug修复完,在该节点打标签
做完这些操作后,结构为:
6.5.3 bug修复完,合并分支,继续后续的开发
bug修复完之后,hotfix分支的fix_02
与master分支的555
需要合并,才能保证master后续的开发没有该bug;
- 切换回master分支;
- 合并hotfix分支,解决合并分支产生的冲突(修改代码)
- commit提交修改后的文件
$ git checkout master # 切换回master分支,此时HEAD指针指向的是最新版本(555)
$ git merge hotfix # 在master分支上(当前处于master分支) 合并hotfix分支
合并之前,两个分支的代码分别为:
两个文件第7行和第9行代码不一致,合并的话这里会有冲突;合并时,Git会在文件中标明冲突的地方(有背景色的地方)
$ git commit -a -m '解决合并冲突' # 提交解决冲突后的代码
$ git log --pretty=oneline --graph # 图的方式查看一下提交记录
全程结构为:
七、 远程分支
远程分支也是一种分支结构。
7.1 远程分支的基本操作
- 推送分支到远程仓库
git push <remote> <branch>
- 跟踪远程分支
git checkout --track <remote/branch>
git checkout <branch>
- 删除远程分支
git push <remote> --delete <branch>
7.2 举例
(1) 新建项目
$ git init #初始化
$ git add .
$ git commit -m 'branch.html'
$ git remote add origin git@github.com:keke474/remotebranch.git
# 设置上游分支,报错
$ git branch --set-upstream-to=origin/main
原因是不知道远程仓库有origin/main分支。
方案一:
所以需要先$ git fetch origin main
, 这个命令的本质是拉取远程仓库mai分支的内容到自动创建的本地origin/main分支上。
接下来再设置上游分支
$ git branch --set-upstream-to=origin/main # 设置上游分支,报错
# 合并的完整命令:git merge 分支名;这里不加分支名,则默认将当前分支内容与上游分支内容合并
$ git merge --allow-unrelated-histories
# 由于本地仓库与远程仓库默认分支名称不一致,改变push的默认设置
$ git config push.default upstream
$ git push
方案二:
一切都是因为两个仓库的默认分支名不一样。执行下行命令
$ git checkout --track origin/main
创建并切换到main分支,并且跟踪origin/main分支。此后本地仓库默认分支也叫main,就不用修改push默认配置了。直接执行git pull
或者git push
即可
注意:
- 在执行track时,要保证本地有名为origin/main的分支,所以必须要fetch,因为fetch会创建origin/main的分支(见方案一)。
- 保证当前仓库的内容与远程仓库一致,比如提前push,保证内容一致。否则track时,切换到main之后,本地仓库的内容将完全变成origin/main分支的内容(也就是fetch从远程仓库拉取的内容),本地的
branch.html
文件就没了。
(2) 新建dev分支进行开发
# 创建并切换到dev分支进行下一步开发
$ git checkout -b dev
$ git commit -a -m 'dev1'
$ git push origin dev # 推送分支到远程,远程仓库就多了个dev分支
$ git commit -a -m 'dev2'
$ git push --set-upstream origin dev # 再次git push还是要设置上游分支
$ git commit -a -m 'dev333' # 开发并提交
$ git push # 直接push推送
(3) 一位新入职的员工需要在dev分支上进行开发
$ git clone git@github.com:keke474/remotebranch.git # 克隆项目到本地,
$ git branch # 但是克隆下来的只有main分支
* main
$ git checkout dev # 执行这行命令 等价于 git checkout --track origin/dev
这行命令进行了如下几步操作
- 检查远程是否存在 origin/dev分支
- 有的话在本地创建并切换到dev分支,并跟踪远程的origin/dev
- 远程没有origin/dev且本地没有dev分支, 就报错
- 本地有dev,这行命令就是切换分支