摘要:背景背景大家都有学习如何规范简洁的编写代码,但却很少学习如何规范简洁的提交代码。
大家都有学习如何规范简洁的编写代码,但却很少学习如何规范简洁的提交代码。现在大家基本上都用 Git 作为源码管理的工具,Git 提供了极大的灵活性,我们按照各种 workflow 来提交/合并 code,这种灵活性把控不好,也会带来很多问题
最常见的问题就是乱成一团的 git log history,那真的是老太太的裹脚布, 又臭又长, 个人极其不喜欢这种 log
造成这个问题的根本原因就是随意提交代码。
代码都提交了,那还有什么办法拯救吗?三个锦囊,就可以完美解决了
这个命令的帮助文档是这样描述的:
--amend amend previous commit
也就是说,它可以帮助我们修改最后一次提交
既可以修改我们提交的 message,又可以修改我们提交的文件,最后还会替换最后一个 commit-id
我们可能会在某次提交的时候遗漏了某个文件,当我们再次提交就可能会多处一个无用的 commit-id,大家都这样做,git log 慢慢就会乱的无法追踪完整功能了
假设我们有这样一段 log 信息
* 98a75af (HEAD -> feature/JIRA123-amend-test) feat: [JIRA123] add feature 1.2* 119f86e feat: [JIRA123] add feature 1.1* 5dd0ad3 feat: [JIRA123] add feature 1* c69f53d (origin/main, origin/feature/JIRA123-amend-test, origin/HEAD, main) Initial commit
假设我们要修改最后一个 log message,就可以使用下面命令:
git commit --amend -m "feat: [JIRA123] add feature 1.2 and 1.3"
我们再来看一下 log 信息, 可以发现,我们用新的 commit-id 5e354d1
替换了旧的 commit-id 98a75af
, 修改了 message,并没有增加节点
* 5e354d1 (HEAD -> feature/JIRA123-amend-test) feat: [JIRA123] add feature 1.2 and 1.3* 119f86e feat: [JIRA123] add feature 1.1* 5dd0ad3 feat: [JIRA123] add feature 1* c69f53d (origin/main, origin/feature/JIRA123-amend-test, origin/HEAD, main) Initial commit
现在我们的 repo 中文件是这样的:
.├── README.md└── feat1.txt0 directories, 2 files
假设我们提交 feature 1.3
的时候,忘记了一个配置文件 config.yaml
, 不想修改 log,不想添加新的 commit-id,那下面的这个命令就非常好用了
echo "feature 1.3 config info" > config.yamlgit add .git commit --amend --no-edit
git commit --amend --no-edit
就是灵魂所在了,来看一下当前的 repo 文件:
.├── README.md├── config.yaml└── feat1.txt0 directories, 3 files
再来看一下 git log
* 247572e (HEAD -> feature/JIRA123-amend-test) feat: [JIRA123] add feature 1.2 and 1.3* 119f86e feat: [JIRA123] add feature 1.1* 5dd0ad3 feat: [JIRA123] add feature 1* c69f53d (origin/main, origin/feature/JIRA123-amend-test, origin/HEAD, main) Initial commit
知道这个技巧,就可以确保我们的每次提交都包含有效的信息了。一张图描述这个过程就是这个样子了:
有了 --no-edit
的 buff 加成,威力更大一些
可以看着,上面的 log 都是在开发 feature1,我们在把 feature 分支 merge 到 main 分支之前,还是应该继续合并 log commit 节点的,这就用到了
git rebase -i HEAD~n
其中 n 代表最后几个提交,上面我们针对 feature 1 有三个提交,所以就可以使用:
git rebase -i HEAD~3
运行后,会显示一个 vim 编辑器,内容如下:
1 pick 5dd0ad3 feat: [JIRA123] add feature 1 2 pick 119f86e feat: [JIRA123] add feature 1.1 3 pick 247572e feat: [JIRA123] add feature 1.2 and 1.3 4 5 # Rebase c69f53d..247572e onto c69f53d (3 commands) 6 # 7 # Commands: 8 # p, pick = use commit 9 # r, reword = use commit, but edit the commit message 10 # e, edit = use commit, but stop for amending 11 # s, squash = use commit, but meld into previous commit 12 # f, fixup = like "squash", but discard this commit"s log message 13 # x, exec = run command (the rest of the line) using shell 14 # d, drop = remove commit 15 # l, label
合并 commit-id 最常用的是 squash
和 fixup
, 前者包含 commit message,后者不包含,这里使用 fixup, 然后 :wq
退出
1 pick 5dd0ad3 feat: [JIRA123] add feature 1 2 fixup 119f86e feat: [JIRA123] add feature 1.1 3 fixup 247572e feat: [JIRA123] add feature 1.2 and 1.3
我们再来看一下 log, 这就非常清晰了
* 41cd711 (HEAD -> feature/JIRA123-amend-test) feat: [JIRA123] add feature 1* c69f53d (origin/main, origin/feature/JIRA123-amend-test, origin/HEAD, main) Initial commit
上面的 feature1 已经完整的开发完了,main 分支也有了其他人的更新,在将 feature merge 回 main 分支之前,以防代码有冲突,需要先将 main 分支的内容合并到 feature 中,如果用 merge 命令,就会多处一个 merge 节点,log history 中也会出现拐点,并不是线性的,所以这里我们可以在 feature 分支上使用 rebase 命令
git pull origin main --rebase
pull 命令的背后是自动帮我们做 merge 的,但是这里以 rebase 的形式,再来看一下 log
* d40daa6 (HEAD -> feature/JIRA123-amend-test) feat: [JIRA123] add feature 1* 446f463 (origin/main, origin/HEAD) Create main.properties* c69f53d (origin/feature/JIRA123-amend-test, main) Initial commit
我们的 feature1 功能 on top of
main 的提交节点,还是保持线性,接下来就可以 push 代码,然后提 PR,将你的 feature merge 到 main 分支了
简单描述 merge 和 rebase 的区别就是这样的:
我这里使用 git pull origin main --rebase
省略了切换 main 并拉取最新内容再切回来的过程,一步到位,背后的原理都是上图展示的这样
使用 rebase 是要遵守一个黄金法则的,这个之前有说过,就不再是赘述了
有了这三个锦囊,相信大家的 git log 都无比的清晰,如果你还不知道,完全可以用起来,如果你的组内成员不知道,你完全可以推广起来,这样的 repo 看起来才更健康
接下来会介绍一个多分支切换互不影响的锦囊
个人博客:https://dayarch.top
加我微信好友, 进群娱乐学习交流,备注「进群」
欢迎持续关注公众号:「日拱一兵」
- 前沿 Java 技术干货分享
- 高效工具汇总 | 回复「工具」
- 面试问题分析与解答
- 技术资料领取 | 回复「资料」
以读侦探小说思维轻松趣味学习 Java 技术栈相关知识,本着将复杂问题简单化,抽象问题具体化和图形化原则逐步分解技术问题,技术持续更新,请持续关注......
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/124127.html
摘要:即便对于行家来说,调试神经网络也是一项艰巨的任务。神经网络对于所有失真应该具有不变性,你需要特别训练这一点。对于负数,会给出,这意味着函数没有激活。换句话说,神经元有一部分从未被使用过。这是因为增加更多的层会让网络的精度降低。 即便对于行家来说,调试神经网络也是一项艰巨的任务。数百万个参数挤在一起,一个微小的变化就能毁掉所有辛勤工作的成果。然而不进行调试以及可视化,一切就只能靠运气,最后可能...
摘要:合并到多个目标分支或其他人正在使用当前分支这是应该使用因为你执行时当前分支原先的会被删除会影响他人,形成新的连接在目标分支最新之后。 阅读原文:合并分支使用Merge还是Rebase? 作为一个有追求的开发者,我一定会选择更好的版本管理工具(Git), 使用中我们难免会在 Merge 和 Rebase 中选择其一用于合并分支。 Rebase 和 merge 都是被设计用于集成你所做的改...
摘要:适配器模式桥接模式过滤器模式组合模式装饰器模式外观模式享元模式代理模式行为型模式这些设计模式特别关注对象之间的通信。对象适配器另外一种适配器模式是对象适配器,它不是使用多继承或继承再实现的方式,而是使用直接关联,或者称为委托的方式。 设计模式汇总 创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用新的运算符直接实例化对象。这使得程序在判断针对某个给定实例需...
阅读 1182·2021-11-22 12:05
阅读 1314·2021-09-29 09:35
阅读 611·2019-08-30 15:55
阅读 3108·2019-08-30 14:12
阅读 936·2019-08-30 14:11
阅读 2860·2019-08-30 13:10
阅读 2387·2019-08-29 16:33
阅读 3310·2019-08-29 11:02