1. 程式人生 > >Git基本操作和Github的使用

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呢。

  1. 在feature1上提交merge
  2. 會提示有衝突,比如下圖是一個文字檔案,在master上和在feature1上的版本是不同的,圖中所示就是這個檔案被Git修改標記成了這個樣子
    Markdown
  3. 此時需要手動修改這個檔案,將最終的修改結果保留到檔案中
  4. 再次提交merge,會在master上再增長一個版本
    Markdown

在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
    • 具體配置方法,見說明
  • 別名
    Markdown
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 */

Markdown

  • 配置資訊作用域
    • 有–global的,使用者域有效
    • 沒有–global的,倉庫域有效
    • 具體反映在不同層級目錄的.git/config

3.8 自己搭建Git伺服器

  1. 使用ubuntu或者debian系統的電腦
  2. 安裝git
  3. 建立一個名位git的使用者,執行git服務

    sudo addusr git
  4. 蒐集公鑰,每行一個寫入

    /home/git/.ssh/authorized_keys
  5. 建立裸倉,倉庫目錄下執行

    sudo git init --bare <repo name>.git
    sudo chown -R git:git sample.git
  6. 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配置

上傳公鑰
Markdown
可以上傳多個公鑰,不同的電腦各生成一個,關聯到同一個賬戶

4.2 遠端倉庫操作

4.2.1 關聯

首先在Github上建立新的repository,然後在本地目錄下通過下面命令,關聯遠端倉庫到當前資料夾:

git remote add origin [email protected].com:[username]/[repository].git

其中[email protected]:xxx,是在github的repository頁面找到的地址:
Markdown
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

第一次推送,會有提示,需要確認以下對端是否可信
Markdown

4.2 倉庫間關係

github上,協作的工程有它的原是倉庫,參與的人自己fork一份自己的倉庫,在自己的倉庫上修改。
Markdown

4.1 使用步驟

  1. 找到專案頁面
  2. 點fork複製到自己的頁面
    Markdown
  3. git clone到本地
  4. 提交修改到自己的github倉庫
  5. 提出pull request,發給專案原始頁面,建議其包含這個修改