在使用 Git 作为版本控制的时候,我们可能提交了很多不尽如人意的 commit。如果这些 commit 太多会显得混乱,甚至会影响到正常的工作流。如何对这些 commit 进行修正呢?
下面以 github.com/jjvvv/autoComplete 项目为示例进行演示。
可以看到一共有 7 个 commit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 commit 75931a058b8c6810048cd9b8fb6ad7dd53a32140 (HEAD -> master, origin/master, origin/HEAD) Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 08:11:35 2015 +0800 add demo commit 9f480fba3c5c973082c30d4751e6d8d802c8e1bc Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:13:32 2015 +0800 change README.md commit 064af197e7674b7357da6606655f13e4aebbcaab Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:10:52 2015 +0800 change README.md commit 251af8b01add69e49c64308c9b328670bcad0aae Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:08:57 2015 +0800 change readme.md commit fdc128e488457e18887d85362dde87f1a2420146 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:07:23 2015 +0800 remove module commit 666ba561a6ef687abb61be44ce410128b2faf645 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:02:05 2015 +0800 autoComplete commit c1c0414ad3dce011802d75347d6191c801bd8f5c Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 05:58:16 2015 +0800 first commit ~
修改最新 commit 如果只想修改最新的 commit,可以使用:
场景 示例 我们把最新的那个 commit add demo
信息改成 docs(readme): add demo
:
进入到编辑模式,修改 commit 信息为docs(readme): add demo
然后保存。修改后的 commit 信息如下,但是要注意,commit 的 id 已经和之前不同了:
1 2 3 4 5 commit 0e49c219ce76065f6825941b3cecf30b3439412d (HEAD -> master) Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 08:11:35 2015 +0800 docs(readme): add demo
修改多个 commit 修改更早提交的 commit ,可以使用git rebase
,通过给 git rebase 增加-i 选项来以交互方式地运行 rebase。
示例 上例中,有三个 commit 是重复的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 commit 9f480fba3c5c973082c30d4751e6d8d802c8e1bc Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:13:32 2015 +0800 change README.md commit 064af197e7674b7357da6606655f13e4aebbcaab Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:10:52 2015 +0800 change README.md commit 251af8b01add69e49c64308c9b328670bcad0aae Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:08:57 2015 +0800 change readme.md
我们利用 git rebase
给它们合并进行合并。
合并有两个方法:
从 HEAD 往过去数 4 个版本 指出要合并的版本的前一个版本号,这里注意,不包括这个指明的 commit 其实按我的理解,git rebase -i HEAD~4
的意思是:嘿,我挑出来最近四个 commit,让我做一些修改吧。
这里我们用第一种方法执行完 rebase 之后,会进入交互模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 pick 251af8b change readme.md pick 064af19 change README.md pick 9f480fb change README.md pick 0e49c21 docs(readme): add demo
我们把 中间两个 pick 改成 squash,意思是说把这两个 commit 融入到前一个 commit 中:
1 2 3 4 pick 251af8b change readme.md squash 064af19 change README.md squash 9f480fb change README.md pick 0e49c21 docs(readme): add demo
保存完之后会再次进入编辑状态,提示你可以修改三个合并好之后的 commit 的信息,再次保存之后,我们看下 git log
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 commit 09ad45377c2c7a616545f7f01ddb740964a2eddb (HEAD -> master) Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 08:11:35 2015 +0800 docs(readme): add demo commit 0c5c282227c9e8d336b1e3633f6962e621880662 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:08:57 2015 +0800 change readme.md change README.md change README.md commit fdc128e488457e18887d85362dde87f1a2420146 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:07:23 2015 +0800 remove module commit 666ba561a6ef687abb61be44ce410128b2faf645 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:02:05 2015 +0800 autoComplete commit c1c0414ad3dce011802d75347d6191c801bd8f5c Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 05:58:16 2015 +0800 first commit
可以看到,三个 commit 已经成功合并到一个了。
如果 rebase 的过程有冲突,解决好冲突之后,运行:
1 2 $ git add . $ git rebase --continue
如果想放弃 rebase 的话,运行:
删除 commit 可以利用 git rebase
删除 commit,同样,将 pick 改为 drop 即可:
1 # d, drop <commit> = remove commit
回滚 commit git reset 示例 比如,我们想回滚到倒数第二个 commit(add demo 的前一个 commit),先记录下这个 commit ID 0c5c282227c9e8d336b1e3633f6962e621880662
1 2 $ git reset 0c5c282 --soft
然后再使用 git log
查看历史记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 commit 0c5c282227c9e8d336b1e3633f6962e621880662 (HEAD -> master) Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:08:57 2015 +0800 change readme.md change README.md change README.md commit fdc128e488457e18887d85362dde87f1a2420146 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:07:23 2015 +0800 remove module commit 666ba561a6ef687abb61be44ce410128b2faf645 Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 06:02:05 2015 +0800 autoComplete commit c1c0414ad3dce011802d75347d6191c801bd8f5c Author: JJVvV <drowning524@gmail.com> Date: Fri Dec 18 05:58:16 2015 +0800 first commit
会发现 add demo 的那个 commit 已经没有了,版本库已经回滚到 0c5c282
提交的状态了。但是 add demo 提交的内容并没有丢失,只是回到了未提交状态:
1 2 3 4 5 Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: .idea/workspace.xml modified: README.md
git reset –mixed 和 git reset –soft 差不多: soft 执行完之后文件是已提交状态,mixed 执行完之后文件是未提交状态。
这些标记往往和 HEAD 作为参数一起使用。比如,git reset –mixed HEAD 将你当前的改动从缓存区中移除,但是这些改动还留在工作目录中。另一方面,如果你想完全舍弃你没有提交的改动,你可以使用 git reset –hard HEAD。这是 git reset 最常用的两种用法。
我们把刚才未提交的文件再次提交为add demo
,然后执行 git reset 0c5c282 --hard
。会发现版本库也回到了这个 commit ID,但是之前提交的 commit 文件已经丢失了。
git revert 有些时候既不想更改 commmit 也不想删除 commit,只是想撤销掉某个 commit,此时可以使用 revert。revert 在撤销一个 commit 的同时会新增一个 commit(相当于综合掉了这个 commit 的影响)。
示例 我们在刚才的实例上连续添加三个 commit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 commit 93a702791a9102dfd14aa12063eb4a71d8df6ceb Author: Alex Liu <drowning524@gmail.com> Date: Sun Apr 28 17:25:08 2019 +0800 format html commit a04e1083fe57b26bd0359e39c1f5e3057485bb9e Author: Alex Liu <drowning524@gmail.com> Date: Sun Apr 28 17:24:12 2019 +0800 add console commit 15618e77fc4c8de131b5c8f655d360d2e7221c3a Author: Alex Liu <drowning524@gmail.com> Date: Sun Apr 28 17:23:16 2019 +0800 change version
如果我们想撤销change version
这个 commit 的话,复制它的 ID,运行:
此时会增加一个新的 commit:
1 2 3 4 5 Date: Sun Apr 28 17:25:26 2019 +0800 Revert "change version" This reverts commit 15618e77fc4c8de131b5c8f655d360d2e7221c3a.
revert 的操作,只会撤销掉change version
这个 commit 的影响。 它前边的两个 commit 仍会保留。
总结 以上总结了一些修改 commit 的方法,当然还有更多的方式,这里只列举了一些常用的。
git commit –amend 修改最新 commit git rebase -i commitID 修改 commitID 之前的多个 commit git reset commitID 重置到某个 commit git revert commitID 撤销掉 commitID(通过新增一个 commit 来撤销掉 commitID,相对安全)