
经典git工作流


简化git工作流(基于环境)

功能开发/修复完成后合并到develop,测试通过后基于master创建发布分支release,release合并开发/修复分支后,部署上线, 验收通过并封版后合到master,看需要来打tag
- 开发/缺陷分支只能合并稳定分支例如可以合并master分支,不可merge develop分支,作用是防止环境 污染
- develop分支只能用于测试环境发布,不可直接合并到release分支,正确流程是在release分支合并开 发/缺陷分支
常用命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| # 初始化git配置
git config --global user.name xxx
git config --global user.email xxx
# 查看git配置
git config -l
# 查看git用户名 邮箱
git config user.name
git config user.email
# 修改用户名
git config --global user.name {用户名}
git remote -v 显示所有远程仓库
git remote prune origin 删除本地有但在远程库已经不存在的分支
git clone -b 克隆分支名 地址
git remote add origin git@github.com:XXXXX/demo.git 新增远程仓库
git remote set-url origin git@github.com:XXXXX/demo.git 修改远程仓库
git remote set-url --add origin git@github.com:XXXXX/demo.git 添加多个远程仓库
git stash 不提交工作区内容
git stash pop 恢复工作区
git fetch 拉取远程分支
git checkout -b develop origin/develop
git reset --hard <commit ID号> 回滚
git push -f origin master 推送到远程分支
git diff 查看工作区和暂存区的区别
git diff –cached 查看暂存区和版本库之间的区别
git diff HEAD 查看工作区和版本库之间的区别
git status 查看当前的工作状态
git branch -a 查看本地所有分支
git branch -r 查看远程所有分支
git branch -r --contains v0.10.2 查看远程tag属于哪一个分支
git push --set-upstream origin online_help_20191024 推分支
git push origin --delete dev20181018 删除远程分支
git branch -d dev20181018 删除本地分支
git cherry-pick 285c9477a759abdee94099e25e75e39e8c77d46b 合并指定版本
git tag -d tag-name #删除本地tag
git push origin --delete tag-name #删除远程tag
|
分支操作
创建一个新分支
1
2
| git branch <new_branch_name>
git checkout <new_branch_name>
|
基于当前分支创建新分支
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 从main分支创建develop分支并切换到develop
git pull origin main (可选)
git checkout -b develop main
# 发布develop分支,使本地分支与远程develop关联
git push -u origin develop
# 发布到main分支
git checkout main # 切换到main分支
git merge --no-ff develop # 对develop分支进行合并
--no-ff
禁止使用快速合并模式,会生成一个新的提交,可以回退到main的上一次提交状态,
如果不加此参数的话,只能回到develop的上一次提交
|
从develop分支拉出一个新功能分支
1
2
3
4
5
6
7
8
9
| git pull origin develop (可选)
git checkout -b feature_v1.0 develop
git push -u origin feature_v1.0
# 完成后,合并到develop分支
git pull origin develop
git checkout develop
git merge --no-ff feature_v1.0 # 从feature分支合并到develop分支
git branch -d feature_v1.0 # 删除feature分支,可选
|
从develop拉出一个release分支
1
2
3
4
5
6
7
8
9
10
11
12
13
| git pull origin develop #可选,获取最新版本
git checkout -b release_v1.0 develop
# 完成release,合并到main分支和develop分支,在main打上tag标记
git checkout main
git merge --no-ff release_v1.0
git tag release1.0 master
git push origin v0.10.3 推送v0.10.3分支
git push --tags 推送本地所有tags
#合并到develop
git checkout develop
git merge --no-ff release_v1.0
|
拉取dev分支到当前本地分支
1
2
3
| 先切换到本地分支v1.0
git pull origin dev:v1.0
|
本地项目和远程仓库关联
1
2
3
4
5
6
7
8
9
| git init
git remote add origin <remote url>
git fetch origin main
git branch --set-upstream-to=origin/main main
git add .
git commit -m "xxx"
git push
若远程分支不存在,git fetch origin main命令替换为git push -u origin main
|
回退
revert仅仅是撤销指定commit的修改,并不影响后续的commit,但所撤销的commit被后续的commit修改了同一地方则会产生冲突;
- git reset 彻底回退到指定的commit版本,其后的commit会被删除
git log找到commit id,然后git reset <commit_id>,然后git push -f
删除某次提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| # 1. 找到要删除的那个 commit 的**前一个** commit hash(比如 B)
git log --oneline
# 2. 启动交互式 rebase
git rebase -i <commit-B-hash>
# 或者用相对位置,比如删除倒数第 3 个
git rebase -i HEAD~3
#把要删除的那行改成 drop 或直接删掉这一行:
drop c123456 commit C
pick d234567 commit D
pick e345678 commit E
# 保存退出,Git 会自动应用。
# 然后可能会出现:CONFLICT (content): Merge conflict in README.md error: could not apply 6cbbb27... feat:
# 需要解决冲突 1. 查看冲突文件
git status
# 2. 手动编辑冲突文件(删掉 <<< === >>> 标记)
vim README.md
# 3. 标记为已解决
git add README.md
# 4. 继续 rebase
git rebase --continue
# 5. 如果又遇到冲突,重复 2-4
#3. 强制推送到远程
git push origin -f
|
开发流程
- 项目负责人从master的基线check out,初始化dev分支
- 开发者从dev分支check out,建立本地个人开发分支feature*</font>
- 开发者完成功能开发后,commit个人feature分支,并push至远程个人feature分支
- 开发者在gitlab上提交个人的代码和并请求至dev分支
- 代码审查人负责代码审查,合并合理代码
- 代码提测时,开发负责人提交dev分支到test的合并请求
- 项目负责人合并dev分支至test分支
- 版本测试完成后,开发负责人提交test分支至master分支的合并请求
- 项目负责人合并代码至master
- 项目负责人以当前代码为基线,在master分支上tag当前版本号
1
2
3
| git tag -a v1.0.0 -m "Release v1.0.0" # 或 git tag v1.0.0
git push origin v1.0.0
|
紧急修复工作流
1
2
3
4
5
6
7
8
| git checkout master
git checkout -b hotfix/1.2.1
# gerrit切出hotfix/1.2.1分支
# 修复完成
# 合并到master
git push origin HEAD:refs/for/master
# 合并到develop
git push origin HEAD:refs/for/develop
|
版本发布工作流
1
2
3
4
5
6
7
8
9
10
11
12
| # 获取预先规划的版本号,并根据实际更新内容修改版本号
# 确保规划的问题修复和功能开发均已合并到develop
# gerrit上创建release/1.2.0分支
# 全量测试并生成固件
# 软件
# 修 bug、验证
git push origin HEAD:refs/for/master
git tag -a v1.0.0 -m "Release v1.0.0"
git checkout develop
git merge release/1.2.0
git push origin HEAD:refs/for/develop
# 删除release/1.2.0分支
|
主分支同步到功能分支
如果是仅个人的功能分支,推荐用rebase保持干净历史,多人开发的功能分支用merge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 更新development
git checkout development
git pull origin development
# 切回功能分支
git checkout feature-branch
git rebase development
# 如果有冲突
# 解决冲突后
git add .
git rebase --continue
# 强制推送
git push --force-with-lease
|
分支类型

开发分支: feat/xxx(功能)_20200804(创建日期)开发分支基于master创建,开发完成合并到测试develop分支
测试分支:develop 只用来发布测试环境
发布分支:release/vx.x.x(版本号)_20200804(创建日期),基于master创建,验收完成,进行封版后合并回master
缺陷分支:hotfix/xxx(功能)_20200804(创建日期)合并流程和开发分支一致,区别在于,hotfix在测试环境测试通过后直接合到最新的release分支验收
提交规范
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| commit 规范:
feat: ⼀个新特性
fix: 修了⼀个 Bug
docs: 更新了⽂档(⽐如改了 Readme)
style: 代码的样式美化,不涉及到功能修改(⽐如改了缩进,css修改不算)
refactor: ⼀些代码结构上优化,既不是新特性也不是修 Bug(⽐如函数改个名字)
perf: 优化了性能的代码改动
test: 新增或者修改已有的测试代码
chore: 跟仓库主要业务⽆关的构建/⼯程依赖/⼯具等功能改动(⽐如新增⼀个⽂档⽣成⼯具)
操作规范(技巧):
在代码push 前先 pull
遇到代码冲突时,最先考虑取最近commit的版本,若想撤销本次拉取 执行git revert --abort
正在开发发现分支错了,执行 git stash,切换分支后,执行git stash pop
只想合并其他分支的某条commit 记录 执行 git cherry-pick commitId
开发分支新建必须基于干净版本,合并到稳定版本前必须是验收通过的版本
开发分支不能合并其他正在开发或者非干净分支
|
| 提交类型 | 含义 |
|---|
| feat | 新功能(feature) |
| fix | 修复 bug |
| perf | 性能优化 |
| refactor | 重构代码 |
| docs | 文档相关 |
| style | 样式相关 |
| test | 测试相关 |
| chore | 构建过程或辅助工具的变动 |
生成密钥对
1
2
3
4
5
6
7
8
9
10
| ssh-keygen -t ed25519 -C "your_email@example.com"
# 拷贝
## mac
pbcopy < ~/.ssh/id_ed25519.pub
## linux
## win
cat ~/.ssh/id_ed25519.pub | clip
|
GitLab CI/CD
项目根目录下新建.gitlab-ci.yml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# 缓存配置,加快项目的构建速度,减少重复下载
cache:
key: $CI_JOB_NAME-$CI_COMMIT_REF_SLUG # job名称-提交的分支名称
paths:
- ${PIP_CACHE_DIR} # 需要被缓存的文件或文件夹的路径
# 定义pipeline
stages:
- lint
- test
# 定义了2个job
lint_job:
stage: lint # 属于哪个stage
image: python:3.7 # 需要的docker镜像
before_script: # job开始之前执行的脚本
- pip install flake8 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
script: # 执行脚本
- flake8 app
test_job:
stage: test
image: python:3.7
services: # 启动名为 postgres 的服务
- postgres
variables:
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_USER: postgres
POSTGRES_PASS: postgres
POSTGRES_DB: oa_performance_test
POSTGRES_PASSWORD: postgres
before_script:
- pip install -r requirements-test.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
script:
- echo "Test started."
# - coverage run --source app -m pytest tests
# - coverage report
- echo "Test finished."
|
常见问题
fatal: refusing to merge unrelated histories
git merge main –allow-unrelated-histories
pull时提示:your local changes will be overwritten by merge…
先git stash changes,然后pull更新,然后git stash pop
忽略已跟踪的某个文件或目录
git rm –cached /path/file 或
git rm -r –cached logs/