開發效率優化之Git分佈式版本控制系統(一)

 

阿里P7移動互聯網架構師進階視頻(每日更新中)免費學習請點擊:https://space.bilibili.com/474380680
本篇文章將先從Git分佈式版本控制系統來闡述開發效率優化html

一,企業高效持續集成平臺場景介紹

 
19956127-3cd9ce282005058e.png
 

二,GIT分佈式版本控制系統

2.1 Git簡介

2.1.1 git是什麼?java

  • Git在Wikipedia上的定義:它是一個免費的、分佈式的版本控制工具,或是一個強調了速度快的源代碼管理工具。Git最初被Linus Torvalds開發出來用於管理Linux內核的開發。每個Git的工做目錄都是一個徹底獨立的代碼庫,並擁有完整的歷史記錄和版本追蹤能力,不依賴 於網絡和中心服務器。
  • Git的出現減輕了許多開發者和開源項目對於管理分支代碼的壓力,因爲對分支的良好控制,更鼓勵開發者對本身感興趣的項目作出貢獻。其實許多開源項目 包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已通過渡到使用Git做爲本身的版本控制工具。能夠在任何地點(在上班的地鐵 上)提交本身的代碼和查看代碼版本;能夠開許許多多個分支來實踐本身的想法,而合併這些分支的開銷幾乎能夠忽略不計。

2.1.2 什麼是版本控制呢?linux

本地版本控制系統:git

  • 許多人習慣用複製整個項目目錄的方式來保存不一樣的版本,或許還會更名加上備份時間以示區別。這麼作惟一的好處就是簡單。不過壞處也很多:有時候會混淆所在的工做目錄,一旦弄錯文件丟了數據就無法撤銷恢復。
  • 爲了解決這個問題,人們好久之前就開發了許多種本地版本控制系統,大多都是採用某種簡單的數據庫來記錄文件的歷次更新差別
 
19956127-1f1b0b74e5b9cc0a.png
 
  • 其中最流行的一種叫作 rcs,現今許多計算機系統上都還看獲得它的蹤跡。甚至在流行的 Mac OS X 系統上安裝了開發者工具包以後,也可使用 rcs 命令。它的工做原理基本上就是保存並管理文件補丁(patch)。文件補丁是一種特定格式的文本文件,記錄着對應文件修訂先後的內容變化。因此,根據每次 修訂後的補丁,rcs 能夠經過不斷打補丁,計算出各個版本的文件內容。

集中化的版本控制系統:github

  • 接下來人們又遇到一個問題,如何讓在不一樣系統上的開發者協同工做?因而,集中化的版本控制系統( Centralized Version Control Systems,簡稱 CVCS )應運而生。這類系統,諸如 CVS,Subversion 以及 Perforce 等,都有一個單一的集中管理的服務器,保存全部文件的修訂版本,而協同工做的人們都經過客戶端連到這臺服務器,取出最新的文件或者提交更新。多年以來,這 已成爲版本控制系統的標準作法
 
19956127-7ea06de061e15661.png
image
  • 這種作法帶來了許多好處,特別是相較於老式的本地 VCS來講。如今,每一個人均可以在必定程度上看到項目中的其餘人正在作些什麼。而管理員也能夠輕鬆掌控每一個開發者的權限,而且管理一個 CVCS 要遠比在各個客戶端上維護本地數據庫來得輕鬆容易。

事分兩面,有好有壞。這麼作最顯而易見的缺點是中央服務器的單點故障。若是宕機一小時,那麼在這一小時內,誰都沒法提交更新,也就沒法協同工做。要 是中央服務器的磁盤發生故障,碰巧沒作備份,或者備份不夠及時,就仍是會有丟失數據的風險。最壞的狀況是完全丟失整個項目的全部歷史更改記錄,而被客戶端 提取出來的某些快照數據除外,但這樣的話依然是個問題,你不能保證全部的數據都已經有人事先完整提取出來過。本地版本控制系統也存在相似問題,只要整個項 目的歷史記錄被保存在單一位置,就有丟失全部歷史更新記錄的風險。數據庫

分佈式版本控制系統:windows

  • 因而分佈式版本控制系統( Distributed Version Control System,簡稱 DVCS )面世了。在這類系統中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客戶端並不僅提取最新版本的文件快照,而是把原始的代碼倉庫完整地鏡像下來。這麼一來,任何一處協同工做用的服務器發生故障,過後均可以用任何一個鏡 像出來的本地倉庫恢復。由於每一次的提取操做,實際上都是一次對代碼倉庫的完整備份
 
19956127-1607c613d56089ea.png
 
  • 更進一步,許多這類系統均可以指定和若干不一樣的遠端代碼倉庫進行交互。籍此,你就能夠在同一個項目中,分別和不一樣工做小組的人相互協做。你能夠根據須要設定不一樣的協做流程,好比層次模型式的工做流,而這在之前的集中式系統中是沒法實現的。

2.1.3 git的優點在哪?瀏覽器

與同類型版本控制軟件:svn,cvs
SVN===>集中式版本控制系統
GIT===>分佈式版本控制系統服務器

 
19956127-c889e7e9644614bd.png
 
 
19956127-4c57851903dd0e4b.png
 

實際的例子:網絡

  • 之前我所 在的小組使用SVN做爲版本控制工具,當我正在試圖加強一個模塊,工做作到一半,因爲會改變原模塊的行爲致使代碼服務器上許多測試的失敗,因此並無提交 代碼。這時候上級對我說,如今有一個很緊急的Bug須要處理, 必須在兩個小時內完成。我只好將本地的全部修改diff,並輸出成爲一個patch文件,而後回滾有關當前任務的全部代碼,再開始修改Bug的任務,等到 修改好後,在將patch應用回來。前先後後要完成多個繁瑣的步驟,這還不計中間代碼發生衝突所要進行的工做量。
  • 但是若是使用Git, 咱們只須要開一個分支或者轉回到主分支上,就能夠隨時開始Bug修改的任務,完成以後,只要切換到原來的分支就能夠優雅的繼續之前的任務。只要你願意,每 一個新的任務均可以開一個分支,完成後,再將它合併到主分支上,輕鬆而優雅。
  • 所以,分佈式的版本控制系統,在每一個使用者電腦上就有一個完整的數據倉庫,沒有網絡依然可使用Git。固然爲了習慣及團隊協做,會將本地數據同步到Git服務器或者GitHub等遠程代碼倉庫
 
19956127-9a099a666c78edac.png
 

2.2 Git的安裝

2.2.1 Windows安裝git客戶端

客戶端下載地址:https://www.git-scm.com/downloads

 
19956127-0a57252772feec55.png
 

雙擊安裝包一路下一步便可。

 
19956127-0eb451e13c119f19.png
 

在桌面上建立一個空目錄,右鍵點擊目錄

 
19956127-185db82cba9393d0.png
 

選擇****Git Bash Here****,進入****git****命令界面

 
19956127-1d0784843d60aba1.png
 

到此windows的git客戶端就安裝好了

2.2.2 Linux利用yum安裝git客戶端

安裝環境查看

 
19956127-d7e5331bbf99d496.png
 

安裝git客戶端 yum安裝的git版本都是比較低的,想要高版本能夠源碼安裝。

 
19956127-0e6fa7c494ed48c2.png
 
 
19956127-2a2228174e71dc4c.png
 

Git全局配置

配置git使用用戶 配置git使用郵箱 語法高亮 查看全局配置

 
19956127-4208749e327f27a0.png
image

說明:

若是沒有提早設置Git的全局配置,那麼在第一次進行代碼提交的時候,會要求輸入使用者的郵箱和姓名

到此利用Yum安裝Linux操做系統的git客戶端就安裝好了

2.2.3 Linux源碼安裝git客戶端

若是咱們想要安裝最新版本的git,那麼就只能源碼包安裝了。

回退以前的yum安裝

 
19956127-39a823480ceaa1e8.png
 

源碼安裝git-2.9.5.tar.gz

 
19956127-2faa8ed764970944.png
 
 
19956127-54cdea5a27839f9f.png
 
 
19956127-ab361f83945973fc.png
 
 
19956127-8c1342b770411337.png
 

源碼編譯須要連接git的命令庫

 
19956127-0a8b6f487f8c7424.png
 
 
19956127-9943a584f0b4927f.png
 

至此,利用源碼包安裝Linux操做系統的git客戶端就安裝好了

2.3 Git的命令入門

  • 工做區
    • 你創建的本地git項目目錄
  • 暫存區
    • 將工做區裏的變動部分(與上一版本不一樣的部分)暫時存儲起來的地方
  • 本地倉庫
    • 在本地建立的git版本倉庫,用於提交工做區的變動。
  • 遠程倉庫
    • githab,gitlab或者隊友機器上所創建的一個倉庫
 
19956127-d13b362058b255e2.png
 
 
19956127-025d2b50ef9e2ca5.png
 

2.3.1 git幫助文檔

輸入git查看

 
19956127-073593591c395526.png
 
 
19956127-3193b4df7f68f4e6.png
 

2.3.2 git init初始化GIT工做目錄

 
19956127-ca6d5e08970d320b.png
 

2.3.3 git add將變動添加進入暫存區

 
19956127-4ae5168216ebbfb5.png
 
 
19956127-a17851e3a5050ce1.png
 

git status 查看git工做目錄的暫存區狀態

2.3.4 git commit將變動從暫存區提交到本地倉庫

 
19956127-38c22fd8062bb4dc.png
 

2.3.5 建立github帳號,並建立我的github遠程倉庫

 
19956127-8bd5c3627a925e7c.png
 

建立完****github****帳號後,咱們就能夠建立遠程倉庫了,以下圖所示:

 

 
19956127-aa90b67f19a99959.png
 

 

 
19956127-d9dc4121787591d0.png
 
 
19956127-79fbff2c40b80196.png
 

2.3.6 git remote用於管理遠程倉庫

 

 
19956127-2c53292d2fbdad37.png
 

 

(****1****)****git remote add

添加一個遠程倉庫的URL
命令格式:git remote add <倉庫的名字> <倉庫的URL>

 
19956127-d65f8457a4eddd9c.png
 

2.3.7 git push將本地倉庫的變動推送到遠程倉庫的某個分支

命令格式:
git push -u <遠程倉庫的名字> <遠程倉庫的某一分支名字>

在Linux上推送本地倉庫變動到遠程倉庫的master分支

 
19956127-091351aa30895ab6.png
 

再次在瀏覽器進行訪問查看你的****github****地址

 
19956127-61070c3ce6a6477e.png
 
 
19956127-dbde58f4ba6b0191.png
 

git remote -v 查看倉庫 前一列倉庫代號,本身起的,fetch拉取代碼,push推送

2.3.8 git clone克隆一個現有倉庫到本地

在另外一臺Git02上來模擬其餘客戶端進行對遠程倉庫克隆到本地倉庫的操做

 
19956127-217af997ba30fe0a.png
 
 
19956127-fb971d097ff0a3f4.png
 
 
19956127-8f0c824d31e09e51.png
 

初始化GIT工做目錄並將已有遠程倉庫克隆到本地

 
19956127-c21842532e45bbae.png
 
 
19956127-90451602bf59348c.png
 

修改倉庫裏的文件內容,並提交變動到本地,推送變動到遠程倉庫

 
19956127-931060bed6a69e5c.png
 
 
19956127-965a6f2daaf89713.png
 
 
19956127-520828d4d1a5e443.png
 

瀏覽器打開****github****查看變動提交狀況

 
19956127-ee6256c2cd3fa478.png
 

2.3.9 git fetch 將遠程倉庫的變動拉取到本地倉庫

在Git01上

 
19956127-05025623207b64f6.png
 

查看文件是否修改 沒有被修改

說明:

應用git fetch拉取到本地倉庫時,並不修改本地工做目錄中的代碼

若是要修改,那麼須要進行git merge變動合併

 
19956127-86e6bae366f993ec.png
 
 
19956127-aa9f7ca1870de083.png
 

2.3.10 get checkout檢查工做目錄代碼與本地倉庫中的代碼的差別

檢查本地工做目錄與本地倉庫的差別

 
19956127-97a7381c7fae9c2c.png
 

2.3.11 git merge 將遠程倉庫的變動,更新到本地工做目錄中

 
19956127-f833d093fdb0e757.png
 

2.3.12 git pull 將遠程倉庫的變動拉取到本地倉庫,並更新本地工做目錄。

git pull ====> git fetch + git merge

在Git01上對文件進行改動,並推送到github遠程倉庫

 
19956127-7e9037acb19686ab.png
 
 
19956127-1229eef38d8011cd.png
 

在Git02上,拉取遠程倉庫的變動後直接合並進本地倉庫的master分支

 
19956127-b055382b4c0743ce.png
 

沒有進行分佈式更新,一旦產生衝突是修改不了的,因此通常來講,開發都是分兩部分進行合併,除非判定沒有衝突就會用pull

2.3.13 git mv && git reset 暫存區文件的修改和撤銷

若是文件尚未被添加到暫存區,那麼Linux命令直接更名便可

 
19956127-3f7a2e7e2cda76f3.png
 
 
19956127-30ff729aa58fc609.png
 
 
19956127-fcb1b0369756c326.png
 

變更文件已經添加到了暫存區

 
19956127-42e000a55b27c933.png
 

經過git mv 來給已經添加到暫存區的文件更名 本地文件同時更名了

 
19956127-e52f8a69def7b0c0.png
 

經過git reset 來給已經添加到暫存區的文件撤銷掉

 
19956127-2ca2c069cc01716d.png
 

2.3.14 git rm 提交文件的刪除變動到暫存區

git add 能夠提交新增文件,修改文件的變動到暫存區;

git rm 則是提交刪除文件的變動到暫存區

 
19956127-f4c1be90dddef8dc.png
 
 
19956127-c69707f957f4974a.png
 

修改還沒有加入提交(使用 "git add" 和/或 "git commit -a")

 
19956127-7126312e4669ea2e.png
 
 
19956127-cb9a032fe49c1830.png
 

2.3.15 git diff 文件對比利器

git diff命令能夠將本地工做目錄中的文件與本地倉庫中的文件進行對比

 
19956127-c064a000761638d2.png
 
 
19956127-b442d6009abf6e74.png
 

2.3.16 git log 查看git提交歷史紀錄

  • git log:查看提交歷史記錄
    • git log -2 :查看最近幾條記錄
    • git log -p -1 : -p顯示每次提交的內容差別
    • git log --stat -2 : stat簡要顯示數據增改行數,這樣就能看到提交中修改過的內容
    • git log --pretty=oneline :一行顯示提交的歷史記錄

查看最近兩條記錄

 
19956127-de181406045d8f36.png
 

顯示最近一次提交的內容差別

 
19956127-a2d0214865020109.png
 

顯示提交內容的修改概要

 
19956127-551d426dc98320ee.png
 

用一行顯示提交的歷史記錄

 
19956127-30cba7e57756725f.png
 

2.4 追根溯源-git log

2.4.1 Git還原歷史數據

Git服務程序中有一個叫作HEAD的版本指針,當用戶申請還原數據時,其實就是將HEAD指針指向到某個特定的提交版本,可是由於Git是分佈式版本控制系統,爲了不歷史記錄衝突,故使用了SHA-1計算出十六進制的哈西字符串來區分每一個提交版本,另外默認的HEAD版本指針會指向到最近的一次提交版本記錄,而上一個提交版本會叫HEAD,上上一個版本則會叫作HEAD^,固然通常會用HEAD~5來表示往上數第五個提交版本。

  • git reset --hard HEAD^ #-->還原歷史提交版本上一次
  • git reset --hard 3de15d4 #-->找到歷史還原點的SHA-1值後,就能夠還原(值不寫全,系統會自動匹配)
 
19956127-97e1074847d2a367.png
 
 
19956127-1fd95b7abe8c6cb8.png
 

2.4.2 Git還原將來數據

當咱們回滾到歷史某個提交版本了之後;
咱們發現咱們已經沒有在那個版本以後的提交記錄了;
也就是說,咱們一旦還原了歷史版本,想要再次還原回去,那麼就回不去了。
如此一來,一旦錯了。咱們怎麼辦呢?

  • git reflog:查看將來歷史更新點
 
19956127-abcbba04ff39b06e.png
 
 
19956127-a90fe9ee64ea6139.png
 

2.4.3 Git的標籤使用

前面回滾使用的是一串字符串,又長又難記
git tag <標籤> -m "描述"
每次提交均可以打一個標籤

  • git tag v1.0 : 給當前提交內容打一個標籤(方便回滾)
    • git tag : 查看當前全部的標籤
    • git show v1.0 :查看當前1.0版本的詳細信息
    • git tag v1.2 -m "描述"
    • git tag -d v1.0 :刪除以前的v1.0標籤
 
19956127-85148f792b72e73f.png
 
 
19956127-e26a5fca4e87f18e.png
 
 
19956127-9c895dddec92b51d.png
 
 
19956127-7d77e1ce130d5e6b.png
 
 
19956127-1044397a4ade8944.png
 
 
19956127-3210d0f922a21f81.png
 

2.5 gitignore文件

  • 爲何使用.gitignore文件
    • 大量與項目無關的文件全推到遠程倉庫上,同步的時候會很是慢,且跟編輯器相關的一些配置推上去以後,別人更新也會受到影響。因此,咱們使用該文件,對沒必要要的文件進行忽略,使其不被git追蹤。
    • 通常狀況下, .gitignore文件,在項目一開始建立的時候就建立,並推送到遠程服務器上。這樣你們初次同步項目的時候,就是用到該文件,避免之後,團隊成員把與項目無關的文件,傳到遠程服務器上。
  • gitignore文件匹配規則
    • *.log 表示忽略項目中全部以.log結尾的文件
    • 123?.log 表示忽略項目中全部以123加任意一個字符的文件
    • /error.log 表示忽略根目錄下的error.log文件
    • **/java/ 匹配全部java目錄下的全部文件
    • !/error.log 表示在前面的匹配規則中,被忽略了的文件,你不想它被忽略,那麼就能夠在文件前加歎號
 
19956127-999ef44315fea67f.png
 
 
19956127-b807aaed3455a3be.png
 
 
19956127-8f73065a431f09b8.png
 
 
19956127-9a4ad8fa91b92ff1.png
 
 
19956127-1c7b1a1ef1fc0850.png
 
 
19956127-d1c39b20e217279a.png
 
 
19956127-9a0a56515d046e16.png
 

三,GIT分支管理

3.1 分支的結構概述

在實際的項目開發中,儘可能保證master分支穩定,僅用於發佈新版本,平時不要隨便直接修改裏面的數據文件。
那在哪幹活呢?幹活都在dev分支上。每一個人從dev分支建立本身我的分支,開發完合併到dev分支,最後dev分支合併到master分支。
因此,團隊的合做分支看起來會像下圖那樣。

 
19956127-8a9455c74ccd0112.png
 

分支管理工做流程:
在工做中,爲了保證master分支穩定,產品經理一般會從master分支上覆制一份代碼做爲dev分支;
而後成員開發A在從dev分支上覆制一份代碼叫作michael;
而後成員開發B再從dev分支上覆制一份代碼叫作bob;
平時開發A和開發B推送和拉取代碼都在本身的我的分支michael和bob上。
當一個新功能開發完畢,或者一個bug修改完畢之後。開發人員會先將代碼變動推送到本身的我的分支,而後再把我的分支的變動合併到dev分支裏;
當開發經理和測試人員拉取dev分支的代碼進行測試之後,若是沒問題,那麼開發經理會把dev分支的變動合併進master版本;
最後,因爲master版本新增了測試過的新功能,那麼就須要進行項目發佈或者代碼上線了。

3.2 GIT本地分支管理

3.2.1 本地分支的建立與切換

  • git branch : 查看當前分支狀況,當前分支前有*號
  • git branch linux : 建立分支
  • git checkout: 檢查本地分支與遠程分支的變動差別
  • git checkout linux:切換分支
 
19956127-c8876a5dff23bddf.png
 

3.2.2 嘗試在linux本地分支進行代碼提交

 
19956127-90f2b72c69644b6d.png
 
 
19956127-9eca05c9b7c98754.png
 
 
19956127-a75f87fea5a9c7b1.png
 

linux分支比master分支新增一行數據

 
19956127-0f3779046fb5e7ab.png
 

說明:

咱們發現切換分支之後,在linux分支修改過的文件數據,徹底還原成了master分支的文件內容

可是這裏存在一個問題,假如咱們在linux分支下,修改了文件,可是並未提交到本地倉庫linux分支,而只是放到了暫存區就切換到master分支的話,那麼會發生什麼呢?

 
19956127-f45007d58e05979f.png
 

說明:

當linux的本地分支倉庫和master本地分支倉庫的代碼不一樣時,若是你沒把變動從暫存區提交到分支倉庫,那麼默認是不能切換分支的。

可是,這裏還有一個問題,假如linux分支和master分支的本地倉庫的代碼相同,可是我仍舊沒把linux分支的變動提交到本地linux分支倉庫,那麼能直接切換master分支嗎?

 
19956127-4f6c7b5126626d3d.png
 
 
19956127-bec891147193fac5.png
 

說明:

若是本地分支倉庫間的代碼一致,那麼就算不把變動提交到本地分支倉庫,那麼也能夠切換分支

在工做中,爲了不意外,在切換分支前,務必要先將暫存區提交或者清空。

 
19956127-479c272da6e8d54a.png
image

3.3 本地分支的合併與刪除

想把linux的工做成果合併到master分支上;
先切換到master分支
git merge linux : 合併linux分支到master
git branch -d linux :肯定合併完成後,能夠放心的刪除Linux分支。

3.3.1 自動合併本地分支

 
19956127-b39ff9b129dd0d63.png
 

3.3.2 本地分支的刪除

 
19956127-aa40082dc2ebdc65.png
 

假如linux分支的變動沒有合併到當前分支,那麼必須用-D參數強制刪除分支

[root@Git01 mycode]# git branch

linux

  • master

[root@Git01 mycode]# git branch -d linux

error: 分支 'linux' 沒有徹底合併。

若是您確認要刪除它,執行 'git branch -D linux'。

[root@Git01 mycode]# git branch -D linux

已刪除分支 linux(曾爲 7212474)。

3.3.3 手動合併本地分支===>本地分支代碼衝突解決方案

當本地分支之間的同名目錄-同名文件-同一行內容不一樣時,在進行分支合併時就會產生衝突,故爲了解決代碼衝突,就須要進行人工手動合併;
在工做中,爲了儘可能避免衝突,通常開發人員之間儘量不負責相同的功能模塊,也就不至於同時修改同一個文件。

 
19956127-aaccfc77509e915d.png
 

說明:

由上可知,本地linux分支的benet.txt文件和本地master分支的benet.txt文件的第五行代碼產生衝突。若是此時,咱們將本地linux分支的變動合併到本地master分支中,那麼就會產生代碼衝突。

合併本地linux分支

 
19956127-d21d0f910391516e.png
 

找出文件衝突內容,並修改。(此時衝突的benet.txt文件裏已經被標註了衝突內容)

 
19956127-1adc95e6ce5a111d.png
 

到了這裏咱們只能手動排除,選擇保留後的內容,假如咱們要保留linux分支的內容,而後再將工做目錄中的變動提交便可人工解決代碼衝突,並完成分支合併

 
19956127-ad32c5237d532e7e.png
 

3.4 GIT遠程分支管理

3.4.1 將linux本地分支代碼和標籤推送到github遠程倉庫的linux分支

在Git01上,建立本地分支linux,複製master分支代碼。

 
19956127-ba4b63b7fa116c5d.png
 

 

 

將本地linux分支推送到遠程github的linux分支

 
19956127-77503c0d2b638e1a.png
image

瀏覽器訪問:https://github.com

 
19956127-3e15608b615dc4d3.png
 

建立本地標籤,並推送到github

 
19956127-7897da8d6e44819d.png
 

瀏覽器訪問:****https://github.com

 
19956127-1388bd5db7f85bac.png
 

3.4.2 從github遠程倉庫克隆一個linux分支到本地linux分支

(1)克隆遠程倉庫master分支後,經過checkout切換成遠程linux分支

在Git02上進行操做

 
19956127-321c18bdf62b3f3f.png
 

說明:

若是clone時不用-b linux指定分支進行克隆那麼默認克隆的都是master分支;咱們能夠經過checkout切換遠程分支的方式對於已經下載下來的master工做目錄進行代碼替換。

 
19956127-a5e241e3db6ec4f5.png
 
 
19956127-b30a077d718cc3c9.png
 

(2)經過git clone -b linux URL直接指定遠程倉庫分支進行克隆

克隆一個遠程分支linux到本地工做目錄(-b linux指定分支)

 

 
19956127-bdcb8856a6c9d932.png
 


原文連接:https://www.cnblogs.com/wsnbba/p/10147256.html
阿里P7移動互聯網架構師進階視頻(每日更新中)免費學習請點擊:https://space.bilibili.com/474380680

相關文章
相關標籤/搜索