共计 8034 个字符,预计需要花费 21 分钟才能阅读完成。
作者: Escape
起源: https://www.escapelife.site/p…
只有在遇到问题的时候,才领会到技巧带来的益处!
常见企业工作流程
次要介绍,企业中罕用的 Git 工作流程!
Git Flow
- 骨干分支
- 稳固分支
- 开发分支
- 补丁分支
- 批改分支
Github Flow
- 创立分支
- 增加提交
- 提交 PR 申请
- 探讨和评估代码
- 部署检测
- 合并代码
Gitlab Flow
- 带生产分支
- 带环境分支
- 带公布分支
日常应用最佳实际
总结日常工作中应该遵循的 Git 应用形式和办法!
- 应用命令行代替图形化界面
-
- 应用命令行来操作,简洁且效率高
- 提交应该尽可能的表述提交批改内容
-
- 辨别 subject 和 body 内容,应用空行隔开
- subject 个别不超过 50 个字符
- body 每一行的长度管制在 72 个字符
- subject 结尾不须要应用句号或者点号结尾
- body 用来具体解释此次提交具体做了什么
- 应用 .gitignore 文件来排除无用文件
-
- 可应用模板文件,而后依据我的项目理论进行批改
- 基于分支或 fork 的开发模式
-
- 不要间接在骨干分支下面进行开发
- 在新建的分支上进行性能的开发和问题的修复
- 应用 release 分支和 tag 标记进行版本治理
-
- 应用 release 分支公布代码和版本保护 (release/1.32)
- 应用 tag 来标记版本 (A- 大 feature 性能.B- 小 feature 性能.C- 只修 bug)
常用命令汇总整顿
日常应用只有记住 6 个命令就能够了。
# 工作区 -> 暂存区 $ git add <file/dir># 暂存区 -> 本地仓库 $ git commit -m "some info"# 本地仓库 -> 近程仓库 $ git push origin master # 本地 master 分支推送到近程 origin 仓库
# 工作区 <- 暂存区
$ git checkout -- <file> # 暂存区文件内容笼罩工作区文件内容
# 暂存区 <- 本地仓库
$ git reset HEAD <file> # 本地仓库文件内容笼罩暂存区文件内容
# 本地仓库 <- 近程仓库
$ git clone <git_url> # 克隆近程仓库
$ git fetch upstream master # 拉取近程代码到本地但不利用在以后分支
$ git pull upstream master # 拉取近程代码到本地但利用在以后分支
$ git pull --rebase upstream master # 如果平时应用 rebase 合并代码则加上
# 工作区 <- 本地仓库
$ git reset <commit> # 本地仓库笼罩到工作区 (保留回退文件内容批改)
$ git reset --mixed <commit> # 本地仓库笼罩到工作区 (保留回退文件内容批改)
$ git reset --soft <commit> # 本地仓库笼罩到工作区 (保留批改并加到暂存区)
$ git reset --hard <commit> # 本地仓库笼罩到工作区 (不保留批改间接删除掉)
配置实用参数选项
尽管配置比较简单,然而十分有用!
全局配置
# 用户信息
$ git config --global user.name "your_name"
$ git config --global user.email "your_email"
# 文本编辑器
$ git config --global core.editor "nvim"
# 分页器
$ git config --global core.pager "more"
# 别名
$ git config --global alias.gs "git status"
# 纠错
$ git config --global help.autocorrect 1
集体配置
# 不加 --global 参数的话,则为集体配置
$ git config --list
$ git config user.name
$ git config user.name "your_name"
# 如果在我的项目中设置,则保留在.git/config 文件外面
$ cat .git/config
[user]
name = "your_name"
......
合并和变基的抉择
到底什么时候应用 merge 操作,什么时候应用 rebase 操作呢?
应用 merge 操作 – Python 中的 Requests 库在应用
反对应用 merge 的开发者,他们认为仓库的提交历史就是记录理论产生过什么,它是针对于历史的一个文档,自身其实是有价值的,咱们不应该随便批改。咱们扭转历史的话,就相当于应用“谎话”来覆盖理论产生过的事件,而这些痕迹是应该被保留的。可能,这样并不是很好。
# 3rd 的两个分支的 commit 批改雷同内容
* 62a322d - (HEAD->master) Merge branch 'hotfix3' into master
|\
| * 6fa8f4a - (hotfix3) 3rd commit in hotfix3
* | 548d681 - 3rd commit in master
|/
* 6ba4a08 - 2nd commit
* 22afcc1 - 1st commit
应用 rebase 操作 – Python 中的 Django 库在应用
反对应用 rebase 的开发者,他们认为提交历史是我的项目过程中产生过的事件,须要我的项目的骨干十分的洁净。而应用 merge 操作会生成一个 merge 的 commit 对象,让提交历史多了一些十分多余的内容。
当咱们前期,应用 log 命令参看提交历史的话,会发现骨干的提交历史十分的难堪。比方,同样的批改内容反复提交了两次,这显然是分支合并导致的问题。
# 3rd 的两个分支的 commit 批改雷同内容
* 697167e - (HEAD -> master, hotfix) 3rd commit
* 6ba4a08 - 2nd commit (2 minutes ago)
* 22afcc1 - 1st commit (3 minutes ago)
两者的应用准则
总的准则就是,只对尚未推送或分享给其他人的本地批改执行变基操作清理历史,从不对曾经推送到仓库的提交记录执行变基操作,这样,你才可能享受到两种形式带来的便当。
更新仓库提交历史
Git 提供了一些工具,能够帮忙咱们欠缺版本库中的提交内容,比方:
合并多个 commit 提交记录
日常开发中,咱们为了实现一个性能或者个性,提交很多个 commit 记录。然而在最初,提交 PR 之前,个别状况下,咱们是应该整顿下这些提交记录的。有些 commit 须要合并起来,或者须要将其删除掉,等等。
# 调整最近五次的提交记录
$ git rebase -i HEAD~5
$ git rebase -i 5af4zd35 # 往前第六次的 commit 值
reword c2aeb6e 3rd commit
squash 25a3122 4th commit
pick 5d36f1d 5th commit
fixup bd5d32f 6th commit
drop 581e96d 7th commit
# 查看提交历史记录
$ git log
* ce813eb - (HEAD -> master) 5th commit
* aa2f043 - 3rd commit -> modified
* 6c5418f - 2nd commit
* c8f7dea - 1st commit
删除意外调试的测试代码
有时候提交之后,咱们才发现提交的历史记录中存在这一些问题,而这个时候咱们又不想新生成一个 commit 记录,且达到一个批改的目录。即,批改之前的 commit 提交记录。
# 不应用分页器
$ git --no-pager log --oneline -1
d5e96d9 (HEAD -> master) say file
# 扭转提交信息并退出暂存区
$ echo "hello" > say.txt
$ git add -u
# 扭转以后最新一次提交记录
$ git commit --amend
# 扭转且息不扭转提交信
$ git commit --amend --no-edit
# 扭转以后最新一次提交记录并批改信息
$ git commit --amend -m "some_info"
# 不应用分页器
$ git --no-pager log --oneline -1
9e1e0eb (HEAD -> master) say file
勾销多个 commit 中的局部提交
咱们开发了一个性能,而在上线的时候,产品经理说这个性能的局部个性曾经不须要了,即相干个性的提交记录和内容就能够疏忽 / 删除掉了。
# 回滚操作 (可屡次执行回滚操作)
# 彻底上次提交记录;也可是 PR 的提交记录
# 默认会生成一个类型为 reverts 的新 commit 对象
$ git revert 3zj5sldl
[4] 合并某些特定的 commit 提交
咱们不心愿合并整个分支,而是须要合并该分支的某些提交记录就能够了。bash
# 摘樱桃
$ git cherry-pick -x z562e23d
应用援用日志记录
如何找回咱们失落的内容和记录?
咱们之前说过,应用上面命令回退内容、强制推送代码、删除本地分支,都是十分危险的操作,因为重置之后咱们就没有方法在找到之前的批改内容了。
# 回退
$ git reset --hard <commit>
# 推送
$ git push origin master -f
# 分支
$ git branch -D <branch_name>
其实 Git 给咱们留了一个后门,就是应用 relflog 命令来找回之前的内容,只不过是相对来说麻烦一些。而原理也很简答,就是在咱们应用 Git 命令操作仓库的时候,Git 偷偷地帮忙咱们把所有的操作记录了下来。
# 查看日志记录
$ git --no-pager log --oneline -1
4bc8703 (HEAD -> master) hhhh
# 回退到上次提交
$ git reset --hard HEAD~1
# 查看援用日志记录
$ git reflog
6a89f1b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1
4bc8703 HEAD@{1}: commit (amend): hhhh
# 找回内容
$ git cherry-pick 4bc8703
批量批改历史提交
批量批改历史提交尽管不罕用,然而了解的话能够省下很多工夫!
之前咱们学习到的命令都是针对于一个或者多个 commit 提交信息进行批改的,如果咱们须要全局批改历史提交呢?当然,Git 中也是反对全局批改历史提交的,比方全局批改邮箱地址,或者将一个文件从全局历史中删除或批改。
- 开源我的项目中应用了公司邮箱进行提交了
- 提交文件中蕴含隐衷性的明码相干信息
- 提交时将大文件提交到了仓库代码中了
这里咱们能够应用 filter-brach 的形式进行批改,然而倡议在应用之前,新建一个分支,在下面进行测试没有问题之后,再在骨干上操作,防止出现问题,背个大锅在身上。
# 创立分支
$ git branch -b testing
# 批改邮箱地址
$ git filter-branch --commit-filter 'if ["$GIT_AUTHOR_EMAIL"=="escape@escapelife.site"]; then
GIT_AUTHOR_NAME="escape";
GIT_AUTHOR_EMAIL="escape@gmail.com";
git commit-tree "$@"
else
git commit-tree "$@"
fi' HEAD
灵便应用钩子函数
次要介绍.git/hooks 目录上面的示例钩子函数!
在 Git 外面有两类,别离对应客户端和服务端钩子函数。客户端的钩子函数,是在执行提交和合并之类的操作时调用的。而服务端钩子函数,就是当服务端收到代码提交之后,能够登程代码检查和继续集成的步骤。作为开发者咱们并不会搭建 Git 服务器,所以根本不会波及。
上面就是 Git 自带的钩子脚本,然而自带的都以 .sample 作为后缀,示意并没有启用,示意为一个示例。如果须要启用的话,将 .sample 作为后缀删除掉,即可。而其钩子脚本的对应内容,都是应用 Shell 语法进行编写的。
➜ ll .git/hooks
total 112
-rwxr-xr-x applypatch-msg.sample
-rwxr-xr-x commit-msg.sample
-rwxr-xr-x fsmonitor-watchman.sample
-rwxr-xr-x post-update.sample
-rwxr-xr-x pre-applypatch.sample
-rwxr-xr-x pre-commit.sample
-rwxr-xr-x pre-merge-commit.sample
-rwxr-xr-x pre-push.sample # 不会推送蕴含 WIP 的 commit 提交
-rwxr-xr-x pre-rebase.sample
-rwxr-xr-x pre-receive.sample
-rwxr-xr-x prepare-commit-msg.sample
-rwxr-xr-x update.sample
其实,钩子脚本应用任何语言编写都是能够的,只有你让程序返回对应的退出码就能够了。
失常的代码合入流程就是,咱们本地批改之后,提一个 PR 申请并通过 Github 的 CI 查看,接下来进行代码评审,最初被合并入主干。然而,好的一个习惯就是,在代码提交之前就应该保障代码不会呈现语法错误等根底问题,比方通过 flake8 和 PEP8 规范等。
这个时候咱们就能够应用 pre-commit 这个 Github 的开源我的项目了,其本质就是给我的项目增加钩子函数的一个脚本,能够保障咱们在提交代码或者推送代码之前,先查看代码的品质。
而 pre-commit-hooks 这个我的项目外面蕴含的就是,当初所反对的钩子脚本,即开箱即用的钩子脚本汇合。而其钩子脚本的对应内容,都是应用 Python 语法进行编写的。
# 装置形式
$ pip install pre-commit
# 指定 hook 类型 (即在哪里查看)
$ pre-commit install -f --hook-type pre-push
# 配置须要执行的查看
$ cat .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.9.2
hooks:
- id: trailing-whitespace
- id: flake8
# 执行 push 操作时查看
$ git push origin master
疾速克隆大型项目
在大我的项目中工作中,拉取代码十分占工夫!
咱们如果想为 Linux 或 Python 这样的大型项目奉献提交的时候,首先遇到的问题就是,如果疾速的 clone 该我的项目到本地。因为改我的项目提交历史超多且仓库微小,加了国内网络的问题,可能等我的项目齐全拉下来的时候,咱们的激情都消减上来了。
好在 Git 也帮咱们想到了这样的问题,咱们能够应用 –depth 参数值拉取近程仓库下面最新一次的提交历史,并不蕴含我的项目历史记录,即 .git/objects/ 目录下的对象只是本地的,并不蕴含之前的屡次批改产生的对象。
# 克隆不蕴含之前历史
$ git clone http://xxx.xx.xxx/xxx --depth=1
然而,有工夫咱们可能会须要 clone 仓库中的某个 tag 版本对应下的内容。如果咱们间接应用 clone 命令是无奈做到的,须要执行如下操作,即可完满解决。# 克隆特定版本代码
$ git init xxx-15-0-1
$ git remote add origin http://xxx.xx.xxx/xxx
$ git -c protocol.version=2 fetch origin 15.0.1 --depth=1
$ git checkout FETCH_HEAD
下面的成果曾经根本能够满足咱们日常应用需要了,然而可怜的是,你当初承受了一个机器学习的我的项目,外面蕴含了大量的 lfs 文件,当初 clone 又会变得十分慢。能够应用如下操作来防止,Git 工具被动拉去 lfs 文件,来达到目录。
# 克隆不蕴含 LFS 数据
$ GIT_LFS_SKIP_SMUDGE=1 git clone http://xxx.xx.xxx/xxx
如何解决工作中断
如果在多路运行的时候,还可能高效的进行开发!
比方,咱们当初正在一个分支为我的项目增加一个小的性能,此时,产品经理找到你说是线上环境当初有一个 bug 须要让你来修复下。然而,此时咱们增加的小性能并没有实现。
如果此时,咱们间接切换到骨干分支的话,会将之前分支没有来得及提交的内容全副都带到了骨干分支上来,这是咱们不想看到的状况。此时,咱们须要保留上个分支的工作状态,在咱们批改实现线上 bug 之后,再持续工作。
好在 Git 也帮咱们想到了这样的问题,咱们能够应用 stash 子命令帮忙咱们将当前工作区、暂存区当中的批改都保留到堆栈之中。等到须要解决的时候,再弹出堆栈中的内容,咱们再次进行开发。
➜ git stash -h
usage: git stash list [<options>]
or: git stash show [<options>] [<stash>]
or: git stash drop [-q|--quiet] [<stash>]
or: git stash (pop | apply) [--index] [-q|--quiet] [<stash>]
or: git stash branch <branchname> [<stash>]
or: git stash clear
or: git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
[--pathspec-from-file=<file> [--pathspec-file-nul]]
[--] [<pathspec>...]]
or: git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
[-u|--include-untracked] [-a|--all] [<message>]
# 存储以后的批改但不必提交 commit
$ git stash
# 保留以后状态包含 untracked 的文件
$ git stash -u
# 展现所有 stashes 信息
$ git stash list
# 回到某个 stash 状态
$ git stash apply <stash@{n}>
# 删除储备区
$ git stash drop <stash@{n}>
# 回到最初一个 stash 的状态并删除这个 stash 信息
$ git stash pop
# 删除所有的 stash 信息
$ git stash clear
# 从 stash 中拿出某个文件的批改
$ git checkout <stash@{n}> -- <file-path>
其实比拟保险的做法就是,将以后的所有批改进行 push 并保留到近程仓库外面。这样的益处在于,能够远端备份咱们的批改,不会胆怯本地文件失落等问题。等到咱们须要持续开发的时候,拉下对应内容,再想方法进行补救,比方应用 –amend 或者 reset 命令。
# 将工作区和暂存区笼罩最近一次提交
$ git commit --amend
$ git commit --amend -m "some_info"
# 回退到指定版本并记录批改内容 (--mixed)
# 本地仓库笼罩到工作区 (保留回退文件内容批改)
$ git reset a87f328
$ git reset HEAD~
$ git reset HEAD~2
$ git reset <tag>~2
$ git reset --mixed <commit/reference>
# 本地仓库笼罩到工作区 (不保留批改间接删除掉)
$ git reset --soft <commit/reference>
# 本地仓库笼罩到工作区 (保留批改并加到暂存区)
$ git reset --hard <commit/reference>
近期热文举荐:
1.600+ 道 Java 面试题及答案整顿 (2021 最新版)
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!