招聘时间
咳咳,在进入正题之前,发一个团队的招聘小广告:
想要参与万亿级别的项目吗?想要跟来自海内外大厂、顶尖高校的大佬们做同事吗?想要和字节一同跳动吗?
欢迎加入抖音电商前端团队,在这里你能够接触到业内前沿的前端技术,找到自己感兴趣的方向进行深研,和公司、团队一同生长。
假设感兴趣的话,欢迎点击岗位信息 进行投递~
等待你的加入~
一、背景
git 是一个分布式版别控制软件,开始由林纳斯托瓦兹创造,于 2005 年以 GPL 发布。开始意图是为更好地办理 Linux 内核开发而规划。
Git 有许多优势,现在是许多团队(当然也包括作者的团队)仅有运用的代码版别控制软件,为了让大家更加方便、标准地运用 Git,本文收拾了作者的团队的 Git 标准、常见场景实践、留意事项、常见问题。
二、强制标准
My-Git Flow 工作流
- 有且仅有
master
分支用于出产环境的布置,一切布置出产环境的 SCM 包分支来历必须是master
-
master
是受维护的分支,任何人都不能推送代码至master
- 任何新改动都需求从
master
派生出一个分支,并且为其起一个描绘新改动内容的姓名:比方 feat/2198234-add-error-boundary
- 在本地提交该新分支改动,并且应常常性的向服务器端该同名分支推送改动
- 在新分支能够兼并(即需求完成测试即将上线)的时分,新建一个
merge request
- 只有在其他人 review 通过之后,新分支才允许兼并到
master
分支
分支办理
分支命名
分支命名应该遵从尽量语义化,假设有相关的 meego,尽量在分支命名中体现出来。
// Good cases
feat/2198234-add-error-boundary
fix/api-error-message
// Bad cases
text
hotfix-xiaowang
dev-xiaowang
Commit 标准
Commit Message
Commit Message 应遵从 Conventional commits 标准。
团队的项目中应该接入 Commitizen 和 Commitlint 来对 commit message 进行标准和校验。
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
全体格式阐明:
- Commit message 都包括三个部分:Header,Body 和 Footer。
- 其间,Header 是必需的,Body 和 Footer 能够省略。
- Header,Body 和 Footer 之前用空行分隔。
- 每一行内容长度都不能超越100个字符。
# header: <type>(<scope>): <subject>,100-character line
# - type: feat, fix, docs, style, refactor, test, chore
# - scope: can be empty (eg. if the change is a global or difficult to assign to a single component)
# - subject: start with verb (such as 'change')
#
# body: 100-character wrapped. This should answer:
# * Why was this change necessary?
# * How does it address the problem?
# * Are there any side effects?
#
# footer: reserved field
# - BREAKING CHANGE: description
# - Closes #123, #245, #992
type(必需)
type 用来阐明 commit 的类别,只允许运用下面的标识:
Changelog 装备参阅:假设 type 为 feat 和 fix ,则该 commit 信息将必定呈现在 change log 之中。其他情况(
docs
、chore
、style
、refactor
、test
)再定,主张是不要。
feat: A new feature
fix: A bug fix(code、UI)
docs: Documentation only changes
perf: A code change that improves performance
refactor: A code change that neither fixes a bug nor adds a feature
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
test: Adding missing tests or correcting existing tests
build: Changes that affect the build system or external dependencies
ci: Changes to our CI configuration files and scripts
chore : Other changes that don't modify src or test files
revert: Reverts a previous commit. If the commit reverts a previous commit, it should begin with revert: , followed by the header of the reverted commit. In the body it should say: This reverts commit <hash>., where the hash is the SHA of the commit being reverted.
scope(可选)
scope 用于阐明 commit 影响的规模,比方影响哪个模块或者功用等。推荐按功用描绘。
subject(必需)
subject 是关于 commit 信息的简略描绘。
Commit message 示例
// good case
feat(页面A): 新增 B 模块
- 添加一致的面包屑布局
- 抽象公共 ProTable 组件,封装了挑选栏、分页器、数据获取
- 晋级 antd 组件库版别号至 2.9.0
// bad case
fix: xiaowang
chore: 修正案牍
fix: 修正线上问题
Commit 原子性
倡议最小粒度 commit 准则,准则上每个独立的改动对应一个 commit。
为了更好的盯梢提交前史以及回溯,要保证 commit 的“原子性”,每个 commit 要以适当的粒度包括且仅包括“单项”改动,防止过多的暂时 commit;提交代码时应该让每个 commit 都更具有意义,而不是散乱随意的 commit。
判别准则参阅:commit 粒度尽量小,且只提交该单个 commit 时功用能够正常运转。
Squash Commits
基于 commit 原子性准则,应防止将过于零星的 commit 提交兼并到骨干分支。对于需求或者功用的 commit,尤其是在协作开发时,假设 commit 过于暂时或零星,应整组成一个 commit 再提交到骨干,保证骨干前史简练有用。
squash commits 能有用削减 rebase 方法兼并时的抵触,能简化处理抵触的过程;频繁暂时的 commit 导致多个无意义提交,简略引起他人困惑。
留意:现已兼并到骨干的 commit,不能进行 squash,改动骨干(协作)分支前史会导致其他人无法正常同步。
暂时 commits 的处理方案
假设你的工作常常被打断,导致呈现许多暂时的 commits,那么你或许需求善用 git stash
技巧。
三、操作主张
Rebase vs Merge
关于 Rebase 和 Merge 的评论,能够参阅这篇文章。
异同总结
- Rebase 和 Merge 都能够用来兼并不同分支的 commits
- Merge 能够坚持修正内容的前史记载,可是前史记载会很杂乱,关注点在于实在的操作记载
- Rebase 前史记载简略(线性),是在原有提交的基础大将差异内容反映进去
Merge | Rebase |
---|---|
推荐操作
- 兼并 master 分支的最新代码至本地分支,请运用 git rebase master
- 将本地代码合入公共分支,请运用 merge(提交 merge request)
四、Git 装备及东西
必要的大局装备
git config --global user.name [YOUR_NAME]
git config --global user.email [YOUR_EMAIL]
git config --global core.ignorecase false
依照自己的习气和喜爱的装备
git config --global push.default current
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.rb rebase
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
设置 Git 的 SSH-Keys
- 访问个人主页的 SSH Keys 设置页面
-
在本地生成 SSH 公钥
- 先承认是否已有 SSH 公钥(默许情况下,用户的 SSH 密钥存储在其
~/.ssh
目录下。 进入该目录并列出其间内容,你便能够快速承认自己是否已具有密钥) -
ls ~/.ssh // 假设有 id_rsa、id_rsa.pub 这两个文件,则已存在 SSH 公钥,将 id_rsa.pub 的内容拷贝至 SSH Keys 设置页面即可 // windows 上是 id_ecdsa 和 id_ecdsa.pub 文件
- 假设上一步没找到 SSH 公钥,则手动生成
-
ssh-keygen // 这个指令会问询生成的位置、密钥口令等,直接默许就行 // windows 上:ssh-keygen -t ecdsa -C "xxxxxx@bytedance.com"
- 拷贝公钥至 SSH Keys 的设置页面
-
cat ~/.ssh/id_rsa.pub // 形如下: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3 Pbv7kOdJMTasjhfashjfgasjhfgahsjfgashjfgahjsgashjfgahjsfgaahfjsasfhj=@mylaptop.local
- 先承认是否已有 SSH 公钥(默许情况下,用户的 SSH 密钥存储在其
装置 Git Commit 指令行东西 —— Commitizen
yarn global add commitizen cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
运用效果
VSCode 插件
GitLens —— 检查 Git 提交记载,找到代码的提交者
Git 可视化东西
- SourceTree
直接用指令行检查 git 的 diff 是非常高效的,并且也非常契合高端程序员的气质,可是需求记住的指令也是非常多。作为一个懒惰的程序员,咱们就需求一些可视化东西来辅佐咱们检查 diff 和处理抵触。SourceTree 是一个界面美丽、功用强大且免费的东西。请留意,SourceTree 应该是一个辅佐东西,它协助咱们更方便检查代码,咱们不应该依靠它去提交代码。
- VSCode 内置东西
- Git-Fork
- Gitkraken
- Tower
五、常见场景
接下来,让咱们看一些工作中运用 Git 常见的场景。
基本场景:
新拉取项目
git clone git@code.byted.org:XXX/XXXX.git
新建分支
// 从当时分支新建
git checkout -b NEW_BRANCH_NAME
// 基于远端分支新建分支
git checkout -b NEW_BRANCH_NAME origin/REMOTE_BRANCH_NAME(长途分支称号)
推送代码至远端分支
git push origin REMOTE_BRANCH_NAME
拉取远端改动
// 拉取远端一切改动
git fetch
// 把长途分支上的内容都拉取到本地
git pull origin REMOTE_BRANCH_NAME [--rebase]
兼并长途分支到本地
常见于长途的 master 或其他分支有改动,并且这部分改动需求合入当时分支。(此处以 master 为例)
git checkout master
git pull --rebase
git checkout YOUR_BRANCH
git rebase master (此处也能够运用 merge)
// rebase 之后,将代码 push 到远端,因为此处改动了当时分支的提交前史,因此或许需求 --force-with-lease
git push origin YOUR_BRANCH --force-with-lease
兼并分支到 master
-
在 gitlab 上手动提交 MergeRequest
-
在他人 Approve 之后,点击 merge 合入 master(主张勾选 「Squash commits」)
暂存及康复修正(stash)
常见于暂时切换分支,且不想放弃或提交当时的修正。
// 将当时修正放入暂存区,能够在 save 之后加入暂存的信息
git stash [save][message]
// 检查当时暂存区清单
git stash list
// 康复暂存区的修正,仅运用"git stash pop" 将康复到最新的操作。指定stash ID (如:stash@{1} ),则能够康复特定的操作。
git stash pop [ID]
// 删去暂存的操作, 假设运用 "git stash drop",会删去最新的操作。指定stash ID (如:stash@{1} ),则能够删去特定的操作。
git stash drop [ID]
装备长途目录
git remote add origin git@code.byted.org:xxx/XXX.git
新建项目
// 1. 新建 .git 文件
git init
// 2. 装备长途目录
git remote add origin git@code.byted.org:xxx/XXX.git
// 3. 推送文件至远端的 master 分支(完成后需求去远端设置 master 为受维护分支)
git push -u origin master
\
杂乱场景
紧缩(兼并)提交
常见于本地分支有多次 commits,其间全部或部分 commits 能够兼并为一次有语义的 commit
// 1. 利用 rebase -i 兼并 commits,其间的 COMMIT_HASH 是需求兼并的 commits 的鸿沟(不包括)
git rebase -i COMMIT_HASH
// 2. 在 vim 界面修正需求保存和 squash 的 commits,能够紧缩修正成 s
紧缩前的 git log 信息:
假设咱们想兼并 e75a64c ~ cc21dbe 这部分提交:
git rebase -i 2701084
修正需求保存的 commit 信息
兼并后的 git log 信息
处理抵触
处理抵触常见于在本地 rebase 或 merge master 的改动,此处以 rebase master 为例:
// 为了削减处理抵触的次数,主张本地先 squash commits(通过上面的兼并提交)
git rebase -i COMMIT_HASH
// rebase master 的改动
git rebase master
// 手动处理抵触
// 处理完抵触之后,继续 rebase
git add .
git rebase --continue
留意:处理抵触遇到困难时(比方不知道该选用谁的提交),主张直接找到代码的提交者,当面处理。
// 暂停当时的兼并操作
git rebase --abort
Revert 代码
通常情况下,代码合入 master 分支的时机是在上线前。因为误操作、提早合入后被告知无法发布等原因导致代码被误合入 master,为了防止影响后续上线同学和线上环境,咱们或许需求及时 revert 现已合入 master 的代码。
Revert 的原理就是提交一个逆向 commit,对之前的 commits 进行 undo 操作,而不是抹除之前的 commits 在 git 中的记载。
- 进入需求 revert 的 merge request 链接,直接点击 Revert 按钮。
- 如平常提交 Merge Request 相同,在这里提交 revert 信息
刚刚的 revert 操作帮咱们做了三件事:
- 生成新分支:revert-COMMIT_HASH
- 提交 undo 的 commit 「fix: revert “Merge branch ‘chore/competitor-shop’ into ‘master'”」
- 提交 merge request
- 咱们能够在新生成的 revert-COMMIT_HASH 上进行修正操作,也能够在他人 Approve 之后将 merge request 合入 master,合入 master 之后,本次 revert 操作就大功告成了。
- 康复 revert:通过上面的操作后,咱们的代码现已从 master 分支上消失了,可是咱们的提交记载还在 master 分支上。假设此刻再从本来的分支提交 merge request,你会发现 「0 file changed」。假设想从头找回之前修正的代码,此刻需求对 revert 进行 revert, 原因见这篇文章。步骤同上。
吊销提交
// 吊销最近一次提交,并保存代码,吊销 add 的状态
git reset --mixed HEAD~1
// 吊销最近一次提交,并保存代码,保存 add 的状态
git reset --soft HEAD~1
// 吊销最近一次提交,并删去代码
git reset --hard HEAD~1
修正提交
景象一:重写最近的提交音讯
git commit --amend
景象二:修正旧提交或者多个提交的音讯,运用 rebase -i(类似于兼并提交)
git rebase -i COMMIT_HASH
此列表将类似于以下内容:
pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.
# Rebase 9fdb3bd..f7fde4a onto 9fdb3bd
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
在要更改的每个提交音讯的前面,用 reword
替换 pick
。
pick e499d89 chore: Delete CNAME
reword 0c39034 fix: Better README
reword f7fde4a feat: Change the commit message but push the same commit.
多人协作
假设有一个功用需求多个人协同开发,请运用一个约好的公共分支随时同步你们的代码,以免抵触并且方便联调。且应该像对待 master 相同对待你们的公共分支(即不能直接推送代码至公共分支)。假设有 A,B 两个人一同开发一个新功用叫 achievement
:
初始化本地分支
在 A 的电脑上:
git checkout master
git pull --rebase
git checkout -b feat/achievement
git push
git checkout -b feat/achievement-a
在 B 的电脑上:
git fetch
git checkout feat/achievement
git checkout -b feat/achievement-b
A 和 B 需求常常更新代码至远端,并合入公共分支
在 A 这边:
// on branch feat/achievement-a
git checkout feat/achievement
git pull --rebase
git checkout feat/achievement-a
git rebase feat/achievement // 或许要处理抵触
git push
// 提交 merge request,将 feat/achievement-a 的提交合入公共分支
在 B 这边:
// on branch feat/achievement-b
git checkout feat/achievement
git pull --rebase
git checkout feat/achievement-b
git rebase feat/achievement //或许要处理抵触
git push
// 提交 merge request,将 feat/achievement-b 的提交合入公共分支
协作开发的时分抵触是非常常见的。不要惧怕抵触,应该尽早处理抵触。养成频繁 rebase
,频繁更新公共分支的习气。
六、留意事项
切换 git 账号的 SSH-Key
实现方法参阅这篇文章。
在公司电脑上进行这样的操作非常危险,强烈主张不要在公司的电脑上进行自己的 github 开发!!!
七、常见问题
此处收拾一些运用 Git 时的常见问题:
未初始化 git
场景复原:fatal: not a git repository (or any of the parent directories): .git
报错原因:未初始化 git(没有 .git 目录)
处理方案:git init
未相关长途分支
场景复原:git push 时报错——fatal: The current branch xxx has no upstream branch.
报错原因:未相关长途分支
处理方案:git push --set-upstream origin xxx
落后长途分支
场景复原:git push 时报错——pdates were rejected because the tip of your current branch is behind its remote counterpart
报错原因:当时分支落后于长途分支
处理方案:需求先拉取远端的更新,再进行 push
git pull --rebase origin YOUR_BRANCH
git push origin YOUR_BRANCH