Git 簡單使用學習筆記

根本停不下來發表於2018-08-28

Git基本使用

安裝 Git

首先,在終端輸入git,看看系統有沒有安裝 Git:

  • 如果已經安裝過了,它會向你介紹 git 相關的命令
  • 如果沒有安裝,它會告訴你沒有安裝

Linux 與 Windows 安裝方式
在 Mac 上進行開發,如果安裝了 Xcode,Git 也會被自動安裝。

安裝完成之後,需要最後一步設定:

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
複製程式碼

因為 Git 是分散式版本控制系統,所以,每個機器都必須自報家門:名字和 Email 地址。

注意 git config 命令的 --global 引數,用了這個引數,表示你這臺機器上所有的 Git 倉庫都會使用這個配置,當然也可以對某個倉庫指定不同的使用者名稱和 Email 地址。

建立版本庫/倉庫/repository

使用 git init 命定把當前目錄變成 Git 可以管理的倉庫。

$ git init
Initialized empty Git repository in /Users/momo/Desktop/Git測試/.git/
複製程式碼

這就已經建立好了,並且當前目錄下多了一個 .git 的目錄,這個目錄是 Git 來跟蹤管理版本庫的。

把檔案新增到版本庫

  1. 使用命令 git add <file>,注意,可以反覆多次使用,新增多個檔案;
  2. 使用命令 git commit -m <message>,完成。

檢視倉庫的狀態

使用 git status 可以檢視工作區的狀態

  • 新建、刪除、修改了哪些檔案
  • 這些檔案的狀態:not staged for commit 或者 to be committed
  • 還會顯示未被追蹤的檔案 Untracked files

使用 git diff 可以檢視檔案具體的修改內容

檢視提交日誌

git log
git log --pretty=oneline

$ git log --pretty=oneline
8a26a5c6c62bb485d0a1dbed9c5d5d7de74a8964 (HEAD -> master) 刪除了檔案
59c61e6748783590b4d430de11edad75cfc2b637 修改了檔名
fd131b631e8938379b93ee1ba2f675714efdcfae 新增了一個檔案
複製程式碼

每一行前面的一大串字元是 commit id (版本號)。

版本回退

在 Git 中,用 HEAD 表示當前版本,上一個版本是 HEAD^,上上一個版本是 HEAD^^,如果往上 100 個版本的話,可以寫成 HEAD~100

回退到上一個版本

$ git reset --hard HEAD^
HEAD is now at 59c61e6 修改了檔名
複製程式碼

去某一個版本

$ git reset --hard 8a26a
HEAD is now at 8a26a5c 刪除了檔案
複製程式碼

版本號沒必要寫全,前幾位就可以了,Git 會自動去找。

檢視版本號

使用 git log 可以檢視之前的提交記錄以及版本號。
如果已經回退到了之前的某個版本,這時候如果使用 git log 就不能看到當前版本之後的提交的版本號了。

這時如果想返回到之後的版本,可以使用 git reflog 檢視命令歷史,以確定版本號。

工作區與暫存區

工作區 (Working Directory)
之前使用了 git init 來把當前目錄變成了 Git 可以管理的倉庫。
當前目錄就是一個工作區。

版本庫 (Repository)
工作區有一個隱藏目錄 .git,這個不算工作區,而是 Git 的版本庫。

Git 的版本庫裡存了跟多東西,其中最重要的就是成為 stage (或者叫做 index) 的暫存區,還有 Git 為我們自動建立的第一個分支 master,以及指向 master 的一個指標叫 HEAD

Git 簡單使用學習筆記

在把工作區的檔案新增到 Git 版本庫中時需要兩步:

  • git add 把檔案修改新增到暫存區
  • git commit 把暫存區的所有內容提交到當前分支

撤銷修改

當你亂改了工作區某個檔案的內容時,想直接丟棄工作區的修改,可以使用 git checkout -- file。這個命令其實就是用版本庫裡的版本替換工作區的版本,無論工作區中是修改還是刪除檔案,都可以"一鍵還原"。命令中--很重要,如果去掉了 -- 就成了切換分支的命令了。

當你亂改了工作區的某個檔案內容,並且提交到了暫存區,想丟棄修改,分兩步。
第一步用命令 git reset HEAD file 撤銷暫存區的修改。完成之後可以用 git status 檢視一下狀態。
第二部用用上邊提到的 git checkout -- file 來丟棄工作區的修改。

當你已經用 git commit 提交到版本庫時,想要撤銷修改,可以回退版本。

刪除檔案

假設有一個已經被 Git 追蹤的檔案 test.txt。

$ ls
test.txt
複製程式碼

現在刪除它

$ rm test.txt
複製程式碼

這時檢視倉庫狀態

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	deleted:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")
複製程式碼

這個時候有兩種選擇

  • 使用 git checkout -- file 放棄修改,檔案會還原
  • 使用 git add file 或者 git rm file 都可以將"刪除"提交到暫存區,然後可以檢視暫存區的狀態,再使用 git commit 提交到版本庫。這樣工作區和版本庫裡面的檔案就都被刪除了。

建立與合併分支

每次提交,Git 都把它們串成一條時間線,這條時間線就是一條分支。一開始的時候,只有一條 master 分支。

HEAD 嚴格來講不是指向提交的,而是指向當前分支,現在是 master
master 是指向當前提交的。每次提交 master 就會向前移動一步。

Git 簡單使用學習筆記

建立新分支的時候,比如 dev,Git 新建了一個指標 dev,指向 master 相同的提交。切換分支的時候,Git 再把 HEAD 指向 dev

Git 簡單使用學習筆記
Git 建立新分支就是增加一個新的指標。

現在每次提交時,dev 就會往前移動,而 master 不變。

Git 簡單使用學習筆記

dev 上的工作完成之後,就可以把 dev 合併到 master 上了。當前這種情況,Git 會直接把 master 指向 dev 的當前提交,就完成了合併:

Git 簡單使用學習筆記

合併完成之後,可以刪除 dev 分支。刪除 dev 分支就是把 dev 指標刪掉。

Git 簡單使用學習筆記

檢視當前分支:

$ git branch
複製程式碼

建立分支:

$ git checkout 分支名稱
複製程式碼

切換分支:

$ git branch 分支名稱
複製程式碼

建立並切換分支:

$ git checkout -b 分支名稱
複製程式碼

合併指定分支到當前分支:

$ git merge 指定分支名稱
複製程式碼

刪除分支:

$ git branch -d 分支名稱
複製程式碼

Fast-forward 快進模式:
之前做的合併操作就是快進模式,直接把 master 指向 dev 的當前提交,所以合併速度非常快。除了這種模式,還有其它的合併方式。

解決衝突

當兩條分支都提交了修改時,這時候合併就不是快進模式了,它只能試圖把各自的修改合併起來。
如果兩條分支都修改了同一處,那麼它就會不知道應該改採用哪個分支的修改,這就是衝突。

$ git merge dev
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
複製程式碼

這段命令試圖將 dev 合併到 master,但是產生了衝突,Git 提示我在 test.txt 檔案中有衝突。

使用 git status 檢視工作區的狀態,它也告訴我衝突的檔案:

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:   test.txt

no changes added to commit (use "git add" and/or "git commit -a")
複製程式碼

檢視 test.txt 檔案的內容:

$ cat test.txt 
1
<<<<<<< HEAD
3
4
=======
2
3
>>>>>>> dev

複製程式碼

可以看到,test.txt 檔案中本來只有第一行寫的是 1
master 分支上新增了 3、4 並做了提交。
dev 分支上新增了 2、3 並做了提交。

git merge dev 之後,Git 把 dev 分支的 test.txt 檔案合併到了 master 分支的 test.txt 檔案。並且標記出了有衝突的地方。

手動修改 test.txt 處理衝突後,使用 git addgit commit 進行提交,這樣整個合併過程才算是完成。

如果合併的過程中沒有出現衝突,那麼 Git 會提示我們輸入 message,輸入完成之後已經合併成功了。

使用 git log --graph 命令也可以檢視分支合併的情況:

$ git log --pretty=oneline --graph --abbrev-commit
*   5403d91 (HEAD -> master) Merge branch 'dev'
|\  
| * 4f86c6a (dev) dev commit 3
* |   0372da4 master merge from dev 2
|\ \  
| |/  
| * cd070ad dev commit 2
* |   c746cc7 master merge from dev
|\ \  
| |/  
| * 794d56a dev commit 1
* | cfe77bc master commit 2
|/  
* 7bca0cd master commit 1
複製程式碼

從下往上看:

  • 我先在 master 上做了一次提交,master commit 1。
  • 建立並切換到了 dev 分支。
  • 切換回 master 分支。在 master 上修改 test.txt 並提交,master commit 2。
  • 切換到 dev,修改 test.txt 並提交,dev commit 1。
  • 切換到 master,開始合併分支 -> 遇到衝突 -> 修改檔案處理衝突 -> 提交 -> 合併完成,master merge from dev。
  • 切換到 dev,修改提交,dev commit 2。
  • 切換到 master,合併分支,master commit merge from dev 2。
  • 切換到 dev ,修改提交,dev commit 3。
  • 切換回 master,合併,Merge branch 'dev'。

分支管理策略

合併分支時,如果可能,Git 會使用 Fast forward 模式,但這種模式下,刪除分之後,會丟失掉分支的資訊。

可以通過 --no-ff 強制禁用 Fast forward 模式,這樣 Git 就會在 merge 時產生一個新的 commit,這樣從分支歷史上就可以看出分支資訊。例如:

$ git merge --no-ff -m "merge with no-ff" dev
複製程式碼

合併分支時,快進模式下沒有產生提交,所以不用輸入資訊。非快進模式下的合併,產生了一次提交,用 -m 輸入提交資訊。

合併之後的圖就像這樣:

Git 簡單使用學習筆記

在實際開發中:
master 分支應該是非常穩定的,僅用來發布新版本,平時不能在上面幹活。
幹活都在 dev 分支上,dev 分支時不穩定的,到某個時候,比如 1.0 版本釋出時,再把 dev 分支合併到 master 上,在 master 分支釋出 1.0 版本;
小夥伴們在 dev 分支上幹活,每個人都有自己的分支,時不時地往 dev 分支上合併就可以了。
所以,團隊協作的分支看起來就像這樣:

Git 簡單使用學習筆記

Bug 分支

當線上出現 bug 需要即刻修復時。可以切換到 master,在建立分支 bug_101,在分支上解決完 bug 之後合併到 master 上,然後刪除 bug_101 分支。

在切換分支分支的時候,如果當前分支上還存在沒有提交的修改,那麼是不能進行切換分支的。但是現在工作只進行到了一半,還沒辦法提交,這時可以使用 stash 功能,可以把當前工作縣城 "儲藏" 起來,等以後恢復現場後繼續工作:

$ git stash
複製程式碼
$ git stash pop
複製程式碼

新功能分支

當開發一個新功能的時候,最好也建立一個新的分支。

如果要強制刪除一個沒有被合併過的分支,可以使用 git branch -D <name>

遠端倉庫

SSH Key

本地的 Git 倉庫和遠端庫之間的傳輸一半都是通過 SSH 加密的,所以需要設定 SSH Key。

第 1 步:建立 SSH Key。在使用者主目錄下,看看有沒有 .ssh 目錄,再看看這個目錄下有沒有 id_rsaid_rsa.pub 這兩個檔案,如果已經有了,可以直接跳到下一步。如果沒有,建立 SSH Key:

$ ssh-keygen -t rsa -C youremail@example.com
複製程式碼

把郵件替換成自己的郵件地址,一路回車即可,這裡無需設定密碼。
完成之後就可以在 ~/.ssh 中看到 i_rsa 和 id_rsa.pub 這兩個檔案。這就是 SSH Key 的金鑰對,id_rsa 是私鑰,id_rsa.pub 是公鑰,可以放心地告訴任何人。

第 2 步:在遠端網站上找到設定SSH Key的頁面,將 id_rsa.pub 檔案中的內容粘進去即可。

為什麼遠端網站需要 SSH Key呢?
因為遠端網站需要識別出你推送的提交確實是你推送的,而不是別人冒充的,而 Git 支援 SSH 協議,所以,它只要知道了你的公鑰,就可以確認只有你自己才能推送。
當然,也可以在網站新增多個公鑰,這樣就可以了使用多個電腦推送了。

關聯遠端倉庫

先有本地倉庫

假設現在已經有了一個本地倉庫,又想建立一個遠端倉庫,並且這兩個倉庫可以同步,可以這樣做:

第 1 步:先建立一個空的遠端倉庫,然後在本地倉庫目錄下執行命令:

$ git remote add origin git@github.com:遠端倉庫名稱
複製程式碼

執行後遠端倉庫的名稱就是 origin,這也是 Git 預設的叫法,也可以改成別的。
這樣 orign 就與我們的本地倉庫關聯起來了。

第 2 步:現在我們就可以把本地倉庫的所有內容推送到遠端庫上:

$ git push -u origin master
複製程式碼

把本地庫的內容推送到遠端,用 git push 命令,實際上是把當前分支 master 推送到遠端。

由於遠端庫是空的,所以第一次推送 master 分支時,加上了 -u 引數,Git 不但會把本地的 master 分支內容推送的遠端新的 master 分支,還會把本地的 master分支和遠端的 master 分支關聯起來,在以後的推送或者拉取時就可以簡化命令。

第 3 步:以後本地提交之後,就可以使用:

$ git push origin master
複製程式碼

把本地 master 分支的最新修改推送至 origin。

先有遠端倉庫

如果從零開發的話,最好的方式是先建立遠端庫,然後,從遠端庫克隆。使用 git clone 命令即可。

$ git clone 遠端倉庫給的地址
複製程式碼

這樣就可以把遠端倉庫克隆到本地,並且它們相關聯。

多人協作

當從遠端倉庫克隆的時候,實際上 Git 自動把本地的 master 分支和遠端的 master 分支對應起來了,並且,遠端倉庫的預設名稱是 origin

要檢視遠端庫的資訊,用 git remote,用 git remote -v 可以顯示更詳細的資訊:會顯示可以抓取和推送的origin的地址。如果沒有推送許可權,就看不到 push 的地址。

推送分支

推送分支就是把該分支上所有本地提交推送到遠端庫。推送時,要指定本地分支,這樣,Git 就會把該分支推送到遠端庫對應的遠端分支上:

$ git push origin 分支名稱
複製程式碼

抓取分支

在開發時,我們會是不是向遠端分支推送新的提交。如果在推送的時候,別人也碰巧修改了這裡,那麼就會產生衝突,推送失敗。

解決的辦法也很簡單,先用 git pull 把最新的提交從抓下來,與本地的分支合併,解決衝突後再推送。

更詳細的說明點這裡

參考文章

Git教程
git

相關文章