搜尋

首頁  >  問答  >  主體

團隊開發經常使用 git rebase 來保持樹的整潔好嗎?

用了以後, 樹可以非常清晰, 某種程度上便於追踪, 但是 push --force 就多多了,
不用呢, 合併沒有遠端倉庫被修改的麻煩, 可是追蹤又不清晰...

怎麼取捨? 團隊裡一般怎麼取捨?

巴扎黑巴扎黑2806 天前1748

全部回覆(11)我來回復

  • 滿天的星座

    滿天的星座2017-04-25 09:04:57

    git rebase是對commit history的改寫。當你要改寫的commit history還沒有被提交到遠程repo的時候,也就是說,還沒有與他人共享之前,commit history是你私人所有的,那麼想怎麼改寫都可以。

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

    樓主遇到的問題,就是改寫了公有的commit history造成的。 要解決這個問題,就要從提交流程上做規範。

    舉個正確流程的栗子:

    假設樓主的team中有兩個developer:tom和jerry,他們共同使用一個遠程repo,並各自clone到自己的機器上,為了簡化描述,這裡假設只有一個branch:master

    這時tom機器的repo有兩個branch
    master, origin/master, origin/master
    而jerry的機器上也是有兩個branch
    master, origin/master, origin/master

    均如下圖

    tom和jerry分別各自開發自己的新feature,不斷有新的commit提交到他們各自私有的commit history中,所以他們的master指針不斷的向前推移,分別指向不同的commit。而又由於他們都沒有git fetchgit push,所以他们的origin/master都維持不變。

    jerry的repo如下

    tom的repo如下,注意T1和上图的J1,分別是兩個不同的commit

    這時Tom先把他的commit提交的遠端repo中,那麼他本機origin/master指針則會前進,和origin/master指针则会前进,和master指針保持一致,如下

    遠端repo如下

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

    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完全沒有問題,改寫之後,如下

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

    git push後,本機repo

    而遠端repo

    異常的輕鬆,一條直線,沒有-f

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

    之前,先git fetch,再git rebase

    git fetch origin master
    git rebase origin/master
    git push
    

    強烈建議閱讀
    • a successful git branching model
    • Git-分支-分支的衍合
    🎜

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-25 09:04:57

    除非只有自己一個人用,不然用 push --force 的都該去死。

    回覆
    0
  • PHPz

    PHPz2017-04-25 09:04:57

    本地分支和遠端分支的綁定(tracking),加上 rebase 策略:

    [branch "master"]
        remote = origin
        merge = refs/heads/master
        rebase = true
    

    這樣一來,更新程式碼(pull)的時候就會自動套用 rebase 而不是產生 merge commit,除非有其他情況產生,例如三方合併造成了衝突需要人共去幹預。大部分時候還是很聰明的,只要團隊裡的習慣都很好,那麼可以保持一個非常乾淨漂亮的樹形。

    其實想讓樹狀結構漂亮些清晰些是有很多辦法的,但首先要取決於團隊用的是什麼樣的 Git Model,對症下藥即可。在這裡就無法一言以蔽之了。

    另外,樓上說得對,慎用 push -f

    回覆
    0
  • 我想大声告诉你

    我想大声告诉你2017-04-25 09:04:57

    這應該是一個git workflow的問題,我們團隊也一直在使用rebase保證commit資訊的整潔,但不會用到push -f這樣的操作。

    關於git workflow就是一個見仁見智的問題了,下面幾篇文章你可以看下,再找出一套適合自己團隊的就可以了,不過最重要的是要確保團隊的每個人都熟悉git,防止犯愚蠢的錯誤。

    • 構造乾淨的 Git 歷史線索
    • 流傳甚廣的A successful Git branching model
    • Github workflow

    如果使用github來團隊合作的話,用好pull request,它可以解決push -f這種愚蠢問題!

    回覆
    0
  • 阿神

    阿神2017-04-25 09:04:57

    每個人提交前,都應該把自己的修改rebase到伺服器的最新程式碼之上,遵守這個規則就不會有任何問題。如果你需要force push,表示你做反了,把伺服器程式碼rebase到你本地分支之上才會需要force push,這是錯誤的用法。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-25 09:04:57

    建議參考Pro Git 中關於rebase 的章節http://git-scm.com/book/zh/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94% AF%E7%9A%84%E8%A1%8D%E5%90%88

    衍合的風險
    呃,奇妙的衍合也並非完美無缺,要用它得遵守一條準則:

    一旦分支中的提交對象發佈到公共倉庫,就千萬不要對該分支進行衍合操作。

    如果你遵循這條金科玉律,就不會出差錯。否則,人民會仇恨你,你的朋友和家人也會嘲笑你,唾棄你。

    就我而言。如果 rebase 完後,需要使用 push -f 的話,一定代表該 rebase 操作是不合適。除非你是有意在修改提交歷史。

    回覆
    0
  • 漂亮男人

    漂亮男人2017-04-25 09:04:57

    不需要push -f啊,如果分支落後就用pull --rebase

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-25 09:04:57

    樓上的答案都很正,個人認為,除非某個分支只有你自己搞,你怎麼rebase都是沒有問題的,但是如果你在master或者develop這種分支上來rebase,估計團隊裡每個人都想拍死你,尤其是對git不熟悉的隊友,手足無措是非常正常的表現。

    rebase之後push -f的情況只有一個,就是題主像我一樣有強迫症,害怕電腦宕機、系統崩潰這種蛋疼的事情(悲慘的血淚史),完成一個特性commit之後迅速push到遠程只屬於你的分支上,每天為了拿到develop的新特性,才在自己的分支上rebase develop,重複執行push的操作,這個個人認為是沒有問題的,畢竟你只影響了你自己(而你知道這是對的)。

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-25 09:04:57

    個人認為, 當你在某個分支進行團隊合作的時候, 常用rebase真的是不合理。而且容易出問題。慎用 push --force

    回覆
    0
  • 習慣沉默

    習慣沉默2017-04-25 09:04:57

    git rebase 一般自己一個人開發時使用,用來保持提交記錄的整潔。一旦上傳到github後,不應該使用git rebase,不然被罵死。

    回覆
    0
  • 取消回覆