情境
在当前 dev 分支上开发了两个毫不相干的内容,并且分别提交。第一个提交是一种长期的开发中的提交,而第二个提交是短暂的可以直接上线的提交。比如在该 dev 分支上新写了一个组件并且提交为 f7fcdf
,然后发现了一个统计代码的问题并且直接在该分支上提交为 9bac9b
,现在要求只上线 9bac9b
,而不需要上线 f7fcdf
,如何做到修改 git 提交历史,而仅仅将 f7fcdf
推送到远程仓库的对应分支 master 呢?
过程
git log
可查看提交的顺序,以及当前分支的版本栈在远程仓库 master 的对应关系是哪个,比如会标记第前三个提交记录 f738401
对应 (origin/master)。则本分支 dev 在本地剩下的两个提交记录 f7fcdf
和 9bac9b
是没有推送的远程仓库的。
现在只需要推送 9bac9b
。
git rebase
修改提交历史。
欲将 dev HEAD -> 9bac9b -> f7fcdf
,修改为 dev HEAD -> f7fcdf -> 9bac9b
。
git rebase -i HEAD~2
可以利用 VIM 编辑器修改提交的顺序。通过 dd
, p
, 即将提交的两个记录的顺序反置。接着通过 :x
命令保存并退出 rebase 子程序。
现在提交记录 9bac9b
位于 f7fcdf
之下了。
我仅想推送 9bac9b
应当如何做
git push
将本地分支 dev 中的前 n - 1 个提交记录推送到远程分支 master
git push origin HEAD~:master
可以利用 HEAD~
来表示某一段提交记录。
git push 关于 refspec 的描述可以参考下面的文档
<refspec>...
Specify what destination ref to update with what source object. The
format of a <refspec> parameter is an optional plus +, followed by
the source object <src>, followed by a colon :, followed by the
destination ref <dst>.
The <src> is often the name of the branch you would want to push, but
it can be any arbitrary "SHA-1 expression", such as master~4 or HEAD
(see gitrevisions(7)).
The <dst> tells which ref on the remote side is updated with this
push. Arbitrary expressions cannot be used here, an actual ref must
be named. If git push [<repository>] without any <refspec> argument
is set to update some ref at the destination with <src> with
remote.<repository>.push configuration variable, :<dst> part can be
omitted—such a push will update a ref that <src> normally updates
without any <refspec> on the command line. Otherwise, missing :<dst>
means to update the same ref as the <src>.
感悟
可见 git 软件还是很灵活的。