1. 程式人生 > >適合小白的大白話講解--->Git與Github的區別

適合小白的大白話講解--->Git與Github的區別

本文旨在使用通俗易懂的文字,講解版本控制背後的理論,以便你能對程式設計師們如何工作有個全域性概念。本文不涉及程式碼,不用下載啥東西,循序漸進,不關注繁複細節,只有文字和一些不怎麼漂亮的手繪塗鴉。

寫本文的動機

學習任何東西都能在網路上找到如此之多的指導教程,這一直令我驚訝不已。Git 和 Github 也不例外,網路上有大量優秀資源,這些資源要麼只對其中一個,要麼兼顧二者引導你開始學習。以下是我特別喜歡的一些資源:

然而,我發現這些教程總是跳過許多理論知識,直接解釋如何通過命令列或 Github 桌面應用程式使用 Git 。坦白說,如果你只是想知道你的開發團隊談論的到底是什麼,這些指導教程也綽綽有餘了。如上所述,我的目標是對版本控制的整體概念進行簡明扼要地講解,同時希望能讓你瞭解到版本控制是如此酷。

讓我們從最基礎的開始:版本控制

Image credit: weebletheringskite, WordPress

版本控制(Version control):學習它,愛上它,享受它。顧名思義,版本控制系統是任何能讓你瞭解到一個檔案的歷史,以及它的發展過程的系統。之前作為平面設計師時,我常常會遇到這種檔案:

看起來眼熟?儘管上述系統不是一個好用的系統 ,但它確實是一個版本控制系統。更復雜點的例子就像,Google 文件的 “修訂歷史”或  Photoshop 的“歷史”工具。

 開始 Git

Git 是一種專為處理文字檔案而設計的版本控制系統。因為,歸根到底,這就是程式碼的本質:一堆堆以某種方式聯合在一起的文字檔案。Git 是一個可安裝應用,它允許你對你自己所做的更改進行註釋,用以建立易於導航的系統歷史。

(附: “Git”  也是工程師取的名字,我們對市場部同仁感到抱歉)

那麼, Git 做了什麼,是簡單地儲存檔案所做不到的呢?從根本上講,檔案儲存就是一個簡化的版本控制系統,但坦率地說,它並不是一個好用的系統,因為它只能前進。當然,你也許會爭論“撤消”按鈕可以讓你的檔案回滾到以前的狀態。但我們都清楚,“撤消”按鈕有其侷限性,最明顯示的是,在關閉檔案時,檔案的過去也隨之丟失。

另外,檔案儲存是非常個人化的。它不能夠顯示整個系統的歷史,只能夠顯示該檔案的。針對這一點,你可能會想,“嗯,我不是一個工程師,我不需要為系統煩惱”。我願意花些時間來解釋一下,很多事情你認為不是“系統”,而實際上它們就是。

以  Sally為例,她是一個正在寫下一個大冒險奇幻小說系列的作家。Sally 已經寫完該系列小說中的第一本,並把它傳給了她的編輯。此外,由於她才華出眾,在等待編輯的反饋的同時,她還寫了第二本書的前三章。每本書都建立了獨立的 World 檔案。

在某個快樂的日子,Sally  等來了她的編輯關於第一本書的反饋。他擔心年輕的讀者不想讀一系列專寫獸人故事的書,希望她在這個故事中引入一些精靈。關於這點,Sally  嘆了口氣,但很快意識到,她的精靈新角色將帶來始料未及的衝突和曲折的情節。然後,她做了以下事情:

  • 在第一本書中加入新角色,並修改故事情節。
  • 完成第一本書之後,對第二本書的故事情節,進行必要的修改。
  • 所有的這些修改,導致她需要引入某個地理位置到第一本書中,而不是第二本書。
  • 重新編輯第一本書,讓它包含新的地理位置。

終於,她推開了她的鍵盤,確信已經把精靈融入到了她的奇幻世界之中。

你瞧,Sally 實際上在處理一個系統。她的兩本書互相影響。角色、地理位置和故事情節在兩本書中流動交織。然而,遺憾的是,一個月後,她的檔案系統裡什麼都沒有了。Word 的 “文件歷史”工具,或她曾經貼上在顯示屏邊緣用於記錄修改過程的便籤紙,將把所有的變化過程都揉合在一起。

這正是Git 大放光芒之處。如果 Sally 一直結合 Git 使用Word,她就能對所有這些相關的變化做一個關於“將精靈引入到系列”的簡潔小結。她可以看到所有穿插在頁、章節、檔案,以及每本書中的修改記錄,讓她真正地瞭解引入精靈對她的奇幻系列產生的影響。這個“簡潔的小結”就是我們在 Git 領域中所講的提交(commit)

回顧一下。 Git 是一個軟體,它允許你通過提交對一個系統(或一組)檔案的歷史進行註釋。這些提交便是在給定時間點對系統做出的差異“快照”。

那麼,如果我是Sally,我的提交歷史看起來是這樣子的:


Github

到目前為止,一切都還不錯。但是,如果 Sally 同時用到兩臺電腦工作,將會發生什麼呢?問得好。這時,就該用到 Github了。注意,不要和 Git 混淆了。Github 獲取 Git 中的提交歷史,並將其儲存在網際網路上,因此你可以從任一一臺電腦訪問它。你在本機(例如:你當前正在使用的電腦)推送(pushing)提交到 Github,然後,從另一臺新的或不同的電腦上拉取(pulling)這些提交。

讓我們假設上圖為 Sally 的工作流程。她在家裡的臺式電腦(左邊,橘黃色的)上開啟她一天的工作。接下來,她完成了幾個章節的寫作,又做了一些編輯工作,等等。整個過程中,她對工作總共進行了三次策略性的“快照”(Git 提交)。

下午,Sally 常常喜歡帶著她的膝上型電腦(上圖中的右側,藍色的)去咖啡館寫作。今天也不例外。因此,在關閉家裡的臺式電腦之前,她需要確認當前的Git 提交歷史已推送(push)到了線上Github。一旦被上傳到 Github,這些提交記錄就被儲存在遠端倉庫(remote repository)中。

我們先來分析一下幾個計算機術語:遠端(remote)僅僅意味著聯網(與“本地”的意思相反,和之前我們理解到的意思一樣的,代表當前正在使用的電腦)。而倉庫(repository,經常簡寫為“repo”),就是一個具備 Git 超級許可權的資料夾。

因此,Github 就是讓你把工作(通過Git提交進行註解)儲存在了一個指定的線上資料夾(repo)。明白了吧?簡單。

午餐之後,在當地的一家咖啡館中,Sally 拿出了她的膝上型電腦。很明顯,她想接著家裡的工作進度繼續。因些,她從 Github 倉庫上獲取到最新進度的工作。“從 Github 上獲取她的工作”,這一過程就叫拉取(pulling)。再看一下上面這幅圖片,你將看到 Sally 拉取了之前她在家時進行的三個提交。

現在,在她的膝上型電腦上,Sally 有整個系統(包含她的幻想系列的所有文字檔案)的最新的完整副本,並能夠基於上次的進度,繼續工作。她寫了更多的章節,對工作進行了兩次以上的策略“快照”(提交)。最後,Sally 把這些提交推送push)到 Github 上,結束了這一天的工作。這樣第二天上午的時候,在家裡的臺式電腦上就可以取得這些最新進度的工作。

協同工作

好吧,這一切都能說得通。但是, Sally再如何酷,整個專案也只有她一人而已。工程團隊要如何確保他們的工作不會重疊?

簡而言之,建立分支。將你的 Git 提交歷史想像成一棵樹。樹的主幹就是我們談到的主分支。為了讓團隊成員避免彼此牽扯,他們在獨立於他人的隔離區(在一個功能分支)進行工作,然而最終,每個人的工作成果都會被提交到主程式碼庫 (主分支)。

現在,回到 Sally 的例子。她加入了奇幻作家協會,在這裡每個人都與他人合作完成這本書——《奇幻系列生物辭典》。這本辭典更像一本教材,由多個作者共同完成:Sally、Tom 和 Adam。

讓我們來看看《奇幻系列生物辭典》專案的線上 Github 倉庫,現在的情況是:

如上圖所示,樹的類比完全適用於奇幻作家協會在這個專案上的合作情況,倉庫歷史沿主分支向上移動。常規工作流始於每個作者為完成一個工作任務(例如編寫章節內容,或排版章節)而在主分支上建立分支。只有當更改得到其他合作作家的批准時,分支才會被合併到主分支上(請謹記,主分支上的內容,才是最終要釋出的內容)。

當一個分支的內容合併(merged)到主分支時,意味著該分支的內容會覆蓋主分支上的。因此,現有內容的任何更改都將會替代之前的。當然,任何新新增的內容也會新增到主分支。實際上,當分支合併到主分支時,該分支的提交歷史被新增到主分支提交歷史的頂部。

然而,你可能正在思考:人們在本機的工作和之後才推送到 Github 的工作變更是如何連線到一起的呢?

關於這個問題,重點在於:你在 Github 的遠端倉庫是你本機工作專案的一個映象。這意味著,你在自己的電腦裡儲存了該專案(例如:一個已設定可進行 Git 提交的資料夾)的本地 Git 倉庫。在這個本地的 Git 倉庫(再次,這是一個特定術語,指你的電腦裡某個啟用了 Git 功能的資料夾)中,你擁有與該專案相關的所有檔案,在本文的例子中,即《奇幻系列生物辭典》。

它的工作原理很像 Dropbox :你在不同的裝置(你的家庭電腦、辦公室電腦,等等)上建立本地資料夾,進行工作並更新這些檔案。最後,這些操作被同步到網路上。然而,我們知道,Git/Github 工作流還包含了一些額外的步驟。首先,你必須有意識地對某一時刻的工作執行“快照”(即執行一次提交)。然後,你必須特意地推送這些提交(push) 到 Github。只有這樣,你的工作才被同步到網路上的位置(Github 版本庫)。

既然如此,為什麼不自動化該工作流呢?為什麼不讓它像 Dropbox一樣,當你更新本地檔案時,同時自動更新 Github 上的檔案?有很多理由讓我們不這麼做。最主要的理由是——bugs 。同出版界一樣,軟體工程中也不是所有寫過的東西都要保留。有時,你希望實驗一下你的想法,如果實驗失敗,你希望有一種簡單的方式能讓工作快速回滾到之前的正確狀態上。這也是為什麼我們提倡這個經驗法則,即在你試圖用不同的方法編輯或實驗之前,先對當前你希望保留的修改進行提交。頻繁地提交小塊工作有益無害,事實上,許多工程師為自己能做到這一點而感到自豪。

現在,回到《奇幻系列生物辭典》。由於  Sally 對獸族有較深的瞭解,她被挑選為寫獸族章節。但她不想在沒有經過其它合作人員允許的情況下去修改這本書,於是,她建立了一個本地分支,並在該分支上進行寫作和提交。然後,她將本地分支推送到 Github。像往常一樣,Github 的遠端倉庫是本地庫的一個映象,最新進展顯示 Sally 已建立了一個包含部分提交的分支(如下圖所示)。

隨著她對本章節的持續寫作,Sally 進行了更多的提交,並將它們推送到 Github 的線上映象分支。終於,她準備請 Tom 和 Adam 一起對她的工作進行評審。因此,她在 Github 上釋出了一個 Pull Request(釋出請求),這是一個 Github 功能,允許她解釋該分支相對於主分支做了哪些修改。Github 還提供了一個簡易平臺,合作人員可以在該平臺上針對分支的修改內容進行討論,並要求 Sally 在分支合併到主分支之前對一些有異議的內容進行修改。

在對部分內容請求修改後,如上圖所示,Tom 和 Adam 對 Sally 的分支內容很滿意,並決定將她的工作成果合併到 Github 的主分支上。此時,他們所要做的就是將 Sally 之前獨立提交的內容,新增到主分支的提交歷史頂部:

此時,Sally可以切換(或“check out”)到本地計算機上的主分支,並將先前在功能分支(獸人章節分支)中的獨立提交拉取下來。現在她又要在新的主分支上重新開始了:以該主分支為基礎為她的下一步工作建立一個新的本地分支,幫助湯姆編輯有關妖精的章節。因此,這一過程又將重複:

  1. 建立本地分支
  2. 在本地分支上編輯修改,然後提交
  3. 推送提交(Push)到 Github
  4.  建立釋出請求(Pull Request),說明該分支包含了哪些更改
  5. 合併(Merge)分支內容到主分支
  6. 將主分支上的最新提交拉取(pull)到本地
  7. 重複上述步驟

正如你所看到的,這是一個非常流暢的工作流,完美地結合了獨立工作與團隊協作。你本機的 Git 提供了一個絕妙的方法,即通過由你自己控制和策劃的豐富的歷史提交,來建立你工作的各種版本。Github 是一個非常棒的線上版本控制工具,不僅儲存和提供了清晰的視覺化歷史記錄,而且還能進行協同工作和質量控制。

總而言之,我希望我已經說服你去嘗試使用 Git  和 Github 進行任何專案。沒有理由只有工程師能從這個很棒的工具中受益。畢竟,我們也想看到更多有關獸人的故事。

致謝:

本文涉及的術語

  • Version Control(版本控制): 任何一個能夠讓你瞭解檔案的歷史,以及該檔案的發展程序的系統。
  • Git:一個版本控制程式,通過對變更進行註釋,以建立一個易於遍歷的系統歷史。
  • Commit(提交):在指定時間點對系統差異進行的註釋 “快照”。
  • Local(本地):指任意時刻工作時正在使用的電腦。
  • Remote(遠端): 指某個聯網的位置。
  • Repository (倉庫,簡稱 repo):配置了Git超級許可權的特定資料夾,包含了你的專案或系統相關的所有檔案。
  • Github:獲取本地提交歷史記錄,並進行遠端儲存,以便你可以從任何計算機訪問這些記錄。
  • Pushing(推送):取得本地Git提交(以及相關的所有工作),然後將其上傳到線上Github。
  • Pulling(拉取):從線上的Github上獲取最新的提交記錄,然後合併到本地電腦上。
  • Master (branch):主分支,提交歷史 “樹”的 “樹幹”,包含所有已稽核的內容/程式碼。
  • Feature branch(功能分支/特性分支):一個基於主分支的獨立的位置,在再次併入到主分支之前,你可以在這裡安全地寫工作中的新任務。
  • Pull Request(釋出請求):一個 Github 工具,允許使用者輕鬆地檢視某功能分支的更改 (the difference或 “diff”),同時允許使用者在該分支合併到主分支之前對其進行討論和調整。
  • Merging(合併):該操作獲取功能分支的提交,加入到主分支提交歷史的頂部。
  • Checking out(切換):該操作指從一個分支切換到另一個分支。