git 分布式版本控制工具
- 集中式版本控制 svn,版本库放在中央服务器,工作时联网把自己的任务推送到中央服务器
- 分布式版本控制 git,没有中央服务器,每个客户端是一个完整的版本库
git 的功能
- 保存文件的所有修改记录
- 使用版本号进行区分
- 随时可以浏览历史版本记录
- 能够还原到历史指定版本
- 对比不同版本的文件差异
关于 git 的更多实战,学习 Git 分支
1、git 安装配置
1.1、git 安装
# linux sudo apt-get install git # 安装 OhMyZsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
1.2、git 的配置
1.2.1、配置文件
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。
git config --system~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。
git config --global.git/config
文件:仅对当前项(目录)有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
git config
1.2.2、配置用户
# 设置当前目录下的用户名和邮箱 git config user.name Azured_Winged_Maggpie git config user.email 2764961197@qq.com vim ./git/config git config --local -l # 设置当全局的用户名和邮箱 git config --global user.name Azured_Winged_Maggpie git config --global user.email 2764961197@qq.com vim ~/.gitconfig git config -l
2、git 原理
2.1、git 的四个区域
本地 3 个区域 + 远程 git 仓库
git 区域
Working Directory
: 工作区,即当前工作目录,存放代码的位置。Stage/Index
: 暂存区,临时存放改动,事实上是一个文件,保存即将提交的文件列表信息Repository
: 仓库区(版本库),存放提交的所有版本的数据, HEAD 指向最新的版本。Remote Directory
: 远程仓库,托管代码的服务器
2.2、git 工作流程
- 在工作目录中添加、修改文件
- 将需要进行版本管理的文件放入暂存区
git add 文件名
- 将暂存区域的文件提交到仓库
git commit -m "提交信息"
- 本地仓库的修改 push 到远程仓库,如果失败则执行第5步
git push origin master
- 将远程仓库的修改拉取到本地,修改冲突,回到第3步
git push origin master
2.3、git 文件的状态
文件的各状态转化如图所示:
git 文件状态
Untracked
: 未跟踪。文件未入仓库,不参与版本控制。Unmodify
: 文件已入仓库但未修改,即工作区与仓库中的文件一致。Modified
:文件已被修改,即工作区与仓库中的文件不一致。Staged
:暂存状态
3、git 操作
3.1、创建仓库
# 1、远端仓库:git init,别名 orgin # 当前目录作为 git 仓库 git init --bare # --bare 该仓库为裸仓库 # 指定目录作为 git 仓库 git init newrepo # 2、本地仓库:git clone # 克隆一个仓库到指定目录 git clone <repo> <directory>
3.2、免密登录
使用协议 (http, ssh, git等) 来实现远端仓库和本地仓库的交互。
使用 ssh 公钥免密登录 git 服务器
# 1、本地生成公钥和私钥 ssh-keygen -t rsa # 2、复制公钥内容到远端 git 服务器 # 本地:拷贝本地公钥 id_rsa.pub cat ~/.ssh/id_rsa.pub # 远端:复制到 git 服务器的 authorized_keys vim .ssh/authorized_keys # 3、远端仓库克隆到本地 git clone git@<CVM IP地址>:git仓库路径
3.3、基本操作
# 1、暂存,工作区 -> 暂存区 git add <path> # 2、提交,暂存区 -> 本地仓库,提交到仓库的文件才真正被 git 追踪记录 git commit -m "提交信息" -a 把当前暂存区里所有的修改(包括删除操作)都提交,未添加到暂存区的内容是不提交 # 3、推送,本地仓库 -> 远端仓库 git push origin master # 拉取合并 git pull origin master # 查看状态 git status # 查看日志 git log [option] --all 显示所有分支 --pretty=oneline 将提交信息显示为一行 --abbrev-commit 使得输出的commitId更简短 --graph 以图的形式显示 # 忽略文件 # 目录下创建.gitignore文件,添加文件至忽略列表
3.4、版本回退
从工作区回退,工作区 -> null,清空工作区的的修改
# 从本地仓库或暂存区中检出文件,并且覆盖工作目录的内容 # 也就是说放弃本地的所有修改,但是工作区新创建的文件不会被删除 git checkout
从暂存区回退,暂存区 -> 工作区
git resore -S
从本地仓库回退
# 使用该 commit 做回滚操作 git reset commitId / HEAD^ # 1、本地仓库 -> 暂存区,暂存区和工作区都不会被改变 git reset --soft commitId / HEAD^ # 2、本地仓库 -> 工作区,暂存区同步到指定的commit,工作区不改变 git reset --mixed commitId / HEAD^ # 3、本地仓库 -> null,修改的内容被清除,暂存区和工作区都同步到指定的提交 git reset --hard commitId / HEAD^
从远端仓库回退
git revert commitId fix conflict git commit git push
3.5、本地仓库整理
注意:修改某个结点导致从该结点往后的所有结点的 commitId 发生变化,会引起其他人冲突,要确保没有人基于你的分支开发。
整理上一次的提交
git commit -amend
整理多次提交
本地 commit 直接使用 git rebase -i
。 push 到远端的 commit 需要使用 git log
查看 commit id,来确定要修改的区间范围。
git rebase -i commitId commitId # 左开右闭
例:合并分支
git rebase -i # 指令名称 + commit hash + commit message p 0bdf99c add_file # pick,执行该 commit s 0eed97b modify_file # squash,该 commit 合并到前一个 commit # 重新编辑合并后的信息(删除之前的信息) add_file # git log 查看合并成功
例2:修改任意提交的内容
git rebase -i # 选择要修改的commit e 2007ae9 add_file # 修改文件内容 # 添加到暂存区 git add filename # 修改要提交的message git commit –-amend # 整理完成该commit结束 git rebse --continue # 若该 commit 已经 push 到远程仓库,产生冲突,强制推送 git push --force
3.6、分支命令
3.6.1、查看分支
git branch
3.6.2、创建分支
git branch 分支名 # 创建分支 git checkout -b 分支名 # 创建并切换分支
3.6.3、切换分支
git checkout 分支名 git switch 分支名
3.6.4、合并分支
HEAD
指向当前所在的分支,当分支切换时,HEAD
会跟着切换到对应分支。
解决冲突
冲突的产生原因:不同分支修改了同一文件的同一行或者相邻行。
解决:
- 合并分支:
git merge / git rebase
,合并前先 pul l更新代码 git add
git commit
git push
merge 合并
git merge
merge 当前分支始终是目标分支,其他分支始终合并到当前分支。所以,需要将某个分支合并到目标分支时,需要先切到目标分支上。
merge 操作会生成一个新的合并结点,冗余信息增多,适用于公有分支上。
A---B---C topic / D---E---F---G master A---B---C topic / \ D---E---F---G---H master # 生成新的提交 H
合并分支,并解决冲突
# 1、拉取 master 最新数据 [master] $ git pull origin master # 2、把 master 合并到当前分支 [master] $ git checkout develop [develop] $ git merge master develop # 产生冲突 CONFLICT (content): Merge conflict in file Automatic merge failed; fix conflicts and then commit the result. # 3、测试代码,解决冲突 # 打开产生冲突的文件,解决冲突 <<<<<<< HEAD hello ======= world >>>>>>> master # 提交解决冲突后的文件 [develop] $ git add . [develop] $ git commit -i -m 'fix:merge master' # 4、测试ok,合并到 master,提交到远端 [develop] $ git checkout master [master] $ git pull push master
rebase 合并
git rebase <newbase> <branch> # branch分支以newbase分支为基底
rebase,变基,改变当前分支的起点。
git rebase
rebase 操作流程
- 从两个分支的共同祖先开始提取当前分支上的修改
- 提取的提交应用到目标分支的最新提交的后面
- 将当前分支指向目标分支的最新提交
具体来说,首先,从当前分支 feature 和目标分支 master 的共同祖先开始提取 feature 分支上的修改 C、D。其次,将提取的提交 C、D 接到 master 分支的最新提交 M 后面,即删除原来的C、D,生成新的 C' 、D'。C'、D'内容不变,但会改变其提交id。最后。将 feature 分支指向 master 分支的最新提交D’。该过程中,feature 分支的基底由 B 变成了 M,发生变基。
问题:由于 rebase 过程中,可能会改变提交 id,引起他人基底改变,发生错误。所以 rebase 操作适用于私有分支,即当前分支没有依赖。
来看下面这个 rebase 合并的案例,左侧为案例,右侧为目标
git rebase main bugFix git rebase bugFix side git rebase side another git rebase another main
3.6.5、删除分支
# 删除分支,不能删除当前分支,只能删除其他分支 git branch -d b1
4、git 规范
主分支 master
- 最稳定的版本,只合并 develop 和 hotifx,合并后打 tag 标识版本,从指定 tag 处发布版本到线上。
- 限制 merge 权限,只允许主管执行,开发人员只能通过 merge request 合并
开发分支 develop
- 限制 merge 权限,只允许主管执行,开发人员只能通过 merge request 合并
- 只有功能完整并测试稳定后,才允许向 master 提交 MR(merge request )
功能分支 feature
- 命名规范:feature/功能名
- 先 pull 远端代码,然后 rebase 整体提交。功能测试完成后,提交 MR,报告主管合并
修复分支 fix
- 命名规范:fix/问题描述
- 使用方法与功能分支类似
紧急修复分支 hotfix
- 命名规范:hotfix/问题描述
例:
# 1 创建功能分支 git checkout -b feature/renameNotificationGroup # 2 开发后,提交代码 git checkout feature/renameNotificationGroup git add . git commit -m “ver_1” git push --set-upstream origin feature/renameNotificationGroup # 3 合并该功能分支到开发分支 git fetch origin develop:develop git checkout develop git merge feature/renameNotificationGroup git push origin develop