华为云DevOps系列之 —— 持续开发与集成(三)Git 基本概念及主要操作
【摘要】 华为云DevOps系列之 —— 持续开发与集成(三)Git 基本概念及主要操作
Git
1. 基本概念
Git 是什么?
- Git 是目前世界上最先进的分布式版本控制系统
- Git 近乎所有操作都是本地执行
Git 优点
- 版本库本地化,本地仓库是服务器仓库的完整克隆,包括标签分支、版本记录等
- 支持离线提交,适合跨地域协同开发
- 分支切换快速高效、创建和销毁分支简单容易
- 由于Git在本地磁盘上就有项目的完整历史,所以在Git中绝大多数操作只需要访问本地文件和资源,不需要实时的与代码服务器连接
Git 文件状态
- 文件的三种状态
- 已修改
- 修改后的 git 仓库中的文件(新增文件、被修改的文件或被删除的文件)
- 已暂存
- git add ‘已修改’ 文件
- 已提交
- git commit ‘已暂存’ 文件,本地的代码同步到远程:git push
- 已修改
2. 主要操作
Git 配置
-
查看 Git 版本
- git --version
- git --version
-
配置用户名和Email
- git config --global user.name yourname
- git config --global user.email name@mail.com
-
查看配置信息
- git config -l
- git config -l
-
传输方式配置
- HTTPS 配置
- git config --global credential.helper “cache”
- SSH 配置
- 生成 ssh-key
ssh-keygen
(根据ssh-keygen
命令,会在本地产生一对秘钥,公钥是以.pub为后缀的文件,把公钥中的内容粘贴到服务器中,就可以使用SSH进行通信了) - 将 public key 添加到 remote 仓库
- 添加 ssh 配置(~/.ssh/config)
- 格式
- 权限 600
- 生成 ssh-key
- HTTPS 配置
-
配置忽略文件
- .gitignore 文件的位置
- 可以配置在代码仓库的任意目录,但是下面规则是以 .gitignore 所在目录为根目录
- .gitignore 文件的位置
规则 | 作用 |
---|---|
/mtk/ | 过滤整个文件夹 |
*.zip | 过滤所有 .zip 文件 |
/mtk/do.c | 过滤某个具体文件 |
!/mtk/one/txt | 追踪(不过滤)某个具体文件 |
初始化仓库
- 创建第一个代码库
- git init
- 从远端克隆仓库到本地
- git clone ssh/https
url
- git clone ssh/https
远程仓库管理
- 查看所有的远程仓库
- git remote -v
- 添加远程仓库
- git remote add remote-name remote_url
- 修改远程仓库命名
- git remote rename old-remote-name new-remote-name
- 删除远程仓库
- git remote remove remote-name
分支管理
- 查看所有分支
- git branch
-v
查看分支的最新的提交-a
查看所有分支包括远程分支
- 切换分支
- git checkout branch_name
- 创建新的分支
- git checkout -b new_branch
- git branch new_branch --track remote-name/remote-branch(基于远程仓库的分支创建新的分支)
- 删除分支
- git branch -d branch_name
Git 分支(指针)
- 分支
- 本质上是个指向 commit 对象的可变指针
- 分支的默认名字为 master
- 每次提交的时候都会自动向前移动
- 作用:从某个提交对象往回看的历史
- 新建分支
- 示例:新建一个 testing 分支
- git branch testing
- 如何识别当前分支
- HEAD 指针(可以理解为当前分支的别名)
- 示例:切换到当前分支
- git checkout testing
- 在 testing 分支上做一次提交操作
- vim test.rb
- git commit -a -m ‘made a change’
- 每次提交后 HEAD 随着分支一起向前移动
- 现在,我们切换回 master 分支
- git checkout master
- 现在做修改的话,相当于处于一个旧的版本(即忽略 testing 分支所作的修改)
- 我们在 master 分支上也做一次提交
- vim test.rb
- git commit -a -m ‘made other changes’
- 我们可以看到项目的提交历史已经发生了分岔
Git 分支(合并)
分支合并:把一个分支中的修改整合到当前分支
普通合并(git merge)
-
快进式合并(fastforward)
- 顺着一个分支走下去可以到达另一个分支的合并过程
- 下图中,
hotfix
比master
多了一个c4
的提交,master
分支向前走一步就可以到达hotfix
分支,完成了从hotfix
向master
分支的合并
-
非快进式合并(non-fast forward)(三方合并)
- 使用两个分支的末端以及它们的共同祖先进行一次简单的三方合并计算的合并过程
三方
在下图中指的是master
分支中的c4
,iss53
分支中的c5
,以及它们两个之间的共同的父节点c2
- 和之前将分支指针向前推进所不同的是,git 将此次三方合并的结果做了一个新的快照,并且自动创建了一个新的提交指向它,这个被称作是一次合并提交。其特别之处在于,不只有一个父的提交,需要指出的是,git 会自行决定选取哪一个提交作为最优的共同祖先,并以此作为合并的基础(cvs / svn1.5之前版本需要用户自己选择最佳的合并基础)
分支衍合(git rebase)
- 衍合原理:先将
master
分支上新增的节点以补丁的形式保存在.git rebase
目录中,然后同步hotfix
分支的最新代码,在 git 中,这种操作叫做变基
- 可以使用 rebase 命令,将提交到某一分支上的所有修改都移交到另一分支(就像重新播放一样)
普通合并 & 分支衍合对比
merge
和rebase
的最终代码没有任何区别,但是变基使得提交历史更加整洁- 变基合并的提交历史是一条直线,使用变基一般是为了确保在向远程分支推送时,能保持历史提交的一个整洁
- 例如我们向某个人维护的项目贡献代码时,在这种情况下,首先在自己的分支里进行开发,当开发完成时,需要先将自己的代码变基的合并到自己的远程仓库master分支上,然后再向主项目提交合并请求。这样的话,该项目的维护者就不需要再进行整合工作,只需要快进合并即可
- 无论是通过变基还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了
变基
是将一系列提交按照原有次序,依次应用到另一分支上合并
是把最终结果合在一起,分支合并容易产生冲突
合并冲突
- 类型1:修改了同一文件的同一行
- 解决方法:确认正确的修改
- 示例:命令行解决
- 类型2:文件被重命名为不同的名字(树冲突)
- 解决方法:确认哪个名字是正确的,删除错误的
- 示例:命令行解决
同步远程代码
-
Merge 方式同步远程代码
git pull remote-name remote-branch
- 将远程代码的
master
分支同步到本地的feature
分支,merge 是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下,会提交合并中修改的内容 - merge 的提交历史,真实的记录了实际发生过什么,关注点在真实的提交历史上面
-
Rebase 方式同步远程代码
git pull -r remote-name remote-branch
- 将远程代码的
master
分支同步到本地的feature
分支,rebase 提取了远程仓库maser
分支的修改,将其复制在了本地feature
分支的最新提交的后面 - rebase 的提交历史反映了项目过程中发生了什么,关注点在开发过程上面
那么这两种方式哪一种更好呢?
- 我们不妨退后一步,想一下提交历史到底意味着什么?
- 有一种观点认为,仓库的提交历史即记录实际发生过什么,它是针对历史的文档,本身就有价值,不能乱改。从这个角度来看,改变提交历史是一种适度,你使用谎言掩盖的实际发生过的事情,如果由合并产生的提交历史是一团糟怎么办?既然就是如此,那么这些痕迹就应该被保留下来,让后人查阅
- 但是另一种观点正好相反,然们认为提交历史是项目过程中发生的故事,没有人会去出版一本书的第1批草稿,软件维护手册页是需要反复修订才能方便使用,持这一观点的人会使用
rebase
,怎么方便后边的读者就怎么写- 现在让我们回到之前问题上来,到底是 rebase 变基好还是直接的 merge 好,这并没有简单的答案,git 是一个非常强大的工具,它允许你对提交历史做许多事情,但每个团队每个项目对此的需求并不相同,既然我们已经学习了两者的用法和原理,相信我们以后在日后的开发中能做出明智的选择
跟踪文件
-
查看文件状态
- git status
- git status
-
提交文件
- git commit -m “提交一个新的文件”
- git commit --amend(加上
amend
参数可以对上一次提交追加修改,不单可以追加一些代码的修改,也可以对上一次提交的 message 信息进行修改)
-
提交代码到远程仓库
- git push remote-name remote-branch
- git push remote-name remote-branch
查看提交记录
- 查看提交记录
- git log
- 搜索历史记录
- 根据 commiter 搜索
- git log --author=“xxx”
- 根据提交信息进行查找
- git log --grep=“xxx”
- 根据 tag 信息查找
- git tag -f
- 根据 commiter 搜索
3. Git 最佳实践
- 我们先讲一下
fork
的功能,在最早以前在 GitHub 上 fork 是一个贬义词,它指的是某个人使开源项目向不同的方向发展,或者说他创建了一个竞争项目,使得原项目的贡献者变得分裂。后来(也就是现在的意思)fork
的意思是指在远程服务器创建一个完全属于开发者自己的项目副本,并且对其有推送权限。如果我们想参与某个项目,但是并没有推送权限,这时我们可以对这个项目进行fork
- 在下图的实践中,通过 fork 这种方式,项目的管理者不需要在忙着把这些用户添加到项目中,给他们赋予推送权限。开发人员可以 fork 这个项目,将代码项目推送到 fork 项目副本中
- 左侧是远端仓库,一个是交付代码仓库,还有两个是开发人员
fork
出的个人远程仓库,这两个个人远程仓库,包含了原来上游交付仓库中的所有内容,如分支、tag、提交等等。 - 开发人员将代码拉取到本地进行开发,开发完成后
push
到个人远程仓库,此时再向交付仓库发起pull request
的请求 - 项目架构师 / 项目管理者负责审核把关代码的质量,审核通过的代码,最终才会进入到交付代码仓库,通过这种方式有效地保证了生产环境代码的质量
最后,欢迎大家关注我的个人微信公众号 『小小猿若尘』,获取更多IT技术、干货知识、热点资讯。同时,我在公众号中分享了精心整理的一些视频资料(包括 Python全栈教程、AI教程、前端、数据库等),大家回复相应关键词即可获取网盘视频链接,感谢大家的关注😊
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)