回顧Jungle寫碩士論文時,雖不至於“披閱十載,增刪五次”,但也費心思修改了很多次。每修改一次都得把之前的複製備份保存,下圖是部分修改版本的截圖。如果修改20次,那麼本地計算機裏就得保存20個版本的論文!不但佔據本地空間,而且要查找某一次修改點時及其不方便。軟件代碼也是一樣,如何管理日漸龐大的軟件項目,Git和Github就是重要的版本控制和管理工具。
1.Git和Github
1.1.Git
Git 是一個免費並且開源的分佈式版本控制系統,被設計用來快速、高效的管理一切從小到大的項目。
說分佈式之前先了解下集中式。集中式版本控制系統的版本庫存放在中央服務器,開發人員在開發前得從中央服務器獲取最新的代碼到自己電腦上,然後纔可以工作。工作完了,再把新代碼傳到中央服務器去。缺點在於:
- 必須聯網,否則不能訪問中央服務器。而且如果網速慢,下載和上傳代碼會非常慢。
- 如果中央服務器出故障,不但開發人員無法工作,甚至服務器上的代碼可能會丟失。
分佈式版本控制系統,沒有所謂的 “中央服務器” 。每一臺電腦都有一個完整的版本庫,每一臺電腦都可以作爲“中央服務器”。工作時並不需要聯網。如果是團隊協作的話,只需要把修改的文件推送給對方即可。
1.2.Github
GitHub 是一個利用 Git 進行版本控制、專門用於存放軟件代碼與內容的共享虛擬主機服務。
Github 社區地址: https://github.com
1.3.兩者之間的關係
Github 是利用 Git 來進行版本控制的。所以 Git 對於 Github 來說只是一個用來管理項目的工具。但Github的功能遠不止於此。
1.4.註冊Github賬號,本地安裝git
登錄https://github.com可以註冊Github賬號,在Git官網下載Git( http://git-scm.com/download/win)並安裝。安裝完成後鼠標右鍵單擊,菜單中可出現Git bash,即安裝成功。
安裝完 Git ,設置用戶名稱與郵件地址。 這一步是必須的,每一個 Git 的提交都會使用這些信息,不可更改:
$ git config --global user.name "FengJungle"
$ git config --global user.email [email protected]
輸入命令git config --list 可以查看所有配置。
2.Git常用操作實踐
2.1.本地分支關聯遠程倉庫
首先,登錄Github賬號,在Github上創建了一個新的倉庫HelloWorld,這是一個新倉庫,附帶一個README.md文檔。
然後,在本地創建了一個文件夾Git,如何讓本地文件夾和遠程倉庫關聯起來呢?兩種辦法:
(1)本地通過Git bash從遠程上clone,這樣本地就會有一個HelloWorld的文件夾,包含一個README.md文檔。
(2)本地有倉庫或代碼,讓本地和遠程倉庫關聯:
$ git init
$ git remote add origin https://github.com/FengJungle/HelloWorld
這個時候可以通過下列命令查看遠程地址:
$ git remote -v
origin https://github.com/FengJungle/HelloWorld (fetch)
origin https://github.com/FengJungle/HelloWorld (push)
但此時,本地和遠程還沒有關聯起來,還需要進行下面的步驟,否則不能pull或push:
$ git branch --set-upstream-to=origin/master master
如果運行這一行命令後提示
fatal: branch 'master' does not exist
那麼需要運行
$ git pull origin master --allow-unrelated-histories
或者可能是本地倉庫不在master分支上,則checkout回本地分支
$ git checkout master
此時即可以pull代碼了。
2.2. pull代碼
$ git pull
2.3.管理本地代碼
本地寫了個打印Hello World功能的代碼,保存在HelloWorld.c文件裏。如何將其push到遠程倉庫呢?首先要了解下工作區和暫存區。本地代碼(工作區)通過git add加入到暫存區(staged),暫存區代碼通過git commit添加到本地倉庫裏。當然,暫存區的文件可以通過git reset HEAD <file>返回到本地工作區。通過git status可以查看每一個文件的狀態。
總結如下:
加入修改了一個文件hello.c
$ git add hello.c # 將本地工作區的hello.c添加到暫存區
$ git reset HEAD hello.c # 將暫存區的hello.c撤銷,返回到本地工作區
$ git status # 查看文件狀態
$ git commit # 將暫存區的hello.c提交到本地倉庫
修改了本地工作區的文件Hello.c,下列命令可以撤銷該修改
$ git checkout Hello.c
2.4.push代碼到遠程倉庫
$ git push
接下來在Github上就可以看到本地已經修改的代碼了。
2.5.其他常用命令
$ git log # 查看歷史提交
$ git reflog # 查看歷史命令
3.學習網站
- 廖雪峯的官方網站:https://www.liaoxuefeng.com/wiki/896043488029600
- Learn Git Branching:https://learngitbranching.js.org/
- Pro Git book:https://git-scm.com/book/zh/v2
4.Git常見異常處理
Updates were rejected because the tip of your current branch is behind
在push的時候報“Updates were rejected because the tip of your current branch is behind”
這是由於遠程repository和我本地的repository衝突造成。解決辦法有兩個:
1.強制push
git push -u origin master -f
但既然是強制的,就可能有風險,比如破壞遠程的修改。
2.先pull,修改後再push
git pull
## 修改後
git push
commit沒有change ID
這一條是在gerrit中,使用Git提交代碼時,遇到missing Change-Id in commit message footer。這是因爲沒有安裝hooks鉤子。
運行下面兩條命令,再commit即可。注意第二條命令的commit-msg和${gitdir}之間有個空格,否則命令運行不成功。
$ gitdir=$(git rev-parse --git-dir)
$ scp -p -P 29418 [email protected]:hooks/commit-msg ${gitdir}/hooks/
修改之前提交的commit信息
當想修改之前某次commit的註釋信息,或者爲之前某次commit增加change ID,可以按照如下的方法:
# 假設你需要修改倒數第n次commit的提交信息
$ git rebase -i HEAD~n
# 進入編輯模式,會出現類似以下的內容
pick 6608e22 修改代碼結構調整導致不能正常顯示的問題
pick 1d381cd 菜單切換可用
...
# 將需要修改的commit的那一行的pick修改爲edit,然後保存退出
# 然後輸入
$ git commit --amend
# 進入你需要修改的commit編輯界面,編輯後保存退出
# 修改結束後,輸入以下命令返回到最新的commit
$ git rebase --continue