Git基本操作和Github的使用
本文大部分來自對廖雪峰Git教程 的學習,結合自己的體會,初步掌握Git的使用方法和Github的工作方式。
不會很難,但是瑣碎,所以多實踐,否則記不住。
1. 版本管理系統
為什麼要管理版本,有實際開發經歷的人都有體會,就不需要多說了。這就是水和空氣一樣,那麼重要,那麼天然。
1.1 集中式
從中央伺服器獲取檔案,修改後送回
集中式是比較自然和容易理解的一種方式。大家都從一個伺服器下載文件和程式碼,修改後再送回去,這樣就完成了版本控制和多人協作。
早起比較廣泛使用的大部分是集中式的版本管理工具:
- CVS
- SVN
- MKS
那麼集中式版本管理工具的短板是什麼呢。
- 必須聯網,否則不能工作
- 效能很差
效能很差這個沒有異議,確實很慢,以前在老東家使用MKS作為版本管理工具,效能瓶頸非常惱人。SVN的效能強於MKS,但是仍然不能令人滿意。
必須聯網這一條並不是說不聯網不能修改檔案,意思是不聯網的話,只能修改本地儲存的檔案,不能進行版本控制,也就是說如果1天都連不上網,那麼這一天的修改都只能一股腦的在下次能聯網的時候推上去。
1.2 分散式
每個人的電腦多有一份版本的拷貝,中央伺服器不是必須的。
分散式與集中式比較起來,我感覺最顯著的差別是本地修改的時候可以有自己的版本迭代,並不需要經常的與中央伺服器互動。
分散式版本管理工具並不是說完全不用中央伺服器。中央伺服器可以起到交換各自修改的作用,本地完成修改以後,可以推送到遠端伺服器上,與其他人協作工作。
分散式版本管理工具比如
- BitKeeper
- Mecurial
- Git
Git太流行,主要的有點是
- 效能好
- 分支管理優秀
這篇文章就是介紹Git的基本用法和一個流行的遠端庫託管機構Github。
2. Git的安裝
2.1 Linux
Linux下是否有安裝Git,簡單敲一下命令就知道了
git
根據提示資訊就知道是否安裝了,如果沒有安裝,我使用的ubuntu,那麼apt-get一下就可以:
sudo apt-get install git
2.2 Mac
我沒有Mac,所以也沒有關注過怎麼安裝。自行baidu吧。
2.3 Windows
Windows下也是可以安裝Git的,安裝以後會提供一個Git的shell環境。
Win下的Git軟體叫msysgit
下載安裝即可,用的不多,這裡不討論。
2.4 初次配置
Git使用,需要使用使用者名稱和郵箱作為個人的ID
第一次使用的時候,需要設定一下個人的資訊,包括使用者名稱和郵箱,通過命令:
git config --global user.name XXX
git config --global user.email YYY@ZZZ
這裡–global 引數表明這是全域性的設定,這臺電腦上所有的Git倉都會使用這個使用者名稱和郵箱。當然也可以位不同的Git倉使用不同的使用者名稱和郵箱。
3. Git使用
3.1 初始化倉庫
Git的檔案倉庫叫做Repository
在需要建立倉庫的資料夾下,輸入以下命令建立一個Git倉:
git init
看到提示資訊,倉庫建立成功。
3.2 新增檔案
有了倉庫以後,可以向其中新增檔案。沒有手動新增過的檔案,雖然存在與Git倉庫資料夾內,也不會受到Git的管理。
新增檔案通過以下命令:
git add [file name]
git add *.c
git add .
如果要提交不止一個檔案的修改,也是沒有問題的,可以反覆使用git add,新增多個檔案到暫存區,然後一次性的提交到倉庫裡。或者在一次add中帶有多個檔名作為引數,或者通過萬用字元,“.”等引數新增多個檔案進去。
git add 還有其他引數,可以參考:
git add只是提交了修改到暫存區,關於暫存區的概念,下邊“Git的幾個分割槽”會詳細介紹。檔案的提交併沒有結束,想要真正提交到庫上,還需要以下命令
git commit -m "This is a description of the commit"
提交成功後有提示:
- 4個檔案有修改
- 建立了4個檔案
3.3 修改檔案
3.3.0 Git的幾個分割槽
Git 一共有3個區域的概念
- 工作區 working directory
- 暫存區 stage
- 倉庫分支
這3個區域,按照層級結構,逐層關聯。即工作區和暫存區可以相互影響,暫存區和倉庫分支可以相互影響,但是工作區和倉庫分支並不能直接相互影響。下文的修改撤銷,會對這個問題進行描述。
工作區
工作區就是本地修改檔案的工作目錄。工作區並不受到Git倉庫的管理,可以任意的修改和增刪檔案。
暫存區
暫存區已經受到Git的管理,所有檔案的修改,都需要首先提交到暫存區。前文提到的git add命令,就是將工作區的修改提交到暫存區的命令。
倉庫分支
Git的分支比較靈活,可以有一個遠端的分支,一般命名位origin,在中央伺服器上;本地一個初始的分支,命名為master。本地還可以建立任意多個分支。每次git commit,都是把暫存區的修改,提交到當前的分支上。
關於分支的建立,合併和推送,下文會有說明。
3.3.1檢視Git倉庫狀態
最經常用的一個Git 命令,就是檢視當前Git倉庫的狀態:
git status
看到的結果可能如下
這裡提示的資訊挺全的
- 有一個檔案修改了,1.c
- 目前可以做的動作有
- git add 把這個檔案的修改新增進暫存區
- git checkout [file name] 或者 git checkout – [file name] 恢復這個檔案,取消修改
現在用git add新增這個檔案的修改,再次用git status檢視狀態
提示資訊發生了變化,提示到
- git reset HEAD [file] 將暫存區的修改取消,恢復到Git倉中的檔案狀態
- git commit 提交這個修改到Git倉中,使這個修改在Git倉中生效
3.3.2 檢視檔案改動
上面的git status只能看到哪個檔案被修改了,如果向看具體怎麼改的,需要用到另一個命令:
工作區和暫存區的檔案比較
git diff [file]
工作區和版本庫的檔案比較
git diff HEAD [file]
是的,這是Unix標準的diff格式檢視命令。
上面改動的1.c檔案,已經加入到暫存區中,所以用git diff檢視是沒有結果的,工作區和暫存區檔案一樣。應該用git diff HEAD:
3.3.3 檢視修改記錄
想要檢視之前提交的各個修改都是什麼,需要用到
git log
git log --pretty=oneline
git log --graph
其中能夠看到的資訊是這個提交的id,commit id,提交者,時間,提交的時候 -m 後面雙引號括住的提交資訊。
commit id是一串雜湊值,可以用這個雜湊值,或者只是前面若干字元,代表這個commit。
git log的其他引數,可以自己試試。
3.3.4 撤銷之前的修改
撤銷修改,包括撤銷3個區的改動,工作區,暫存區和倉庫分支的改動,下面分別說明
所謂修改撤銷,就是恢復到上一個已經儲存過的檔案狀態,取消從上一個狀態到當前所做的改動。
- 工作區
- 工作區的修改,如果想要撤銷,只能通過暫存區儲存的該檔案的上一個狀態來恢復。使用的命令是git checkout [file], git checkout – [file]。這個命令執行以後,工作區的檔案,就可以恢復到與暫存區一致的狀態。
- 暫存區
- 暫存區的修改,如果想要撤銷,只能通過倉庫分支儲存的該檔案的上一個狀態來恢復。使用的命令是git reset HEAD [file]。這個命令執行以後,暫存區的檔案,就可以恢復到與倉庫分支一致的狀態。
- 倉庫分支
- 倉庫分支的修改,如果想要撤銷,只能通過再次提交一個修改。暫存區通過git reset HEAD^,可以恢復成倉庫分支上一個版本的狀態,更多細節參考下文的版本回退。
3.3.5 刪除檔案
刪除檔案命令
git rm [file]
注意 本地刪除檔案,參考git add命令表格,可以通過git add的某些選項和git rm來完成。
這些命令執行以後,檔案的刪除資訊就提交到暫存區了,還需要通過git commit來提交到倉庫分支,最終生效。
工作區刪除了,但是是誤刪除,想要恢復怎麼辦
上一節撤銷修改提到,恢復工作區的方法,恢復被刪除的檔案同樣適用。git checkout [file] 即可。
3.4 版本回退
版本的表示
-HEAD
-HEAD^
-HEAD^^
-HEAD~100
這裡的版本回退,指的是倉庫分支版本的回退。上面的幾個版本表示方法,都是倉庫分支的版本表示方法。當前版本,前一個,前兩個,前100個。
版本回退的命令是
git reset HEAD^
git reset [commit id]
git reset --hard HEAD^
git reset --hard [commit id]
–hard的作用
一併將工作區和暫存區都恢復到目標版本的狀態。如果沒有這個選項,將只有倉庫分支指向的版本發生變化,工作區和暫存區都不動,通過git status能看到版本間的差異。
回退錯了,怎麼恢復到最新的版本
回退版本之後,git log檢視到最新的就是回退之後的版本,更新的版本已經在git log中看不到了。這樣就不能通過git reset -hard [commit id]來恢復到之前的新版本。
HEAD也變成了這個稍老一些的版本,不能通過git reset –hard HEAD來恢復。
比如已經進行了幾次git commit,版本庫增加了幾次提交,用git log檢視版本庫:
此時回退版本庫,回退到最開始的狀態,最後2個提交放棄,那麼通過命令:
git log HEAD^^
檢視log:
可以看到,最後2此提交已經看不到了。那麼如果這個時候反悔了,還是想要包括最後的2次提交怎麼辦呢,在git log裡邊已經看不到ID號了。還是有辦法的,通過以下命令:
git reflog
這裡邊記錄了所有的log,可以在這裡找到丟失的commit id,通過git reset –hard [commit id]恢復到之前的新版本。
git reset a9af60c
那麼就恢復到“update 3.txt”這個版本了。
3.5 分支管理
3.5.0 多分支工作方式
Git上多分支的工作方式如圖
- 主線master,僅用來發布版本
- dev分支,大家日常工作的分支
- 個人分支,每個人都工作在自己的分支上,階段性的merge到工作分支dev中
- 個人還可以根據需要,建立更多的分支,修改完成後,merge到個人分支上
3.5.1 建立分支
git checkout -b [branch name]
建立分支,同時切換到這個分支上,相當於2條命令
git branch [branch name]
git checkout [branch name]
3.5.2 檢視分支
git branch
檢視所有分支的資訊,包括有多少個分支,當前處在哪個分支上。
3.5.3 修改分支
切換到哪一個分支,當前就在哪個分支上。
所有的修改,都提交到當前的分支上了。
可以在不同的分支之間隨意切換,通過
git checkout [branch]
比如上圖
- 切換到dev,那麼dev的HEAD就是當前的HEAD
- 切換到master,master的HEAD就是當前的HEAD
3.5.4 合併分支
不同的分支用於不同的修改,最終還是需要合併到一起的。
分支合併的方式是
- 切換到主分支(或者相對主分支)
- 通過命令git merge合併
git merge [branch name]
分支合併的FastForward模式
- ff模式,合併進來的分支的HEAD,作為主分支的新的HEAD
- 非ff模式,產生一個新的HEAD,需要引數-m 提供描述資訊
ff模式和非ff模式的區別,是在log中能不能看出來曾經有過一個分支。ff模式是看不出來的。
所以為了保留完整的log,建議都使用非ff模式合併分支。
git merge --no-ff -m "description" [branch name]
3.5.5 刪除分支
合併以後的分支,即可以刪除了。
刪除分支的命令是
git checkout -d [branch name]
3.5.6 衝突解決
發生衝突的場景一般是,多人共同工作在一個分支上,分別做了各自的修改,然後需要merge到一起。
比如下圖
圖中,feature1分支從master分出來,之後master又merge了別的分支,增長了版本。
那麼feature1如何合併入分支master呢。
- 在feature1上提交merge
- 會提示有衝突,比如下圖是一個文字檔案,在master上和在feature1上的版本是不同的,圖中所示就是這個檔案被Git修改標記成了這個樣子
- 此時需要手動修改這個檔案,將最終的修改結果保留到檔案中
- 再次提交merge,會在master上再增長一個版本
在log中如何檢視分支合併資訊
git log --graph --pretty=oneline
3.5.7 保護現場
什麼是保護現場,為什麼要保護現場
從前面的分支操作過程可以看到,任意的切換分支,是可以的。
那麼問題來了,切換分支以後,倉庫分支是切換了,工作區和暫存區是否隨著切換?
- 答案是否定的,工作區和暫存區只有一份,所有的倉庫分支共用
如果所有的倉庫分支共用一份工作區和暫存區,那麼切換到新分支的時候,工作區和暫存區的狀態,會影響新的分支,造成混亂。
解決工作區和暫存區在不同分之間共享的方法–保護現場
- 保護現場
- 列出儲存過的現場
- 恢復現場
git stash
git stash list
git stash pop
pop以後,該現場就無效了,清理儲存過的現場還有其他方式,請自行檢視幫助文件
3.5.8 多人協作
前面提到過多人協作的方式。
使用中央伺服器作為交換修改的伺服器,平時自己工作在本地倉庫中,需要時推送修改到遠端倉庫。
本地倉庫是不需要聯網的,遠端倉庫需要聯網。
那麼遠端倉庫相關操作:
檢視遠端倉庫資訊
git remote
git remote -v
拉取遠端倉庫的最新狀態
git pull
推送本地分支的修改到遠端倉庫
git push [remote branch] [local branch]
master和dev是需要協同工作的,所以應該部署在遠端倉庫,作為遠端倉庫的兩個分支
- origin/master
- origin/dev
如果遠端有dev分支,那麼本地建立對應分支的命令:
git checkout -b dev origin/dev
本地分支,不需要在遠端倉庫中建立分支
3.6 標籤
標籤的作用,是給某個特定的版本節點,新增一個可讀的名字。否則所有的版本節點都用commit id標識,可讀性很差。
比如master上的各個release版本,如果用標籤標明,就很容易瞭解和做相應的處理。
3.6.1 新增
切換到想要新增標籤的分支,通過以下命令
git tag [tag name] //為當前版本新增標籤
git tag [tag name] [commit id] //為某個commit id版本新增標籤
git tag -a [tag name] -m "tag information" //新增描述資訊
git tag -s [tag name] -m "tag information" //用PGP簽名
3.6.2 檢視
檢視標籤的命令
git tag //檢視有多少個標籤
git show <tag name> //檢視某個標籤的說明資訊
3.6.3 刪除
刪除標籤的命令
git tag -d [tag name] //本地的
git push origin :refs/tags/[tag name] //遠端的
3.6.4 推送
推送標籤到遠端的命令
git push origin [tag name]
git push origin --tags
3.7 Git配置
Git的配置一般通過Git配置命令外完成,最主要的有以下幾個
- 顏色
git config --global color.ui true
- 忽略檔案
- Git工作區根目錄下建立檔案.gitignore
- 具體配置方法,見說明
- 別名
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
/* 配置了這個以後,使用git lg 就可以了,就會使用上述配置來列出log */
- 配置資訊作用域
- 有–global的,使用者域有效
- 沒有–global的,倉庫域有效
- 具體反映在不同層級目錄的.git/config
3.8 自己搭建Git伺服器
- 使用ubuntu或者debian系統的電腦
- 安裝git
- 建立一個名位git的使用者,執行git服務
sudo addusr git
- 蒐集公鑰,每行一個寫入
/home/git/.ssh/authorized_keys
- 建立裸倉,倉庫目錄下執行
sudo git init --bare <repo name>.git
sudo chown -R git:git sample.git
- clone遠端倉庫
git clone [email protected]<server>:<path>/<repo name>.git
4. Github
4.1 環境準備
4.1.1 祕鑰對
遠端倉庫登陸和使用需要使用者的公鑰,使用者的簽名需要私鑰。所以需要生成一對公鑰和私鑰。
檢查以下目錄位置,是否已經生成了祕鑰對
/*使用者目錄下 .ssh*/
.ssh/id_rsa //私鑰
.ssh/id_rsa.pub //公鑰
/*如果沒有,通過以下命令生成祕鑰對*/
ssh-keygen -t rsa -C "[email protected]"
Github配置
上傳公鑰
可以上傳多個公鑰,不同的電腦各生成一個,關聯到同一個賬戶
4.2 遠端倉庫操作
4.2.1 關聯
首先在Github上建立新的repository,然後在本地目錄下通過下面命令,關聯遠端倉庫到當前資料夾:
git remote add origin [email protected].com:[username]/[repository].git
其中[email protected]:xxx,是在github的repository頁面找到的地址:
origin是遠端倉庫的分支名稱。
4.2.2 clone
如果本地還沒有任何相關的檔案,那麼從遠端倉庫直接克隆一個到本地比較乾淨。
通過以下命令:
git clone [email protected].com:xxxx/yyyy.git
github地址參考4.2.1節的說明。
4.2.3 推送
推送命令:
git push -u origin master //第一次,用-u,後續不用
git push origin master //如果origin下還有分支,用origin/master, origin/dev
第一次推送,會有提示,需要確認以下對端是否可信
4.2 倉庫間關係
github上,協作的工程有它的原是倉庫,參與的人自己fork一份自己的倉庫,在自己的倉庫上修改。
4.1 使用步驟
- 找到專案頁面
- 點fork複製到自己的頁面
- git clone到本地
- 提交修改到自己的github倉庫
- 提出pull request,發給專案原始頁面,建議其包含這個修改