Git 之五 通信协议(HTTPS、SSH、Git)、使用远程仓库(GitHub、GitLab、Gitee等)
寫在前面
??Git 的官網上有很詳細的使用教程(當然有翻譯版本),具體地址是 https://git-scm.com/book/zh/v2。唯一不足就是,很多講解并沒有實機演示。但是,毫無疑問,官網資料是最全面的!如果有任何疑問,可以去官網看看!
協議
??Git 通常也會有個遠程倉庫。用來協調各個參與者的工作!這與上一代集中式版本控制系統的作用基本類似。一個遠程倉庫通常只是一個裸倉庫(bare repository),即一個沒有當前工作目錄的倉庫。 因為該倉庫僅僅作為合作媒介,不需要從磁盤檢查快照;存放的只有 Git 的資料。 簡單的說,裸存倉庫就是你工程目錄內的 .git 子目錄內容,不包含其他資料。
??Git 本地倉庫與遠程倉庫之間的交互需要遵循一定的協議。Git 可以使用四種主要的協議來傳輸資料:本地協議(Local),HTTP 協議,SSH(Secure Shell)協議及 Git 協議。
本地協議(Local)
??本地協議主要是針對版本庫就是硬盤內的另一個目錄的情況。常見于團隊每一個成員都對一個共享的文件系統(例如一個掛載的 NFS)擁有訪問權。使用本地協議,就可以從本地版本庫克隆(clone)、推送(push)以及拉取(pull)代碼。這與操作其他遠程倉庫一樣!
??如果在 URL 開頭明確的指定 file://,那么 Git 的行為會略有不同。 如果僅是指定路徑,Git 會嘗試使用硬鏈接(hard link)或直接復制所需要的文件。 如果指定 file://,Git 會觸發平時用于網路傳輸資料的進程。如下:
我們可以使用本地協議來模擬學習 Git。如下:
在 Git 中,裸存倉庫通常是 名 + .git 的形式!
Git 會給出提示,我們正在克隆一個裸存倉庫!注意,我們克隆倉庫時,沒有指定路徑(含名稱),因此默認名稱就是遠程倉庫的名字。
成功推送之后,在遠程倉庫中會有對應的記錄。如上圖所示的遠程倉庫的 objects 目錄。
其實,使用遠程協議的流程與本地協議是一樣的!
HTTP 協議
??根據 Git 官網的描述,Git 通過 HTTP 通信有兩種模式。 在 Git 1.6.6 版本之前只有一個方式可用,十分簡單并且通常是只讀模式的;Git 1.6.6 版本引入了一種新的、更智能的協議,讓 Git 可以像通過 SSH 那樣智能的協商和傳輸數據。這兩種模式分別被稱為 啞(Dumb) HTTP 協議 和 智能(Smart) HTTP 協議。
??啞 HTTP 協議里 web 服務器僅把裸版本庫當作普通文件來對待,提供文件服務。智能(Smart) HTTP 協議在服務端運行了兩組進程,分別負責上傳[客戶端的進程連接到服務端進程]和下載數據[客戶端的進程連接服務端],它們可以讀取本地數據,理解客戶端有什么和需要什么,并為它生成合適的包文件。
??每次推送,Git 服務器會詢問用戶名與密碼。 默認情況下它會在終端中提示服務器是否允許你進行推送。如果不想在每一次推送時都輸入用戶名與密碼,你可以設置一個 “credential cache”。 最簡單的方式就是將其保存在內存中幾分鐘,可以簡單地運行 git config --global credential.helper cache 來設置它。在 Windows 系統中,在輸入過用戶名密碼之后,會被系統給保存下來!我們可以如下圖所示的位置進行修改:
??由于我們有搭建服務器,因此這個不好驗證。但是 Git 官網有比較詳細的介紹這兩種協議的具體工作流程:https://git-scm.com/book/zh/v2/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE
SSH(Secure Shell)協議
??架設 Git 服務器時常用 SSH 協議作為傳輸協議。 因為大多數環境下服務器已經支持通過 SSH 訪問 —— 即使沒有也很容易架設。 SSH 協議也是一個驗證授權的網絡協議;并且,因為其普遍性,架設和使用都很容易。
??通過 SSH 協議克隆版本庫,你可以指定一個 ssh:// 的 URL:$ git clone ssh://user@server/project.git 或者使用一個簡短的 scp 式的寫法:$ git clone user@server:project.git。你也可以不指定用戶,Git 會使用當前登錄的用戶名。
??現有的很多平臺(例如 Github)都是以 SSH 秘鑰的方式進行通信的!因此如果我們要以 SSH 的方式訪問遠程倉庫,則根據 SSH 協議,必須要生成我們 Key。Git 客戶端默認是帶有 OpenSSH 的,配置方式是使用命令ssh-keygen -t rsa -C "youremail@example.com",如下:
Git 協議
??這是包含在 Git 里的一個特殊的守護進程,它監聽在一個特定的端口(9418),類似于 SSH 服務,但是訪問無需任何授權。 要讓版本庫支持 Git 協議,需要先創建一個 git-daemon-export-ok 文件 —— 它是 Git 協議守護進程為這個版本庫提供服務的必要條件 —— 但是除此之外沒有任何安全措施。 要么誰都可以克隆這個版本庫,要么誰也不能。 這意味著,通常不能通過 Git 協議推送。 由于沒有授權機制,一旦你開放推送操作,意味著網絡上知道這個項目 URL 的人都可以向項目推送數據。
??Git 協議是現存最快的傳輸協議。如果你在提供一個有很大訪問量的公共項目,或者一個不需要對讀操作進行授權的龐大項目,架設一個Git守護進程來供應倉庫是個不錯的選擇。它使用與 SSH 協議相同的數據傳輸機制,但省去了加密和授權的開銷。
??Git 協議消極的一面是缺少授權機制。用 Git 協議作為訪問項目的唯一方法通常是不可取的。一般的做法是,同時提供 SSH 接口,讓幾個開發者擁有推送(寫)權限,其他人通過 git:// 擁有只讀權限。Git 協議可能也是最難架設的協議。它要求有單獨的守護進程,需要定制,需要設定 xinetd 或類似的程序,而這些工作就沒那么輕松了。該協議還要求防火墻開放 9418 端口,而企業級防火墻一般不允許對這個非標準端口的訪問。大型企業級防火墻通常會封鎖這個少見的端口。
關聯遠程倉庫
??Git 通常也會有個遠程倉庫。使用 git init 方式創建的本地倉庫只能本地使用,其沒有與任何遠程倉庫關聯!遠程倉庫的增、刪、改、查都是通過 git remote 命令來實現。
??在 Git 中,會為關聯的遠程倉庫創建一個本地名稱,默認不顯示指定時為 origin,這樣我們在與遠程倉庫通信時,直接使用本地名稱就可以了!例如,我們要將代碼推送到以上關聯的遠程倉庫,直接使用 git push origin 就可以了。git remote 命令的格式如下:
以下是一些常用的命令參數:
- -v、--verbose:用于列出關聯的遠程倉庫,格式為:本地名稱 + 遠程倉庫地址。該參數必須緊跟在 git remote 之后。如下圖:
- git remote add:命令格式:git remote add [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=<fetch|push>] <name> <url>。關聯一個遠程倉庫 <url>,本地名稱為 <name>。
- git remote rename:命令格式:git remote rename <old> <new>。將名為 <old> 的遠程倉庫名重命名為 <new>。
- git remote rm:命令格式:git remote remove <name>。其中,參數 --rm 是 --remove 的簡寫。刪除關聯的名為 <name> 的遠程倉庫的關聯信息。
??與遠程倉庫相關的配置,均位于 工作目錄下/.git/config 文件中,這是個文本文件,我們也可以直接打開改文件進行修改。
還有一點就是,一個本地倉庫可以關聯多個遠程倉庫! 如下圖所示是關聯了兩個遠程倉庫之后的情況。
如上所示,建議在關聯遠程倉庫的時候,指定一個本地名稱,這樣我們就可以很容易的知道關聯情況。這個在我們往遠程倉庫提交代碼是很有用處!
關聯遠程分支(upstream)
??有一種情況,我們建立的遠程倉庫并不是空的(里面有文件),在使用以上命令關聯本地倉庫和遠程倉庫之后,我們還并不能將本地修改提交到遠程倉庫!第一點是因為,由于遠程倉庫本身有內容,我們的本地倉庫與遠程倉庫并不是同步的!我們必須要將本地倉庫與遠程倉庫同步之后,才可以正常提交代碼。第二點是因為,多分支的問題,我們必須要關聯分支!如下圖所示:
從上圖中我們不難看出兩者的區別!遠程倉庫不空時,具體操作步驟如下:
當然,如果遠程倉庫本身是空的(沒有任何文件),這步驟如下:
#git初始化 git init #關聯遠程倉庫 git remote add --origin Github_xxx 遠程倉庫地址 #將全部文件加入git版本管理 .的意思是將當前文件夾下的全部文件放到版本管理中 git add . #提交文件 使用-m 編寫注釋 git commit -m "注釋" #推送到遠程分支 git push克隆遠程倉庫
??如果本地倉庫是直接使用 git clone 命令克隆自一個指定的遠程倉庫,則默認本地倉庫就是和克隆的倉庫關聯的!我們可以使用 git remote 命令來修改關聯信息。例如,如果在克隆時,使用的命令是git clone 遠程倉庫地址 而不是 git clone --origin 本地名字,那么,默認使用 origin 來表示我們關聯的遠程倉庫,我們可以使用 git remote rename 來更改這個名字!
??在我們想要保存遠程倉庫的文件夾中打開 Bash 命令框,執行 git clone https://github.com/ZCShou/N_W_Z_1.git命令即可(注意將以上倉庫地址換為自己的)。如下圖:
??該命令將遠程存儲庫克隆到新創建的目錄中,并為本地存儲庫中的每個分支創建遠程分支關聯,并創建和檢出從遠程存儲庫當前活動的分支派生出來的初始分支。
該命令的完整格式如下:
該命令常用參數如下:
- -o <name>、--origin <name>:指定遠程倉庫的本地名稱為 <name>,而不使用默認的 origin。
- -b <name>、--branch <name>:用于克隆名為 <name> 的遠程分支,而不是以 HEAD 創建分支。在非空的倉庫中執行該命令,表示將指定的分支同步到當前倉庫!
- <repository>:要克隆的(可能是遠程的)存儲庫。
- <directory>:指定保存克隆的倉庫的本地目錄名稱。 如果沒有明確給出目錄,則使用遠程庫名字在當前目錄。只有當目錄為空時,才允許克隆到現有目錄。
??克隆之后,默認會使用 git fetch 將更新所有遠程跟蹤分支,并且沒有參數的 git pull 將另外將遠程主分支合并到當前主分支中(如果有的話)。其中也會有個 .git 的文件夾!
??使用以上命令之后,本地倉庫就會和以上指定的遠程倉庫管理關聯。在 Git 中,會為關聯的遠程倉庫創建一個本地名稱,不顯示指定時默認為 origin。我們可以在以上命令中使用參數 --origin 本地名稱 來指定本地名稱(git clone --origin NWZ_xxx https://github.com/ZCShou/N_W_Z_1.git)。
遠程倉庫名字 “origin” 與分支名字 “master” 一樣,在 Git 中并沒有任何特別的含義一樣。 同時 “master” 是當你運行 git init 時默認的起始分支名字,原因僅僅是它的廣泛使用,“origin” 是當你運行 git clone 時默認的遠程倉庫名字。 如果你運行 git clone -o booyah,那么你默認的遠程分支名字將會是 booyah/master。
git fetch 與 git pull
??一旦遠程主機的版本庫有了更新,需要先將這些更新取回本地,否則,在將本地提交到遠程倉庫時會報錯。這時就要用到 git fetch 或者 git pull 命令。
??該命令用來從一個或多個其他存儲庫中獲取分支和/或標記(統稱為“refs”),以及完成其歷史記錄所需的對象。 該操作會更新遠程跟蹤分支。行完成后,你將會擁有那個遠程倉庫中所有分支的引用,可以隨時合并或查看。
??必須注意 git fetch 命令會將數據拉取到你的本地倉庫——它并不會自動合并或修改你當前的工作。 當準備好時你必須手動將其合并入你的工作。而運行 git pull 通常會從最初克隆的服務器上抓取數據并自動嘗試合并到當前所在的分支。簡單來說,git pull = git fetch + git merge
git push
??該命令用來將本地倉庫(分支)同步到遠程倉庫(分支)。該命令將使用本地引用更新遠程引用,同時發送完成給定引用所必需的對象。
git push -u Docs master #這里的Docs 就是上面 起的別名; -u 表示:以后操作,默認的倉庫為Docs,默認關聯的分支為master使用上面的-u 以后,后續很多操作都可以簡化,如下:
git push 命令: 格式:$ git push <遠程主機名> <本地分支名>:<遠程分支名> 舉例:$ git push Docs master:master # 將本地master分支推送到遠程倉庫Docs的master分支 # 如果省略本地分支名,則表示刪除指定的遠程分支,因為這等同于推送一個空的本地分支到遠程分支。例如:$ git push Docs :master# 等同于$ git push Docs --delete master# 如果當前分支與遠程分支之間存在追蹤關系,則本地分支和遠程分支都可以省略。( 即使用 git push -u 關聯的那個)$ git push Docs# 如果當前分支只有一個追蹤分支,那么主機名都可以省略。$ git push代碼托管平臺
??代碼托管平臺主要用來輔助項目開發,同時協調項目程序的開發工作。一般的代碼托管平臺除了提供基本的源代碼版本控制之外,還通常會集成一系列項目輔助開發工具。
Github
??Github 應該是大家最熟悉的一個代碼托管平臺。目前應該是最大的開源軟件托管平臺。針對于個人以及企業,Github 有不同的套餐,具體如下:
??如上圖列出了不同類型的用戶的限制條件。最初,Github 的免費用戶僅可以創建公開倉庫,被微軟在 2018 年 6 月4 日收購之后,現在可以創建無限的公開或者私有倉庫。
??登錄自己的賬號,在賬號下面就可以創建我們自己的倉庫了。
Github 的倉庫支持通過 HTTPS 和 SSH 協議來克隆倉庫。打開倉庫的主頁,就會發下如下:
在使用 SSH 方式的時候,我們必須要將 SSH 的公鑰放到 Github 的賬戶下。至于如何生成 SSH 的公鑰,參見之前的博文即可。具體如下:
特別說明一下,就是創建組織,上圖左側列表中的 Organizations 選項下,我們就可以創建組織,創建組織之后,我們就可以直接在組織中,通過 Github 賬戶名來添加組織成員。
GitLab
使用方式與 Github 差不多。https://about.gitlab.com
Bitbucket
使用方式與 Github 差不多。Github 中的組織這里被稱為 Team。
碼云
碼云是開源中國旗下的 Git 代碼托管平臺,依托國內的程序員較多基于平臺中發布項目。目前是獨立平臺運營的。
阿里云Code
https://code.aliyun.com
Azure DevOps
https://dev.azure.com
https://docs.microsoft.com/en-us/azure/devops/?view=azure-devops
參考
總結
以上是生活随笔為你收集整理的Git 之五 通信协议(HTTPS、SSH、Git)、使用远程仓库(GitHub、GitLab、Gitee等)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Git 之四 分支管理
- 下一篇: STM32 之十一 LL 库(low-l