天天看點

Git 分支操作&存儲原理淺談

作者:騰訊技術工程

作者:robertlong,騰訊 PCG 用戶端開發工程師

相信大家對于 git 版本控制系統都不陌生,大部分同學在工作中都會使用到 git,他幫助我們管理我們的代碼,讓我們能夠随心所欲的送出代碼,進行不同的實驗而不用擔心将項目毀掉,同學們可以在工作中熟練的使用 git 進行代碼送出,但是部分同學對于 rebase,merge 等等針對分支,合并的操作不十分自信,并且對目前騰訊視訊用戶端采用的主幹開發模式背後的原理并不熟悉,在本文章中,我想通過介紹 git 的存儲機制,來幫助大家更好的了解分支以及分支操作。

希望有相關困惑的同學能夠通過本文章,從原理上對 git 的分支操作有一定的了解,在日後的工作中使用相對應的 git 指令時能更加得心應手,遊刃有餘,本文主要分為以下幾個部分:

  • Git 簡單介紹
  • Git 存儲原理淺談
  • 分支與分支管理,以及不同的分支合并方式
  • 常見問題&一些使用技巧

Git 是什麼?— 分布式的版本控制系統

git 是一個分布式版本控制系統。Git 記錄的是整個項目的快照,而非不同版本之間的差異,這一點上,git 和許多其他的版本控制系統不太一樣,當 git 存儲更新或者儲存檔案狀态時,它基本上就會對當時項目中由 git 管理的全部檔案建立一個快照并儲存這個快照的索引。 為了效率,如果檔案沒有修改,Git 不再重新存儲該檔案,而是隻保留一個連結指向之前存儲的檔案。 Git 對待資料更像是一個快照流。

Git 分支操作&存儲原理淺談

分布式的版本控制

Git 的版本控制是分布式的,這意味着當多人工作在同一個項目或者同一個分支上時,每個人的系統之都包含了這個項目或者分支的全部資訊,即使此時中央 git 伺服器出現不可修複的故障,仍可以基于任何一個已經檢出該項目的電腦來使用本地的 git 記錄來進行覆寫還原。同時 git 對于所有的資料在存儲前都會計算校驗合(使用一種叫做 SHA-1 的哈希計算方式),用來校驗和引用,這意味着 git 可以察覺到所管理項目中任何一個檔案内容或者目錄内容的變動。

總是在添加資料

Git 一般隻會添加資料,我們所做的任何操作(即使是回退代碼),都在向 git 資料庫中添加資料,這意味着 git 幾乎不會執行任何可能導緻檔案不可恢複的操作。

鼓勵分支的使用

Git 引入了分支的概念,并且允許我們頻繁的添加,删除,合并以及修改分支,這極大地便利了我們在不同開發工作之間切換,同時也讓項目管理者可以更好的管理有很多開發者參與以及送出貢獻的項目。 Git 的這些特性迅速讓他成為了主流,git 讓我們可以愉快的進行多人協作開發,也允許開發人員針對項目的規模和特點,選擇各種各樣的開發模式。(對 git 開發模式感興趣的同學可以閱讀:https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows)

Git 的存儲原理淺談

要想搞明白分支的概念,以及各種分支操作到底做了什麼,我們首先需要對 git 存儲代碼版本和資訊的原理有個簡單的認識。

Git 的本質是一個鍵值存儲系統,我們可以向 git 倉庫中插入任意類型的内容,他會對内容進行存儲,同時基于内容計算并傳回一個唯一的值(前文說到的 sha-1 哈希值)作為鍵,通過該鍵我們可以再次通路到該内容。 Git 就是基于這個存儲系統存儲我們的項目送出的,為了記錄我們項目的送出快照,送出資訊等資料,git 定義并存儲了不同類型的存儲對象,主要包括:

資料對象(blob):包含存儲檔案的内容資訊的對象,一個資料對象通常包含一個檔案的内容資訊,但是不包含檔案名。

樹對象(tree):存儲檔案名,同時可以将多個檔案組織到一起,(有點類似 unix 檔案系統中的目錄項。一個樹對象可以包含一條或多條送出記錄)通常,我們在 git commit 時會将暫存區的所有狀态寫為一個樹對象,一個樹對象包含多個樹對象記錄(tree entry),每條記錄都代表了目前目錄下的一個條目,他們有可能是一個檔案,也有可能是一個子目錄(指向另一個樹對象的指針)他們幫助我們管理項目的目錄和層級關系。

送出對象(commit):有了樹對象和資料對象,我們記錄下了每次送出的内容,為了記錄送出之間的順序關系,以及送出的作者資訊,git 引入了送出對象的概念,一個送出對象通常會儲存一個樹對象,作為目前的項目快照。可能存在的父送出對象,作者資訊,時間戳,以及送出的注釋。

靠這三種對象,git 基本上儲存了我們項目需要的所有資訊。假設我們建立了一個簡易的項目,我們首先在項目中建立了一個 test.txt 檔案并送出給 git 來管理,之後我們修改了 test.txt 檔案的内容,并建立了另一個叫做 new.txt 的檔案,最後我們又建立了一個叫 bak 的目錄,并将 test.txt 檔案的第一個版本放在了該目錄中。在以上過程中,我們建立了三次送出,git 的送出曆史大概長這樣:

Git 分支操作&存儲原理淺談

可以看到,資料對象對象儲存了檔案内容資訊,樹對象存儲了檔案名和目錄相關的資訊,而送出對象為我們存儲了送出之間的順序,以及和每個送出相關的資訊。

現在我們回到我們的主題:分支以及分支操作上。這涉及到了另外一種對象:引用對象(reference)

Git 引用

上文我簡單介紹了 git 存儲資訊的結構,不難看出,想要檢出或者重制某個 commit 對應的樹對象,我們需要獲得他對應送出對象的 SHA-1 code, 我們很難記住所有存儲在 git 中送出對象的 SHA1-code 以及他們對應修改具體的作用,是以 git 引入了引用對象的概念來幫我們更好的管理和通路不同的送出。 **引用(reference)**允許我們給某個送出對象起一個簡單的名字,這個名字可以幫助你想起這個送出對象所對應的項目狀态,引用一般存儲在.git/refs 目錄下。你應該已經猜到了,每個引用都對應我們項目中的一個分支。現在假設我們為後兩次送出分别建立了不同的引用,我們的 git 檔案目錄可能長這樣:

Git 分支操作&存儲原理淺談

引用對象的種類多種多樣,包括:

  • HEAD 引用:(指向目前檢出的分支的頭部,可能指向其他引用的指針,或者某個 git 對象),
  • 标簽引用(指向某個标簽對應的送出對象),
  • 遠端引用(對遠端倉庫的引用,隻讀),

(如果你對不同的引用類型不熟悉,可以檢視這裡:Git--local-branching-on-the-cheap) 此處我們就不再展開。

分支與分支管理 - 分支的建立,切換

知道了 git 的存儲原理和分支的本質,我們現在可以來聊聊分支以及一些分支的操作了,我們已經知道了分支本質上是指向送出對象的指針,是以在 git 中建立分支的花費極小,同時檢出新分支的操作也隻是将 HEAD 引用指向對應分支的引用,同時檢出對應的樹對象到工作目錄。

我們在前文已經提到,當你在目前檢出的分支上送出新的修改并送出時,git 會自動幫助你将目前分支的引用對象挪動到新的送出節點,HEAD 引用也會随之移動,但是這不會對其他分支的引用進行任何修改,我們也知道送出對象(commit)會儲存自己的父送出對象資訊,這使得當項目存在分叉時尋找恰當的合并基礎(共同送出祖先)變得簡單而高效(lowest common ancestor 問題)。

使用 merge 合并分支:

在适當的時機開發者們會将多個分支的送出合并到一個分支上,在 git 中,将兩個分支合并有兩種不同的方式,merge 和 rebase,我們将分别讨論這兩種合并方式,以及他們到底做了什麼,以便同學們在日後的工作中可以更好的選擇不同的方式。

合并沒有分叉的分支

如果我們的開發分支與合入到的目标分支之間沒有任何分叉(例如在下面的示意圖中, 我們檢出了 master 分支,并且想将 hotfix 分支合并到 master 分支上,hotfix 分支所指向的送出 C4 是我們所在的分支 master 所指向的送出 C2 的直接後繼),那麼這時候 git 會直接将目标分支的指針向前挪動到指向開發分支的頭部,這個指針移動操作被叫做 fast forward,

Git 分支操作&存儲原理淺談
Git 分支操作&存儲原理淺談

圖:将 hotfix 分支 merge 到 master 分支,master 分支的引用對象直接向前移動到 hotfix 分支所指向的送出對象。

合并包含分叉的分支

并不是所有的分支合并都能夠 fast forward,假設我們有這樣一條分叉送出記錄:

Git 分支操作&存儲原理淺談

圖:一個包含分叉的 git 送出記錄,此時檢出名為 master 的分支。

當我們想把 experiment 分支上的修改通過 merge 的方式合并到 master 分支上時,兩個分支的頭部送出節點都不在另一個分支的送出曆史中(如上圖中 c3,c4 節點的情況),git 會幫助我們建立一個新的合并送出,合并之後的送出記錄長這樣:

Git 分支操作&存儲原理淺談

其中 c5 是 git 為了完成此次三方合并而建立出來的一個新的送出,可以發現 c5 擁有兩個父送出。 當兩個分支對同一檔案的相同位置進行了不同修改時,git 會暫停下來并詢問你想要如何處理此處沖突。

Git 分支操作&存儲原理淺談

圖:git 在監測到沖突後生成的沖突标記,将兩部分沖突的代碼放在兩個代碼塊中,用=======号間隔開。

通常我們在進行 merge 操作時會檢出兩個分支中的一個,此時 git 自動産生的沖突解決标記中的 HEAD 代碼塊就代表了目前檢出分支上的修改,而另一部分則是合入過來的分支上對該部分代碼進行的修改。(HEAD 所指向的分支在 rebase 情況下會發生颠倒,如果在解決沖突時遇到需要解決不熟悉的代碼沖突,一定要進行區分,否則可能導緻 revert 他人代碼或者舊的修改被重新送出到遠端的情況,我們在後面會對解決沖突時選擇哪個分支的送出進行更詳細的解釋) 當然你也可以在解決沖突後任意修改此次合并送出的 commit message(C5 送出的 commit message)。

Merge 操作的一個問題是使用後我們的送出記錄将不再是線性的,這不僅會影響送出記錄的簡潔性,也會增加在遇到問題時正确復原代碼的難度(想了解復原分支合并送出時可能産生的問題,可以閱讀這個文檔中的撤銷合并部分:https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E9%AB%98%E7%BA%A7%E5%90%88%E5%B9%B6 )

同時,由于在計算兩個分支差異時 git 會尋找他們的公共父節點,是以如果兩個分支存在分叉,git 可能會計算出錯誤的 diff 資訊(例如在上面的例子中,C3 送出是某個從 experiment 分支 cherry-pick 過來的送出,或是某個過去送出的復原送出),這時候如果基于錯誤的父節點進行了 diff 計算,會産生令開發者迷惑的 diff 記錄。 那麼就沒有辦法解決這些問題,并維持漂亮的線性送出記錄了嗎?有的!rebase。

使用 rebase 合并分支,rebase 到底做了什麼?

Rebase 操作會修改目前分支的 git 送出曆史,将它修改成像是将目前分支的送出按照順序依次 cherry-pick 到目标分支上一樣,正入他的名字“變基”一樣,他讓你将目前分支(experiment 分支)上所做的修改改變為基于 rebase 分支(master)的頭部,而不是你目前分支修改前的頭部。換句話說,他讓你修改 C4 送出,使他的祖先從 C2 變到 C3. 如果我們使用 rebase 的方式合并之前提到的分叉分支,合并後的分支會長這樣:

Git 分支操作&存儲原理淺談

圖:将 experiment 分支基于 master 分支進行變基

當我們對自己的開發分支進行變基合并後,将它 merge 到之前變基的分支變得十分輕松了,隻需要 fast-forward master 的引用指針,同時也不會出現多餘的合并節點。

注意在示意圖中我們 rebase 後的分支為 C4’而并非 C4,這是因為他和 C4 已經是兩個不同的(長得十分相似)送出對象,他們分别基于不同的父送出,如果 git 在将 C4 應用到 C3 上時出現了沖突,同樣也會暫停并詢問你應當如何解決這個沖突,這會使得 C4‘和 C4 的差異更大,你同時也可以在解決沖突後對 c4’的送出資訊進行修改。如果你在目前分支存在多條送出記錄,例如 C4 後面還跟着 C5,C6…那麼在變基後他們的變基送出也會依次跟在 C4’的後面 C4’ - C5’ -C6’。

同時在 rebase 過後,我們在 experiment 分支上的送出已經被修改為基于 master 分支的頭部節點,這極大的降低了 git 計算 diff 時找到錯誤的 base 的可能性。

很多同學不喜歡使用 rebase 的一大原因是,在 rebase 的時候,我們經常會需要解決同一個沖突很多次,當我們基于新的 master 重放原有的送出時,如果 git 不知道如何基于你剛剛解決沖突後的 C4‘應用 C5(很有可能發生,因為 C5 是基于 C4 進行的開發,現在 C4 已經被改變了),那麼在應用 C5 的時候你需要再解決一次沖突(這次沖突很可能是你解決 C4 沖突時引入的)。

作者推薦的解決方式是盡量保證在 rebase 前本地隻有一個 commit 記錄,你可以使用 git squash 等指令将多個送出合并,也可以在本地有一次新的送出以後,後續使用 git commit —amend 的方式來對本次送出進行追加修改。除此之外,git 也提供了一個可以記住你之前解決沖突的方式,并且當相同的沖突再次出現的時候自動幫助你應用相同解法的工具 git rerere(https://git-scm.com/book/en/v2/Git-Tools-Rerere )

使用 squash&merge 進行合并

除了使用 rebase 保證項目的送出曆史為線性外,我們還希望送出曆史沒有備援的送出記錄,同時確定送出曆史中的每一筆送出都是一個可以穩定運作的版本(由流水線進行保證),這将會極大的提升項目主幹的穩定性,同時讓復原操作變得更加便利。

Git 分支操作&存儲原理淺談

工蜂的 git 網頁端已經為我們提供了 squash and merge 的按鈕選項,我們也可以在指令行使用 git merge 指令時 通過添加 git merge --squash 來通過 squash merge 的方式将 branchName 分支合入到目前檢出分支中, 本質上就是将分支上的修改壓縮成一個送出再合并過來。将 branch 上的所有改動儲存到目前的暫存區中,如果在本地使用 git merge --squash 指令進行 merge 的話,還需要進行一次 commit 操作,将 staged change 送出,才算是完成了整個 merge 的過程,在網頁端,當我們點選 squash and merge 按鈕并且填寫好本次送出的 commit 資訊後,網頁端會自動幫助我們完成上述操作,假設我們有以下的分支送出曆史:

E----F feature branch
 /
A----B----C----D master branch
           

那麼當我們在 master branch 上 使用 git merge --squash 并進行 commit 後,我們将得到下面的送出曆史:

E----F feature branch
 /
A----B----C----D----H master branch
           

其中 master 分支上面的 H 送出包含了 feature 分支上面 E 和 F 兩次修改的内容。

一種了解 squash merge 的方式是他隻會保留檔案的修改内容資訊,同時丢棄掉 feature 分支上的送出資訊。從上面的例子我們注意到使用 squah and merge 不會建立出 target 分支和 feature 分支的 merge 公共節點,squash merge 相當于在 target 分支上将 feature 分支上與 target 分支不同的所有修改全部儲存在一個新的 commit 中并送出上去。這個新的 commit 和 feature 分支上的送出除了内容修改相同外(無沖突情況下),沒有任何的聯系。使用 squash merge 後并不能從任何一個分支的送出曆史中辨認出兩個分支存在 merge 過程。這也是一部分開發者非常反對在項目中使用 squash merge 的原因之一。大家在選擇使用 squash merge 作為 merge 方式時需要謹慎,同時建議在 squash merge 後将 feature 分支删除,防止混淆。

将 rebase 和 squash and merge 搭配使用

在大型項目中,由于開發者衆多,如何保證主幹的穩定性成了這一類項目能夠持續發展的關鍵。在這個背景下,配套使用 rebase 和 squash merge 的主幹開發模式可以很好的保證主幹上的每一筆送出都有品質把關,同時送出曆史是簡介的,線性的。由于 rebase 後,target 分支的頭部一定在 feature 分支的送出曆史記錄中,是以 git 計算出來的 diff 就隻包含 feature 分支上面的修改。通過 squash merge 的送出資訊,可以将每一筆送出的具體改動和功能和對應的需求進行綁定,很好的解決了 squash merge 沒有合并資訊的問題。rebase 和 squash & merge 的配套使用,讓我們既享受到了簡潔,線性的送出記錄,又盡可能的避免了合并的風險。

合并前的送出曆史:

E----F feature branch
 /
A----B----C----D master branch
           

feature 分支基于 master 分支 rebase 後:

B----C----D----E'----F' feature branch
 /
A----B----C----D master branch
           

squash merge:

B----C----D----E'----F' feature branch
 /
A----B----C----D----G master branch
           

在 G 送出的 commit 資訊中包含必要的資訊,用來記錄此次送出的改動。

相信大家對于 merge 操作已經有了更深的了解,在以後的開發過程中對于分支的合并可以更加的得心應手。

在 rebase 後使用 git push -f 來更新遠端的跟蹤分支

如果我們之前已經将我們的開發分支推送到了遠端,此時本地又 rebase 了另一個分支(比如主幹),這時如果我們想更新遠端該分支的送出記錄,就不能再使用 git push 了(有時候即使推送成功了,遠端分支的送出記錄也是錯誤的,git 有時會将 rebase 後分支上來自 rebase 分支的送出當成是新的送出,在發起 mr 時産生令人混亂的 diff 記錄)

正确的做法是使用 git push -f 指令來強制更新遠端分支的送出記錄,很多同學對于 git push -f 的使用很忌憚,因為這會使用本地的送出完全覆寫掉遠端的送出記錄,其實在官方的文檔中,也推薦在 rebase 過後使用 git push -f 來更新遠端對應分支的記錄,但是使用中一定要記住一點,不要對多人共享的分支使用 git push -f,否則會導緻已經将該分支檢出到本地的同學在合并以及後續開發中痛苦至極(對于這種情況的解決辦法,可以參考:https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%8F%98%E5%9F%BA 中用變基解決變基的例子)

如何将本地檢出分支上的修改送出到其他的分支

有時候我們會遇到比較緊急需求或者 bugfix 的情況,在開發完過後才發現自己還在 master 分支上,忘記了切換分支(也有可能隻是我)。我們無法直接将本地的 master 推送到遠端,但是有一些方法可以解決這個問題:

  1. 切換到正确的分支 将代碼 cp 過來。
  2. 如果還未送出,将未送出的代碼 stash,切換到對應的送出分支,再使用 stash pop 方法将代碼從 stash 棧中取出。
  3. 使用 git push HEAD: 方法将目前分支推送到遠端的指定分支上(如果 HEAD 指向的遠端分支已經存在,且兩個分支存在送出曆史沖突,需要使用-f 進行強行覆寫,需要謹慎使用)。

對本地 commit 進行修改

我們經常遇到講代碼送出成 commit 後,又發現一些需要修改的點的情況,無論是因為編譯發現一些遺漏的邏輯,還是因為突然發現了某個 typo 或者多餘的空行,這個時候如果修改并且從新送出一個 commit,會導緻送出記錄中充滿了“修複 typo”, “修複另一個 typo”這樣沒有意義的送出,不但使得送出記錄不美觀,同時也導緻同一個 feature 的送出記錄不收斂(當然如果在合入 master 時使用 squash&merge 可以解決這個問題),如果你的上一個 commit 還沒有被送出到遠端,那麼可以在 git add 過後,使用 git commit —amend 指令,這會将目前暫存區的送出合并到上一個 commit 中,同時允許你修改上一條 commit 的 commit message。 當然,你也可以選擇讓 commit message 保持原樣,隻要使用 git commit —amend —no-edit 就可以。

Ps:這會修改你最後一次的送出記錄,如果你還沒有将最後一次送出推送到遠端,那麼這樣做是很安全的,如果你已經将修改送出到了遠端,請確定沒有其他人此刻與你共享該分支進行開發,因為你需要使用 git push -f 來覆寫推送修改後的最後一條 commit。這會導緻其他共享該分支開發的同學 git 的沖突。

什麼是 Detached Head? 我該怎麼辦?

前文我們提到引用的種類有很多,其中 HEAD 引用指向目前檢出的項目狀态的頭部,HEAD 引用通常會指向目前檢出分支的引用(他通常是一個指向引用的引用)當我們在目前的分支上開發并送出時,我們将目前分支的引用向前挪動到新的送出對象上,相應的 HEAD 引用也随之指向了新的送出。

但是在某些情況下,HEAD 分支可能不指向某個引用,比如我們檢出了某個标簽對應的樹對象,或者我們檢出了某個目前分支上面的送出,那麼 HEAD 将不再指向任何分支的引用,而是直接指向了對應的樹對象,這種情況下,我們便進入了 detached head 狀态,我們可以進行任何正常的 git 操作,也可以在該狀态下送出新的代碼和 commit,但是當我們檢出到其他分支時,如果沒有為在 detached head 狀态下送出的代碼建立新的引用,那些送出将無法再被通路到,git 會對他們進行 gc。是以你如果需要在 detached head 模式下進行開發和送出,一定要記得在檢出其他分支前為他們建立引用。(例如建立一個新的分支)

在解決沖突時遇到不了解的修改到底應該接受哪個?

很多同學在解決沖突的時候都會遇到這個問題,如果沖突代碼我們比較熟悉還好,但是如果出現沖突的代碼我們并不熟悉,隻想要使用最新的送出的話,到底應該接受哪部分修改呢? 我們舉個很常見的例子:

Git 分支操作&存儲原理淺談

當你在 experiment 分支上使用 git rebase origin/master 指令将目前分支基于主幹進行 rebase 時,如果出現沖突,而你想要應用 master 分支上面的最新修改,則應該選擇 HEAD section 中的修改進行送出,此時的沖突 block 與分支的對應關系如下:

Git 分支操作&存儲原理淺談

如果你使用 git merge origin/master 或者 git pull origin/master 指令将 master 反向合入到 experiemnt 分支,那麼此時的沖突 block 會是這樣:

Git 分支操作&存儲原理淺談

可以看到,來自 master 分支的送出被放在了下方的區域中,如果我們想要應用來自 master 分支的修改,則應該選擇非 HEAD section 中的修改進行送出,兩個種不同的合并操作下,接受同一個分支的送出所進行的選擇是相反的。

這看起來很反直覺,這樣設計的原因在于兩種合并操作站在不同的分支立場上。當你使用 rebase 操作時,由于我們是在 master 分支上重放 experiment 分支分叉上的每次送出,是以 git 是站在 master 分支的立場上,此時若發生沖突,git 會把 rebase 基于的分支(在此例子中,master 分支)上面的修改放在 HEAD section 中,而将 experiment 分支的修改放在下方。 如果是使用 merge 操作反相合并主幹分支,那麼 git 會站在 experiment 分支的立場上,将 master 分支的送出合入到目前分支。如果遇到沖突,自然會将 master 分支放在非 HEAD 的 section 中了。同學們在解沖突,尤其是自己不清楚的代碼沖突時一定要明确二者的差別。

使用 GUI 工具(Sourcetree)來管理 git 倉庫

如果你對于 git 指令行的使用并不是那麼得心應手,我強烈推薦你使用 source tree 等 gui 工具來輔助你進行項目的 git 管理,sourcetree 提供了非常直覺的 git 送出記錄圖,可以幫助你快速的檢視各個檔案的狀态,不同分支之間的關系,同時也可以讓你輕松管理本地以及遠端分支,實作檔案部分代碼區塊的復原,合并多個本地送出,或者将本地修改分成多次送出等操作。sourceTree 允許你快速檢視每次送出的修改内容,同時支援一鍵復原任意行的改動,十分友善。感興趣的同學可以去 sourcetree 的官網進行更深入的了解:https://www.sourcetreeapp.com/

Git 分支操作&存儲原理淺談

圖:sourceTree 展示的 git 送出曆史

結語

本文章中使用到的例子以及截圖大部分都來自https://git-scm.com/book/en/v2 ,git 的功能十分強大,本文章隻是圍繞着分支操作這個主題,簡單介紹了 git 的存儲原理。如果你感興趣,可以去該網站更深入和詳細的了解 git 的更多功能和特性。

本文章由 OVB 終端技術團隊提供支援

----OVB 終端技術團隊,為 OVB 各個終端業務提供技術支援。拉通 OVB 終端相同、相似技術,沉澱成可複用的 PaaS 服務。負責元件化改造,基礎元件更新,工程架構優化,CI/CD,終端動态化方案,編譯優化,工具鍊,性能&穩定性治理等工作。在工作中不斷探索各個方向和領域内的行業最佳實踐。