日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你根本不懂rebase-使用rebase打造可读的git graph

發布時間:2023/12/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你根本不懂rebase-使用rebase打造可读的git graph 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

git graph 可讀指什么?

這里的可讀,主要指的是能夠通過看git graph了解每一次版本更迭,每一次hotfix的修改記錄.反映到分支上面,有兩個要求:

  • 每個分支的歷史修改可讀(單個分支的層面)
  • 每個分支的分叉合并可讀(多個分支的層面)

rebase是什么,它是更優雅的merge嗎?

rebase翻譯做變(re)基(base).

講rebase的文章經常會引用三張圖:

原本的兩個分支

通過merge的結果

通過rebase的結果

用來說明git rebase和git merge的區別的時候確實是足夠了,但是 git rabase的用途并非是合并分支,它與merge根本不是同樣的性質.(注意,這里的說法是并非是,不是并非只是,因為雖然有時rebase替代了merge的工作,但其原理和性質完全不一樣.)

rebase還有以下幾種用處:

  • git pull —-rebase處理同一分支上的沖突(如果你能理解其實這是git fetch&&git rebase兩個操作,并且理解遠程分支和本地分支的區分的話,那么其實他跟單純的rebase用法沒什么區別,但是因為其場景不一樣,所以單獨拆分出來講)
  • git rebase -i修改commit記錄

實質上:

  • merge是對目前分叉的兩條分支的合并
  • rebase是對當前分支記錄基于任何commit節點(不限于當前分支上的節點)的變更.

rebase的base不能理解為分叉的基點,而是整個git庫中存在的所有commit節點:

  • 在git pull —-rebase的時候,這個當前分支是本地分支,commit節點是遠程分支的head
  • 在git rebase master的時候,這個當前分支是feature分支,commit節點是master分支的head
  • 在git rebase -i的時候,這個當前分支就是當前工作分支,commit節點是在 -i后注明的commit

rebase是怎么工作的?

上面我們已經說到了:

rebase是對當前分支記錄基于任何commit節點(不限于當前分支上的節點)的變更.

怎么做到呢?我沒有深入研究它真的是如何實現的,以下步驟一定是不對的,但足夠讓你理解rebase干了什么.

我們標注出了兩個重點,當前分支和commit節點.

  • 把當前分支branch-A從頭到尾列出來,從數據結構的角度來說這是一個鏈表
  • 把commit節點所在的分支branch-B從頭到尾列出來,同樣是一個鏈表
  • 找到這兩個鏈表最近相同的節點n
  • 把A在n之后的所有節點拆下來構成L
  • 把B在n之后的所有節點中存在的diff信息都匯總起來構成d
  • 對于L中的每一個節點,把他的diff信息拿出來,看看d中有沒有沖突,如果有沒法自動處理的沖突拋出錯誤,等待用戶自己處理
  • 可選地,對于rebase -i來說,還可以一次取多個節點或者按照不同順序取,你有更大的處理自由
  • 沒沖突和處理完沖突的節點,改一個hash放到branch-B的commit節點之后 你可以把之前我們說到的三種rebase用處套在以上步驟看看,是否能夠理解.

rebase很危險對嗎?

對,很危險.

不過就像小馬過河一樣,光聽別人說是沒用的,我們需要明白為什么有人說危險,有人說不危險.我看到很多文章說rebase有問題,但他們的說法其實并不讓人信服,很多時候只是他們不會用.

很多人聽說過一個golden rule,在文末有鏈接,但是很少有人會明白真正的原因.讓我們一層層地剖析:

  • 其他人git push的時候會對比較本地分支和遠程分支的區別,把不同的地方推上去
  • 如果遠程分支被修改了,那么其他人的本地分支和遠程分支就會出現分叉(另外還可能造成其他人之前已經推送的工作被覆蓋)
  • 當出現分叉的時候,意味著其他人需要處理沖突,也就是說,你對于遠程歷史記錄的修改使得沖突擴散到了其他人身上
  • 所以我們盡量不能修改遠程分支,不能把別人fetch回去的改掉,因為他們的工作就是基于fetch回去的分支開展的(往前推進是必須的,其實也修改了遠程分支,所以才會merge產生沖突,但是這個沖突是無法避免的)
  • 針對上面說的這一條,git也做了限制,如果你觸犯了上面的原則,會在push的時候被阻擋,但是通過加一個-f可以強推

實際上不止rebase這樣,任何修改遠程分支歷史的操作都會造成沖突,并且這個沖突需要所有人都解決一遍.

但是分析還是太長了,記不住怎么辦?

只需要記住-f,只要你不使用-f,那么就是安全的.

不過僅是安全,并不能保證優雅,如果要使git graph可讀,那你還得多想想:

  • 怎么讓自己的commit歷史清晰(每個commit反應了一個單位的工作,前后順序合理)
  • 怎么讓每次hotfix和feature所做的工作和順序清晰

rebase如何讓git graph可讀?

我們還是說回之前提到的三個用法:

git rebase master

在把分支合并回master的時候,用git rebase master代替git merge master.(注意,只在合并之前使用,否則多人協作會遇到沖突)

這樣的好處有兩個:

  • log里不會出現一個Merge branch 'master' into hotfix/xxx的節點
  • master分支上在這次merge之前已經被提交的上一次工作和這一次工作的順序更清晰,因為rebase會讓這次feature的分叉節點改到上一次工作后.對于master分支來說,我們并不關心checkout新的feature的順序,我們更關心merge新的feature的順序.

比如這里,使用merge master導致的紫色的分叉在提交之前與master多了一次連接,而且主線上在紫色分叉合并之前還經歷了一次合并,這個時間順序并不清晰.

那么在master分支上合并也用rebase嗎?不是.因為我們需要master上的分叉讓我們更明白master上的改變(所以使用-no-ff).實際上,不管你采用任何git flow模型,我都建議你對不太重要的分支合并采用rebase,對重要的分支合并采用merge.這樣會讓主干的更改更清晰,而分支不會擴散地太遠.

git pull —-rebase

多人在同一分支上工作的時候(包含master分支和多人合作的feature等分支),在git pull的時候會遇到沖突,git pull的默認行為是git fetch&git merge,merge的對象是遠程分支和本地分支.

它的好處基本上與上一條無異,還多了一條:

  • 使用merge行為的pull會將其他人的工作作為外來的分叉,從而在graph上產生一個新的分叉, 并且其他人這一段時間所做的所有的工作都會在graph上被抬升出去,如果這段時間其他人做的工作很多,graph的主線會變得喪失了主線的意義(因為它太單薄了,很多工作根本沒反應上來).

比如這里,本來左數第二條玫紅色的才是主線,因為不規范地在master上直接提交了一次commit并且采用merge方式的pull做了合并導致主線被抬升到了外層.而這次不規范的commit卻成了主線.

git rebase -i

使用這條命令可以修改分支的記錄,比如覺得之前的commit修改內容不夠單元化,像是修改了文案1為文案2,修改了文案2為文案3,這種記錄對于master分支來說是沒必要關注的信息,最好通過git commit --amend或者rebase的方式修改掉.

不過并不推薦在提交之前手動做一次整個分支的squash,如果是rebase方式合并的話,也許更有意義.工蜂(騰訊內部的code平臺)提供了merge request的標題和內容功能,所以沒必要做squash,完全可以不必太聚合,以便反應真實的信息.

為了不影響別人,只用它修改未push的commit,或者如果一條分支只有一個人,你也可以修改已經push的commit.

對于這條命令的更多功能,可以再去查閱其他文章.

可讀的graph應該長什么樣?

先說一個原則,看graph要先看主線,主線要清晰,再看分叉上信息,這與我們的工作流程是一致的.

綠色的hotfix或者feature分支每次不是只允許提交一次commit,只是這一段都是一些小更改.

這看起來有點可笑,一點都不高級.說了這么多做了這么多難道只是為了得到這么簡單的圖?

沒錯,為了讓東西變簡單,本來就要付出很多代價,我們所做的就是要讓東西變簡單,比如努力工作是為了讓賺錢變簡單,努力提升是為了讓工作變簡單.讓事情變復雜只會讓事情不可控.

當然具體如何還是要取決于你采用的git flow,但是原則很簡單:

  • 每個分叉的子分叉盡量是一個串聯一個,內部盡量不要再有自己的提交.

為什么我認為這樣的git graph可讀性好,因為它把我們的工作也拍平了,不在乎每個工作的開始時間和持續時間,只關心這個工作的完成時間.

假如一個項目需求1是1月1號啟動,2月1號上線,需求2是1月20號啟動,2月10號上線.1月10號修了一個bug,2月3號修了一個bug. 聽起來是不是很繞?

如果你的git graph顯示的也是這樣的信息,可讀性一定不好,所以我們要做的git graph應該反應的是如下信息:

  • 1月10號修補bug
  • 2月1號上線需求1
  • 2月3號修補bug
  • 2月10號上線需求2

rebase的缺點是什么?

(這里并不討論rebase可能帶來的沖突問題,有很多文章都會講,上面也已經提到了rebase的危險性,這里只討論rebase對于git graph的缺點.實際上,沖突只是rebase不恰當使用導致的問題,而非rebase本身的問題.)

當然也有人會說,工作的開始時間也很重要呀,因為它反映了當時工作開展的基礎條件.對,這是rebase master的弊端.他讓記錄清晰,也讓記錄丟失了一些信息.記錄的加工讓可讀性變得更好,也讓信息量變少了.

git rebase 讓git graph發生了變化,每次分叉的檢出和并入之間不會再有任何節點.(因為合并到master采取的是merge行為.否則根本沒有分叉)

也就是這種情況不會再出現.因為每次總是rebase master,把自己的起點抬了上去.git rebase實際上讓檢出信息沒有意義,換取了主分支分叉的清晰.

如果rebase沒有缺點,那么也就沒有爭議.是否使用rebase也要看真實的需求是什么.

這篇文章要干什么?

通過rebase讓git graph更可讀.目的和原則我們都已經說過了,沒必要再重新說一遍.

多有謬誤之處,還望不吝賜教!

總結

以上是生活随笔為你收集整理的你根本不懂rebase-使用rebase打造可读的git graph的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。