0%

git中的撤销操作

git rebase

git rebase是对commit history的改写
当你要改写的commit history还没有被提交到远程repo的时候,
也就是说,还没有与他人共享之前,commit history是你私人所有的,那么想怎么改写都可以

一旦被提交到远程后,这时如果再改写history,那么势必和他人的history长的就不一样了
git push的时候,git会比较commit history,如果不一致,
commit动作会被拒绝,唯一的办法就是带上-f参数,
强制要求commit,这时git会以committer的history覆写远程repo,
从而完成代码的提交。虽然代码提交上去了,
但是这样可能会造成别人工作成果的丢失,所以使用-f参数要慎重

注意点

  1. 除非只有自己一个人用,不然用 push –force 的都该去死
  2. 慎用 push -f!
  3. 每个人提交前,都应该把自己的修改rebase到服务器的最新代码之上,遵守这个规则就不会有任何问题。
    如果你需要force push,说明你做反了,把服务器代码rebase到你本地分支之上才会需要force push,这是错误的用法。
  4. 一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作
  5. 如果 rebase 完后,需要使用 push -f 的话,一定代表该 rebase 操作是不合适。除非你是有意在修改提交历史
  6. 除非某个分支只有你自己搞,你怎么rebase都是没有问题的,但是如果你在master或者develop这种分支上来rebase,
    估计团队里每个人都想拍死你
  7. 当你在某个分支进行团队合作的时候, 常用rebase真的是不合理。而且容易出问题。慎用 push –force
  8. git rebase 一般自己一个人开发时使用,用来保持提交记录的整洁。一旦上传到github后,不应该使用git rebase
  9. 一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作。
    如果你遵循这条金科玉律,就不会出差错。否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你
  10. 不需要push -f啊,如果分支落后就用pull –rebase

例子

假设楼主的team中有两个developer:tom和jerry,他们共同使用一个远程repo,
并各自clone到自己的机器上,为了简化描述,这里假设只有一个branch:master。

这时tom机器的repo有两个branch: master, origin/master

而jerry的机器上也是有两个branch: master, origin/master

均如下图所示

1

tom和jerry分别各自开发自己的新feature,
不断有新的commit提交到他们各自私有的commit history中,
所以他们的master指针不断的向前推移,分别指向不同的commit。
而又由于他们都没有git fetch和git push,所以他们的origin/master都维持不变

jerry的repo如下

2

tom的repo如下,注意T1和上图的J1,分别是两个不同的commit

3

这时Tom首先把他的commit提交的远程repo中,那么他本机origin/master指针则会前进,和master指针保持一致,如下

4

远程repo如下

5

现在jerry也想把他的commit提交到远程repo上去,
运行git push,毫无意外的失败了,所以他git fetch了一下,把远程repo,也就是之前tom提交的T1给拉到了他本机repo中,如下

6

commit history出现了分叉,要想把tom之前提交的内容包含到自己的工作中来,
有一个方法就是git merge,它会自动生成一个commit,既包含tom的提交,也包含jerry的提交
这样就把两个分叉的commit重新又合并在一起。但是这个自动生成的commit会有两个parent
review代码的时候必须要比较两次,很不方便。

jerry为了保证commit history的线性,决定采用另外一种方法,就是git rebase
jerry的提交J1这时还没有被提交到远程repo上去,也就是他完全私有的一个commit,
所以使用git rebase改写J1的history完全没有问题
,改写之后,如下

7

注意J1被改写到T1后面了,变成了J1`

git push后,本机repo

8

而远程repo

9

异常的轻松,一条直线,没有-f

所以,在不用-f的前提下,想维持树的整洁,方法就是:在git push之前,先git fetch,再git rebase

git fetch origin master
git rebase origin/master
git push
  1. 10 个迅速提升你 Git 水平的提示
  2. 团队开发里频繁使用 git rebase 来保持树的整洁好吗?
  3. a-successful-git-branching-model
  4. Git-分支-分支的衍合
  5. 构造干净的 Git 历史线索
  6. Github workflow