git rebase總結及git使用規范


一、git規范

  場景一:如果代碼commit到本地庫了,但是commit之前忘記pull了,遠程代碼也已更新,此時不能使用pull直接拉取遠程代碼(分支會產生merge的記錄):

    解決方法:commit之后,使用git fetch,拉取遠程代碼到緩存區,然后使用git rebase origin/dev,此時會產生沖突,解決沖突后即可提交,這樣分支不會產生merge的記錄

  場景二:commit提交之前先使用pull總是沒問題的,但如果pull不下來,是因為代碼和遠程代碼沖突了,此時有兩種解決辦法:

    1.使用git stash 保存本地修改的代碼到緩存區,此時代碼會還原為沒修改之前的,此時在使用git pull拉取代碼,然后使用git stash pop恢復緩存區的代碼,此時解決沖突即可提交

    2.先commit提交本地代碼到本地庫,這時候不要直接pull(分支會產生merge的記錄),先使用git fetch,拉取遠程代碼到緩存區,然后使用git rebase origin/dev,此時會產生沖突,解決沖突后即可提交,這樣分支不會產生merge的記錄

  場景三:dev代碼修改后,test分支需要同步更新修改:

    解決方法:dev修改后push代碼,切換到test分支,pull保證與遠程代碼一致,此時不能merge dev,而是使用git rebase dev(或者git rebase origin/dev),此時會把dev的代碼都更新到本地test分支,然后在push到遠程test分支,這樣分支不會產生merge的記錄

  場景四:新增測試不穩定的版本,在dev上切一個臨時分支tmp:

    解決方法:手動打包放在dev上測試,如果功能穩定沒問題,那么合並代碼,步驟1:git rebase origin/tmp;合並完臨時分支,還要在合一次origin/dev,步驟二:git rebase origin/dev,此時才可以push

  場景五:取消merging狀態

    git reset --hard HEAD (or sha_1)

  場景五:多人同時開發一個分支:

    1、git pull

        如果pull不下來,說明本地代碼和遠程分支有沖突,代碼更新不了

    2、git commit -m "xxx"
        將本地代碼添加到本地緩沖區

      git commit -a -m "xxx"
    3、git stash
        如果本地有不需要提交的代碼,git stash把你的修改保存起來,恢復到和你沒修改之前一致
    4、git fetch
        更新遠程代碼到本地暫存區
    5、git rebase
        把本地暫存區的代碼更新到工作區
    6、有沖突的話把沖突解決
    7、git status
      git add . 將解決完沖突的文件添加提交
    8、git rebase --continue
    9、git push origin dev 提交遠程分支
    10、git stash pop 恢復不需要提交的文件

 

  場景六:回滾遠程倉庫版本

    1.git reset --hard xxx(git提交版本號)

    2.git push --force

 

 二、tag標簽

  到達一定階段后,在代碼封版時,需要將穩定的代碼發布成一個版本,使用git 創建一個tag ,這樣一個不可修改的歷史代碼版本就像被我們封存起來一樣,不論是運維發布拉取,或者以后的代碼版本管理,都是十分方便的

創建tag標簽:
git tag -a 版本號 -m 'tag備注'
git tag -a v2.0.0 -m 'version2.0.0'

查看tag:
git tag

提交tag到遠程:
git push origin --tags

刪除tag:
git tag -d v2.0.0

刪除遠程tag:
git push origin :refs/tags/v2.0.0

 

三、rebase總結

  1. 如果新參與一個項目,首先需要本地clone遠程倉庫。之后會有一個master(若不特殊說明,均指代本地master)和遠端的master(以下稱為remote/master)是關聯的,即remote/master是本地master的up-stream。


    從遠程倉庫進行克隆
  2. 做開發時,要新建一個分支,如dev1,作為你的開發分支。開發完新特性后,將工作區(work tree)的修改提交至暫存區(index),然后commit,此時會在dev1分支上生成一個新的commit單號。


    提交你的修改
  3. 切換回master分支,然后使用pull或者fetch+merge命令與remote/master同步一下(此時可能會有來自其他開發者的提交),再合並(merge)dev1分支的,如果有沖突,則解決沖突。最后推送代碼到遠端倉庫。


    更新本地主分支

    合並dev1分支,推送
    合並dev1分支,推送

    這是我剛開始實習時,常用的一個開發,推送代碼的流程。久而久之,我發現了幾個問題:

  • 在master分支上解決沖突,可能會有些風險。比如一不注意,沖突沒有正確解決,導致本地修改與別人的修改混在一起,本來穩定的與遠程保持同步的master分支被你改混亂了,且沒有其他的備份了。

  • 在master分支上merge開發分支,如果master分支上有dev1沒有的commit單號,則會產生一個攜帶merge信息的提交單。這個commit你也要推送到遠端。企業開發一般會有一個評審分支,主管會對commit單號進行review,然后submit合並進remote/master分支中。merge信息的提交單也會讓reviewer做一次review,然而沒什么必要的。

  • 一個人提交時,會有一個merge commit,那么10個人提交,就會有10個merge commit,此時分支樹看起來會很混亂。零零散散的merge commit信息穿插在你的特性commit之間。

因此,我考慮使用另外一種本地分支管理策略,來改善這樣的問題。

 

使用rebase命令。

先簡要說下rebase命令的作用。

比如在dev1分支上,你提交了2個單,c1和c2。然后你在dev1分支上將master分支rebase到當前分支git rebase master。此時,如果master分支已經與remote/master做了同步,更新了2個來自其他人的提交,c3和c4。

 
場景描述

rebase會做如下操作:

 

  1. 把dev1分支上的c1和c2“拆”下來,並臨時保存成c1'和c2'。git里將其稱為patch
  2. 將master分支上更新的提交c3和c4合並進dev1分支上。


    rebase操作,拆分提交
    rebase操作,拆分提交
  3. 將c1'和c2',再按順序接在c3和c4的提交后面,如果沒有沖突,則rebase成功。此時c1'和c2'雖然和c1和c2的修改完全一樣,但卻已經不是原來的提交了,commit id已經變化了。
     
    連接patch

    此時dev1分支包含master分支的所有commit,並且超前了兩個commit。如果你現在切換至master分支,並執行git merge dev1操作,由於沒有不同於dev1的提交,merge操作就不會產生merge commit了。此時推送代碼,也只會有兩個commit。同時,master分支樹筆直前進,分支很清晰地展示一個個提交。並且,上述的更新和提交代碼的過程,是在dev1分支上修改沖突的,相對來說會比在master分支上修改更安全,如果不小心改混了,也能通過切換回master分支來找到穩定代碼。
     
    在master分支上合並dev1分支

    基於上述內容,可以使用如下流程來提交代碼:

 

  1. 在dev1分支上進行開發,然后commit提交,在dev1分支上生成一個提交單。
  2. 切換到master分支,與remote/master分支同步。
  3. 切換回dev1分支,將master分支rebase到dev1分支上,如果有沖突,修改沖突。rebase操作的沖突修改與merge不一樣,修改完沖突后,保存進index,然后直接git rebase --continue即可,不同再多做一次提交。
  4. 切換回master分支,合並dev1分支,此時合並會非常順暢。然后push。

rebase的風險

之前提到,rebase會將當前分支的新提交拆下來,保存成patch,然后合並進其他分支新的commit,最后將patch接進當前分支。這是rebase對多條分支的操作。對於單條分支,rebase還能夠合並多個commit單號,將多個提交合並成一個提交。

git rebase -i [commit id]命令能夠合並(整改)commit id之前的所有commit單。加上-i選項能夠提供一個交互界面,分階段修改commit信息並rebase。

但這里就會出現一個問題:如果你合並多個單號時,一不小心合並多了,將別人的提交也合並了,此時你本地的commit history和遠程倉庫的commit history不一樣了,無論你如何push,都無法推送你的代碼了。如果你並不記得rebase之前的HEAD指向的commit的commit ID的話,git reflog都救不了你。

tips: 你可以push時帶上-f參數,強制覆蓋遠程commit history,你這樣做估計會被打,因為覆蓋之后,團隊的其他人的本地commit history就與遠程的不一樣了,都無法推送了。

因此,請保證僅僅對自己私有的提交單進行rebase操作,對於已經合並進遠程倉庫的歷史提交單,不要使用rebase操作合並commit單。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM