0x001 概述
一个优秀的前端工程师,必先是个优秀的工程师;一个优秀的工程师,要为自己写的每一行代码负责,要为自己提交的每一个 commit 负责。话虽这么说,但是不想写一篇十分大而全的文章,就想写一些小东西。
0x002 撤销 git add
我们知道,要提交一个 commit,必须要先 add,那如果把一些不想要 add 的东西 add 进去了,该咋办?下面提供几个场景和解决方案:
场景1:添加某个误创建文件,这个文件是不想要的
- 环境:误创建了一个 new.txt,并使用 add
$ echo new > new.txt
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: new.txt # 👈
- 解决方案:直接删除就好了
$ rm new.txt
$ git add .
$ git status
On branch master
nothing to commit, working tree clean # 👈
场景 2:新建了一个组件,但是不希望在这次 commit 中一起提交
- 环境:创建了一个 Product 组件,但是这个组件不在当前使用,本次的修改只应该包含一个 index.js
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Product/index.css # 👈 多余
new file: Product/index.js # 👈 多余
new file: index.js
- 解决方案 1:使用
git rm
移除,-r
表示文件夹递归,--cache
表示从index
移除,working tree
还保留着
$ git rm -r --cache Product/
rm 'Product/index.css'
rm 'Product/index.js'
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: index.js # 👈 index 只剩下一个文件了
Untracked files:
(use "git add <file>..." to include in what will be committed)
Product/ # 👈但是 working tree 还有
$ git commit -m 'feat: index'
\[master 3bf1398\] feat: index
1 file changed, 1 insertion(+)
create mode 100644 index.js
- 解决方案 2:使用
git stash
将Product
组件先暂存,提交index.js
,再放出Product
- 暂存
Product
$ git stash -- Product
Saved working directory and index state WIP on master: b426e7e feat: initial
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: index.js # 👈 只剩下一个文件了
- 提交 index.js
$ git commit -m 'feat: index'
\[master 3bf1398\] feat: index
1 file changed, 1 insertion(+)
create mode 100644 index.js
- 取出 stash 中的
Product
$ git stash pop
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Product/index.css # 👈 又拿出来了
new file: Product/index.js # 👈 又拿出来了
Dropped refs/stash@{0} (28675d4accc329da3e54b0a839967471f21c7102)
- 作为独立
commit
提交
$ git commit -m "feat: product"
\[master de42d60\] feat: product
2 files changed, 2 insertions(+)
create mode 100644 Product/index.css
create mode 100644 Product/index.js
0x003 撤销不想要的修改
场景1:修改了某个文件,但是又不想要其中一些或者全部
- 环境
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Product/index.js # 👈 不想要
modified: index.js # 👈 不想要
- 解决方案1:
git stash
,然后就不用管它了,适用于全部抛弃或者部分
$ git stash -- Product/index.js
Saved working directory and index state WIP on master: de42d60 feat: product
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: index.js # 👈 只剩下这个了
no changes added to commit (use "git add" and/or "git commit -a")
- 解决方案2:
git reset
,适用于当前全部修改都不要了
$ git reset --hard HEAD
HEAD is now at de42d60 feat: product
$ git status
On branch master
nothing to commit, working tree clean # 👈 全没了
- 解决方案3:
git checkout
,适用于部分抛弃
$ git checkout -- Product/index.js
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: index.js # 👈 只剩下这个了
no changes added to commit (use "git add" and/or "git commit -a")
0x004 撤销/修改 git commit
场景1:commit 已经提交,但是 commit message 有错误
- 场景展示
$ git add .
$ git commit -m 'feat: 错误的 message'
\[master ed31f58\] feat: 错误的 message # 👈
2 files changed, 2 insertions(+), 2 deletions(-)
- 解决方案:git commit --amend
$ git commit --amend -m 'feat: 正确的 message'
\[master 325e290\] feat: 正确的 message # 👈
Date: Tue May 26 12:39:07 2020 +0800
2 files changed, 2 insertions(+), 2 deletions(-)
场景2:commit 已经提交,但是有文件遗漏了
场景展示:
- 查看状态,当前有两个文件被修改
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: Product/index.js # 👈 修改
modified: index.js # 👈 修改
- 只提交一个文件
$ git add Product/index.js # 👈 提交一个
$ git commit -m 'feat: 完成产品功能'
\[master 8f3f605\] feat: 完成产品功能
1 file changed, 1 insertion(+), 1 deletion(-)
- 查看状态,还有一个文件还没提交
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: index.js # 👈 剩余一个
解决方案1:git commit --amend
$ git add .
$ git commit --amend -m 'feat: 完成 产品功能' # 👈 提交
\[master 1ae5752\] feat: 完成 产品功能
Date: Tue May 26 12:49:00 2020 +0800
2 files changed, 2 insertions(+), 2 deletions(-)
$ git status
On branch master
nothing to commit, working tree clean # 👈 全提交了
解决方案2:git reset --soft HEAD^
$ git reset head^
Unstaged changes after reset:
M Product/index.js # 👈 上次提交的又回来了
$ git add .
$ git commit -m 'feat: 完成 产品功能' # 👈 再次提交
\[master 1ae5752\] feat: 完成 产品功能
Date: Tue May 26 12:49:00 2020 +0800
2 files changed, 2 insertions(+), 2 deletions(-)
场景3:commit 已经提交了,但是多了一些文件
- 场景展示:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Product/index.css
new file: Product/index.js
modified: index.js
# 原本只想提交 Product 相关文件,但是误把 index.js 提交了
$ git add .
$ git commit -m 'feat: 完成 Product 组件'
\[master 6c0f3c8\] feat: 完成 Product 组件
3 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 Product/index.css
create mode 100644 Product/index.js
解决方案1: git reset head^ 之后重新提交
$ git reset head^
Unstaged changes after reset:
M index.js
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: index.js # 👈 提交的又回来了
Untracked files:
(use "git add <file>..." to include in what will be committed)
Product/ # 👈 提交的又回来了
no changes added to commit (use "git add" and/or "git commit -a")
$ git add Product/\* # 👈 只提交 Product
$ git commit -m 'feat: 完成 Product 组件'
\[master 9b9d085\] feat: 完成 Product 组件
2 files changed, 2 insertions(+)
create mode 100644 Product/index.css
create mode 100644 Product/index.js
0x005 删除一个 commit(最新的一个)
有时候我们不想要一个 commit 了怎么办,这里提供几个解决方案
- 场景展示:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: index.js
$ git commit -m 'feat: 不想要的提交'
\[master aa47ff2\] feat: 不想要的提交
1 file changed, 1 insertion(+)
$ git log --pretty=oneline
aa47ff2541fa64e6d44735e90dedcee60d5fb0a3 (HEAD -> master) feat: 不想要的提交 # 👈 这个提交不想要
0dc03f1970ed670b97bccffc92ab5598b5049bf8 feat: 完成首页
9b9d085b932043a2d9250b864a1cbb1535f82184 feat: 完成 Product 组件
...
- 解决方案1:reset
$ git reset --hard HEAD^
HEAD is now at 0dc03f1 feat: 完成首页
$ git log --pretty=oneline
0dc03f1970ed670b97bccffc92ab5598b5049bf8 (HEAD -> master) feat: 完成首页 # 👈 没了
9b9d085b932043a2d9250b864a1cbb1535f82184 feat: 完成 Product 组件
- 执行以下命令
$ git rebase 7064a1652cda00d4a57d24d3661b018771a49387 # 倒二个
- 此时会进入 vim
pick 5acd6e2 feat(project): 添加 version 脚本
# Rebase 7064a16..5acd6e2 onto 7064a16 (1 command)
- 修改为以下内容并保存
drop 5acd6e2 feat(project): 添加 version 脚本
- 查看结果
Successfully rebased and updated refs/heads/feat/A.
$ git log --pretty=oneline
7064a1652cda00d4a57d24d3661b018771a49387 (HEAD -> feat/A) feat(changeLost): 添加 changeLog # 第一个没啦
c45cbb73e79d460473dc941ab062ff7e11d099fa (tag: v1.0.3) 1.0.3
671757d69b98e3d6cae6e4dce5717fac4f77a3a7 feat(project): 添加 ChangeLog
fd369e89072279a7057e236ba1707f2a19709b03 (tag: v1.0.2) 1.0.2
4e9f32cc30525a70c07f3c544594f105c48d8d0f (tag: v1.0.1) 1.0.1
- 解决方案2:rebase
$ git log --pretty=oneline
5acd6e27a85b7e728454374b9fe516387e2e7450 (HEAD -> feat/A) feat(project): 添加 version 脚本
7064a1652cda00d4a57d24d3661b018771a49387 feat(changeLost): 添加 changeLog
c45cbb73e79d460473dc941ab062ff7e11d099fa (tag: v1.0.3) 1.0.3
671757d69b98e3d6cae6e4dce5717fac4f77a3a7 feat(project): 添加 ChangeLog
fd369e89072279a7057e236ba1707f2a19709b03 (tag: v1.0.2) 1.0.2
4e9f32cc30525a70c07f3c544594f105c48d8d0f (tag: v1.0.1) 1.0.1
- 解决方案3: revert
$ git revert aa47ff2541fa64e6d44735e90dedcee60d5fb0a3 --no-edit
\[master ae7eae8\] Revert "feat: 不想要的提交"
Date: Tue May 26 13:45:07 2020 +0800
1 file changed, 1 deletion(-)
$ git log --pretty=oneline
ae7eae86691a90e81b68b85e0f3cb7ebaee4312c (HEAD -> master) Revert "feat: 不想要的提交" # 👈 没了
aa47ff2541fa64e6d44735e90dedcee60d5fb0a3 feat: 不想要的提交
0dc03f1970ed670b97bccffc92ab5598b5049bf8 feat: 完成首页
9b9d085b932043a2d9250b864a1cbb1535f82184 feat: 完成 Product 组件
- 解决方案4:reflog + reset
$ git reflog
6fa3df5 (HEAD -> master) HEAD@{0}: commit: feat: 不想要的提交
0dc03f1 HEAD@{1}: reset: moving to HEAD^ # 👈 这个
aa47ff2 HEAD@{2}: reset: moving to HEAD
aa47ff2 HEAD@{3}: reset: moving to HEAD@{6}
$ git reset --hard HEAD@{1}
HEAD is now at 0dc03f1 feat: 完成首页
0x006 取消一次 merge
- 场景展示
有 feat/A 和 feat/B 分支合并到 master,如下图现在想撤销 feat/B 到 master 的合并
![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2020/png/281707/1590472368645-536b45c9-ebc2-4f6e-858a-f906614ba5cb.png)
- 解决方案1:reset
$ git log --pretty=oneline
aeca903ffad7140b2d1c854c936290c006542f05 (HEAD -> master) Merge branch 'feat/B'
7c8f46806ffb2ee5961e24b4a435d68f893c78c4 (feat/A) feat: 添加功能a # 👈 回退到这个就行了
1b2dd75b7193a9b37e20a269f5490971adfe4b50 (feat/B) feat: 添加功能b
0dc03f1970ed670b97bccffc92ab5598b5049bf8 feat: 完成首页
9b9d085b932043a2d9250b864a1cbb1535f82184 feat: 完成 Product 组件
$ git reset --hard 7c8f46806ffb2ee5961e24b4a435d68f893c78c4
HEAD is now at 7c8f468 feat: 添加功能a
看看结果
![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2020/png/281707/1590472911298-e89e3453-14ff-4ad6-bf32-3c28e4e26699.png?x-oss-process=image%2Fresize%2Cw_1500 "image.png")
- 解决方案2:revert
$ git log --pretty=oneline
aeca903ffad7140b2d1c854c936290c006542f05 (HEAD -> master) Merge branch 'feat/B'
7c8f46806ffb2ee5961e24b4a435d68f893c78c4 (feat/A) feat: 添加功能a # 👈 回退到这个就行了
1b2dd75b7193a9b37e20a269f5490971adfe4b50 (feat/B) feat: 添加功能b
0dc03f1970ed670b97bccffc92ab5598b5049bf8 feat: 完成首页
9b9d085b932043a2d9250b864a1cbb1535f82184 feat: 完成 Product 组件
$ git revert aeca903ffad7140b2d1c854c936290c006542f05 -m 1 # 👈 1是只分支序号
\[master a26fa95\] Revert "Merge branch 'feat/B'"
1 file changed, 1 deletion(-)
delete mode 100644 b.txt
- 解决方案3:reflog + reset
$ git reflog
aeca903 (HEAD -> master) HEAD@{0}: merge feat/B: Merge made by the 'recursive' strategy.
7c8f468 (feat/A) HEAD@{1}: merge feat/A: Fast-forward # 👈 回退到这个就行了
0dc03f1 HEAD@{2}: checkout: moving from feat/A to master
7c8f468 (feat/A) HEAD@{3}: commit: feat: 添加功能a
0dc03f1 HEAD@{4}: checkout: moving from feat/B to feat/A
1b2dd75 (feat/B) HEAD@{5}: commit: feat: 添加功能b
0dc03f1 HEAD@{6}: checkout: moving from feat/A to feat/B
0dc03f1 HEAD@{7}: checkout: moving from master to feat/A
$ git reset --hard HEAD@{1}
HEAD is now at 7c8f468 feat: 添加功能a
结果:
0x007 删除提交历史中的一个大文件/敏感文件
这个功能在我看来有两个用处:
- 过去提交了敏感文件,比如密钥,期望把它从提交历史中移除
- 提交了大文件,导致整个项目变大,虽然后期把它删除了,但是历史中还是存在的
- 场景展示
\# 不小心把一个安装包给提交进来了
$ git add .
$ git commit -m 'feat: 完成首页'
\[master aa23c6a\] feat: 完成首页
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 XMind-for-macOS-10.1.0-202003221812.dmg # 👈不小心添加的大文件
# 尝试删除 安装包
$ rm XMind-for-macOS-10.1.0-202003221812.dmg
$ git add .
$ git commit -m 'feat: 删除安装包'
\[master 68a3be8\] feat: 删除安装包
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 XMind-for-macOS-10.1.0-202003221812.dmg # 👈删除
明面上看是删除了,但是看看提交历史,这个文件依旧是存在的,如果是密钥文件,那不免有泄露风险。
并且文件特别大,看看这时候我们项目有多大吧:
解决方案1:filter-branch
$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch XMind-for-macOS-10.1.0-202003221812.dmg' --prune-empty --tag-name-filter cat -- --all
Rewrite b426e7e5fe1633d4321403e36be5656a99ba4ad8 (1/5) (0 seconds passed, remainRewrite 3bf1398f9010f2358ddb9bb6c29669c11a2fea01 (2/5) (0 seconds passed, remainRewrite 9b9d085b932043a2d9250b864a1cbb1535f82184 (3/5) (0 seconds passed, remainRewrite aa23c6ad093baa8a90264e5d8c761d8cc7b062f8 (4/5) (0 seconds passed, remaining 0 predicted) rm 'XMind-for-macOS-10.1.0-202003221812.dmg'
Rewrite 68a3be8e878eaba59af800c63856d488de3f3df3 (5/5) (0 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
再看看历史:
再看看大小,还是没变啊,咋回事
继续往下:
$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
$ git reflog expire --expire=now --all
$ git gc --prune=now
Enumerating objects: 16, done.
Counting objects: 100% (16/16), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (16/16), done.
Total 16 (delta 3), reused 14 (delta 3)
注意:git filter-branch 有很多陷阱,不再推荐使用它来重写历史。 请考虑使用 git-filter-repo,它是一个 Python 脚本,相比大多数使用 filter-branch 的应用来说,它做得要更好。它的文档和源码可访问https://github.com/newren/git-filter-repo获取。
0x008 招聘
新零售技术事业群-CCO技术部的前端团队,我们致力于Web前端技术的研究,同时也重视全栈的能力、产品的推动。Glue即为胶水,我们粘合了设计与技术、用户和产品的关系,用最酷的技术提升客户服务的体验和小二工作的幸福感。FGT也可看成是Fighting的缩写。我们在听得到炮火的地方战斗,我们要把好阿里用户体验的最后一关!
我们负责的产品线非常丰富,PC、无线、内部CRM、Native等等,无论你是什么技术特质,总能找到合适的应用场景。
我们的业务也很有挑战,整个BU致力于通过产品技术创新驱动服务变革,改变人力密集型的传统服务模式。通过打造一站式服务平台,为企业提供全套客户服务解决方案,提升服务体验的同时极大降低服务成本。 通过输出阿里平台沉淀,构建服务生态圈,为电商服务体系贡献水电煤。
如果你来到我们团队,你将负责:
- 各业务前端开发 - 平台易用性与用户体验的持续改进
- Web前沿技术研究和新技术调研
职位要求:
- 精通各种前端技术,同时具备 PC/无线 端的开发能力,有复杂产品的开发经验。
- 掌握常见性能优化的方法,以及衡量产品性能的方法。
- 对 MVC/MVVM 等模式有一定的理解,熟悉 React/Vue 等热门框架,有实际项目经验。
- 对前端工程化有一定理解,熟练掌握 Webpack/Grunt/Gulp 等构建工具的使用和配置。 ‘
- 熟悉 ES6/Node.js 并且具备一定的开发能力。
简历投递地址:
- cangxiu.lyx@alibaba-inc.com
微信(不投简历交个朋友也行哦):
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。