我们在本地开发的过程中,常常会有一些语义不清的提交,比如
git commit -m 'save'
但是当我们 push 到 origin 的时候会期望有一些实际意义的 commit message 比如
git commit -m 'fix: timestamp bug'
解决这个问题有两种方式:
git amend
git rebase -i
Amend
使用 git commit — amend
直接修改上一次的 commit message。
git commit --amend # 进入交互模式修改
git commit --amend -m 'new commit message' # 直接修改上一次 commit
需要注意:
- 这是用一个新的 commit 来替换掉原来的 commit,所以 commit ID 会发生变化。
- 不要修改已经 push 的 commit,除非你是在自己的分支
Interactive Rebase
首先说下 rebase 操作是什么,变基 (rebase) 其实是一种 merge 的操作,但是和 merge 不同的是,merge 会保留 分支信息,但 rebase 是直接把修改嫁接到你想保留的分支,而把切出去的那个分支的信息全部丢掉了,这样看起来就像从未切过分支一样。下面两个图可以看出 git rebase
和 git merge
的区别。
master 分支 get merge branch1
![efe0d7888fdd04e9217c22022f8c88ab.gif](https://img-blog.csdnimg.cn/img_convert/efe0d7888fdd04e9217c22022f8c88ab.gif)
branch1 分支 git rebase master
![baa060dc6cf92f7ca288373961dad2b8.gif](https://img-blog.csdnimg.cn/img_convert/baa060dc6cf92f7ca288373961dad2b8.gif)
git rebase -i
使用交互式 rebase 则有更多的功能,可以细致的操作每一条 commit,这样我们就能合并,修改 commit
git rebase -i [start-commit] [end-commit]
# (start-commit, end-commit] 前开后闭区间,默认 end-commit 为当前 HEAD
示例
假如我们一共有四次提交,如下
commit b95a1b0d2fbc2210aeffd80cbd521fbdf019d0be (HEAD -> master)
Author: N
Date: Mon May 27 18:49:00 2019 +0800
4th commit
commit 295fadd3680a8909220a73ab37703113eff00d44
Author: N
Date: Mon May 27 18:48:29 2019 +0800
third commit
commit e96c3419b9edb337d24861906de562430dc974db
Author: N
Date: Mon May 27 18:48:00 2019 +0800
second commit
commit da629ffe1dc0d22c418b7e60a4a804b42ab4a313
Author: N
Date: Mon May 27 18:47:30 2019 +0800
first commit
如果我们想合并后三次 (2, 3, 4) 提交,那么 start-commit 应该为第一个 commit ID (前开后闭区间)。输入命令后,会进入交互模式,其中,pick
表示当前的后三次都是使用的。
> git rebase -i da629ffe1dc0d22c418b7e60a4a804b42ab4a313 #(第一次提交的 commit ID)
----------------------------
pick e96c341 second commit
pick 295fadd third commit
pick b95a1b0 4th commit
下面的内容同时也会出现,提示你应该将 commit 置为哪种状态。
# Commands:
# 用这个 commit
# p, pick <commit> = use commit
# 修改 message
# r, reword <commit> = use commit, but edit the commit message
# 停下来,修改内容
# e, edit <commit> = use commit, but stop for amending
# 合并
# s, squash <commit> = use commit, but meld into previous commit
# 合并且抛弃 message
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# 抛弃这个 commit
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# 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
我们要将三个 commit 合并成一个,因此需要应该 pick 第一个 commit,同时将后面两个 commit "压入"第一个 commit 。所以需要将后面两个 commit 从 pick
改为 squash
或者 fixup
,然后保存 :wq
,如下
pick e96c341 second commit
f 295fadd third commit
f b95a1b0 4th commit
结果只剩下两个 commit,大功告成!
BTW 如果想要修改 commti message,可以在这一步之后再使用 git commit --amend
,或者在上一步选择用 squash
的模式。
commit 521bea075647a6e0a0d34d4f6df288bfda9353ad (HEAD -> master)
Author: N
Date: Mon May 27 18:48:00 2019 +0800
second commit
commit da629ffe1dc0d22c418b7e60a4a804b42ab4a313
Author: N
Date: Mon May 27 18:47:30 2019 +0800
first commit
Conventional Commits
最后提一下 Commit message 的社区标准规范 Conventional Commits ,是一个对 commit message 的约束。即每条 commit message 都要满足一个结构:
type(optional scope): description
---
# 比如
fix: onClick event
featrue(user): allow add user
其中 type 可选的大概有
- fix 修复
- feat 功能
- chore 杂项
- docs 文档
- style 样式
- BREAKING CHANGE 重大更新
Ref
- https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history